Merge pull request #17599 from BruceForstall/CleanupUbunuArmBuildMachine_2.1
[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 #ifdef DEBUG
7361         if (emitComp->verbose)
7362         {
7363             printf("NOGC Call: savedSet=");
7364             printRegMaskInt(savedSet);
7365             emitDispRegSet(savedSet);
7366             printf("\n");
7367         }
7368 #endif
7369     }
7370     else
7371     {
7372         assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7373     }
7374
7375     /* Trim out any callee-trashed registers from the live set */
7376
7377     gcrefRegs &= savedSet;
7378     byrefRegs &= savedSet;
7379
7380 #ifdef DEBUG
7381     if (EMIT_GC_VERBOSE)
7382     {
7383         printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7384         dumpConvertedVarSet(emitComp, ptrVars);
7385         printf(", gcrefRegs=");
7386         printRegMaskInt(gcrefRegs);
7387         emitDispRegSet(gcrefRegs);
7388         printf(", byrefRegs=");
7389         printRegMaskInt(byrefRegs);
7390         emitDispRegSet(byrefRegs);
7391         printf("\n");
7392     }
7393 #endif
7394
7395     assert(argSize % REGSIZE_BYTES == 0);
7396     argCnt = (int)(argSize / (int)REGSIZE_BYTES);
7397
7398     /* Managed RetVal: emit sequence point for the call */
7399     if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7400     {
7401         codeGen->genIPmappingAdd(ilOffset, false);
7402     }
7403
7404     /*
7405         We need to allocate the appropriate instruction descriptor based
7406         on whether this is a direct/indirect call, and whether we need to
7407         record an updated set of live GC variables.
7408      */
7409
7410     if (callType >= EC_INDIR_R)
7411     {
7412         /* Indirect call, virtual calls */
7413
7414         assert(callType == EC_INDIR_R);
7415
7416         id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7417     }
7418     else
7419     {
7420         /* Helper/static/nonvirtual/function calls (direct or through handle),
7421            and calls to an absolute addr. */
7422
7423         assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7424
7425         id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7426     }
7427
7428     /* Update the emitter's live GC ref sets */
7429
7430     VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7431     emitThisGCrefRegs = gcrefRegs;
7432     emitThisByrefRegs = byrefRegs;
7433
7434     /* Set the instruction - special case jumping a function */
7435     instruction ins;
7436     insFormat   fmt = IF_NONE;
7437
7438     id->idSetIsNoGC(isNoGC);
7439
7440     /* Record the address: method, indirection, or funcptr */
7441
7442     if (callType > EC_FUNC_ADDR)
7443     {
7444         /* This is an indirect call (either a virtual call or func ptr call) */
7445
7446         switch (callType)
7447         {
7448             case EC_INDIR_R: // the address is in a register
7449
7450                 id->idSetIsCallRegPtr();
7451
7452                 if (isJump)
7453                 {
7454                     ins = INS_br_tail; // INS_br_tail  Reg
7455                 }
7456                 else
7457                 {
7458                     ins = INS_blr; // INS_blr Reg
7459                 }
7460                 fmt = IF_BR_1B;
7461
7462                 id->idIns(ins);
7463                 id->idInsFmt(fmt);
7464
7465                 id->idReg3(ireg);
7466                 assert(xreg == REG_NA);
7467                 break;
7468
7469             default:
7470                 NO_WAY("unexpected instruction");
7471                 break;
7472         }
7473     }
7474     else
7475     {
7476         /* This is a simple direct call: "call helper/method/addr" */
7477
7478         assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7479
7480         assert(addr != NULL);
7481
7482         if (isJump)
7483         {
7484             ins = INS_b_tail; // INS_b_tail imm28
7485         }
7486         else
7487         {
7488             ins = INS_bl; // INS_bl imm28
7489         }
7490         fmt = IF_BI_0C;
7491
7492         id->idIns(ins);
7493         id->idInsFmt(fmt);
7494
7495         id->idAddr()->iiaAddr = (BYTE*)addr;
7496
7497         if (callType == EC_FUNC_ADDR)
7498         {
7499             id->idSetIsCallAddr();
7500         }
7501
7502         if (emitComp->opts.compReloc)
7503         {
7504             id->idSetIsDspReloc();
7505         }
7506     }
7507
7508 #ifdef DEBUG
7509     if (EMIT_GC_VERBOSE)
7510     {
7511         if (id->idIsLargeCall())
7512         {
7513             printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7514                    VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7515         }
7516     }
7517
7518     id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7519     id->idDebugOnlyInfo()->idCallSig   = sigInfo;
7520 #endif // DEBUG
7521
7522 #ifdef LATE_DISASM
7523     if (addr != nullptr)
7524     {
7525         codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7526     }
7527 #endif // LATE_DISASM
7528
7529     dispIns(id);
7530     appendToCurIG(id);
7531 }
7532
7533 /*****************************************************************************
7534  *
7535  *  Returns true if 'imm' is valid Cond encoding
7536  */
7537
7538 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7539 {
7540     // range check the ssize_t value, to make sure it is a small unsigned value
7541     // and that only the bits in the cfi.cond are set
7542     if ((imm < 0) || (imm > 0xF))
7543         return false;
7544
7545     condFlagsImm cfi;
7546     cfi.immCFVal = (unsigned)imm;
7547
7548     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7549 }
7550
7551 /*****************************************************************************
7552  *
7553  *  Returns true if 'imm' is valid Cond/Flags encoding
7554  */
7555
7556 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7557 {
7558     // range check the ssize_t value, to make sure it is a small unsigned value
7559     // and that only the bits in the cfi.cond or cfi.flags are set
7560     if ((imm < 0) || (imm > 0xFF))
7561         return false;
7562
7563     condFlagsImm cfi;
7564     cfi.immCFVal = (unsigned)imm;
7565
7566     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7567 }
7568
7569 /*****************************************************************************
7570  *
7571  *  Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7572  */
7573
7574 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7575 {
7576     // range check the ssize_t value, to make sure it is a small unsigned value
7577     // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7578     if ((imm < 0) || (imm > 0x1FFF))
7579         return false;
7580
7581     condFlagsImm cfi;
7582     cfi.immCFVal = (unsigned)imm;
7583
7584     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7585 }
7586
7587 /*****************************************************************************
7588  *
7589  *  Returns an encoding for the specified register used in the 'Rd' position
7590  */
7591
7592 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(regNumber reg)
7593 {
7594     assert(isIntegerRegister(reg));
7595     emitter::code_t ureg = (emitter::code_t)reg;
7596     assert((ureg >= 0) && (ureg <= 31));
7597     return ureg;
7598 }
7599
7600 /*****************************************************************************
7601  *
7602  *  Returns an encoding for the specified register used in the 'Rt' position
7603  */
7604
7605 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7606 {
7607     assert(isIntegerRegister(reg));
7608     emitter::code_t ureg = (emitter::code_t)reg;
7609     assert((ureg >= 0) && (ureg <= 31));
7610     return ureg;
7611 }
7612
7613 /*****************************************************************************
7614  *
7615  *  Returns an encoding for the specified register used in the 'Rn' position
7616  */
7617
7618 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7619 {
7620     assert(isIntegerRegister(reg));
7621     emitter::code_t ureg = (emitter::code_t)reg;
7622     assert((ureg >= 0) && (ureg <= 31));
7623     return ureg << 5;
7624 }
7625
7626 /*****************************************************************************
7627  *
7628  *  Returns an encoding for the specified register used in the 'Rm' position
7629  */
7630
7631 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7632 {
7633     assert(isIntegerRegister(reg));
7634     emitter::code_t ureg = (emitter::code_t)reg;
7635     assert((ureg >= 0) && (ureg <= 31));
7636     return ureg << 16;
7637 }
7638
7639 /*****************************************************************************
7640  *
7641  *  Returns an encoding for the specified register used in the 'Ra' position
7642  */
7643
7644 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(regNumber reg)
7645 {
7646     assert(isIntegerRegister(reg));
7647     emitter::code_t ureg = (emitter::code_t)reg;
7648     assert((ureg >= 0) && (ureg <= 31));
7649     return ureg << 10;
7650 }
7651
7652 /*****************************************************************************
7653  *
7654  *  Returns an encoding for the specified register used in the 'Vd' position
7655  */
7656
7657 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(regNumber reg)
7658 {
7659     assert(emitter::isVectorRegister(reg));
7660     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7661     assert((ureg >= 0) && (ureg <= 31));
7662     return ureg;
7663 }
7664
7665 /*****************************************************************************
7666  *
7667  *  Returns an encoding for the specified register used in the 'Vt' position
7668  */
7669
7670 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7671 {
7672     assert(emitter::isVectorRegister(reg));
7673     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7674     assert((ureg >= 0) && (ureg <= 31));
7675     return ureg;
7676 }
7677
7678 /*****************************************************************************
7679  *
7680  *  Returns an encoding for the specified register used in the 'Vn' position
7681  */
7682
7683 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7684 {
7685     assert(emitter::isVectorRegister(reg));
7686     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7687     assert((ureg >= 0) && (ureg <= 31));
7688     return ureg << 5;
7689 }
7690
7691 /*****************************************************************************
7692  *
7693  *  Returns an encoding for the specified register used in the 'Vm' position
7694  */
7695
7696 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7697 {
7698     assert(emitter::isVectorRegister(reg));
7699     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7700     assert((ureg >= 0) && (ureg <= 31));
7701     return ureg << 16;
7702 }
7703
7704 /*****************************************************************************
7705  *
7706  *  Returns an encoding for the specified register used in the 'Va' position
7707  */
7708
7709 /*static*/ emitter::code_t emitter::insEncodeReg_Va(regNumber reg)
7710 {
7711     assert(emitter::isVectorRegister(reg));
7712     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7713     assert((ureg >= 0) && (ureg <= 31));
7714     return ureg << 10;
7715 }
7716
7717 /*****************************************************************************
7718  *
7719  *  Returns an encoding for the specified condition code.
7720  */
7721
7722 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7723 {
7724     emitter::code_t uimm = (emitter::code_t)cond;
7725     return uimm << 12;
7726 }
7727
7728 /*****************************************************************************
7729  *
7730  *  Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7731  *  architecture manual).
7732  */
7733
7734 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7735 {
7736     emitter::code_t uimm = (emitter::code_t)cond;
7737     uimm ^= 1; // invert the lowest bit
7738     return uimm << 12;
7739 }
7740
7741 /*****************************************************************************
7742  *
7743  *  Returns an encoding for the specified flags.
7744  */
7745
7746 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7747 {
7748     emitter::code_t uimm = (emitter::code_t)flags;
7749     return uimm;
7750 }
7751
7752 /*****************************************************************************
7753  *
7754  *  Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7755  */
7756
7757 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7758 {
7759     assert((imm & 0x003F) == imm);
7760     assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7761
7762     return (emitter::code_t)imm << 10;
7763 }
7764
7765 /*****************************************************************************
7766  *
7767  *  Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7768  */
7769
7770 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7771 {
7772     if (size == EA_8BYTE)
7773     {
7774         return 0x80000000; // set the bit at location 31
7775     }
7776     else
7777     {
7778         assert(size == EA_4BYTE);
7779         return 0;
7780     }
7781 }
7782
7783 /*****************************************************************************
7784  *
7785  *  Returns the encoding to select the datasize for the general load/store Arm64 instructions
7786  *
7787  */
7788
7789 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7790 {
7791     bool exclusive = ((code & 0x35000000) == 0);
7792
7793     if ((code & 0x00800000) && !exclusive) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7794     {
7795         if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7796         {
7797             if (EA_SIZE(size) != EA_8BYTE) // Do we need to encode the 32-bit Rt size bit?
7798             {
7799                 return 0x00400000; // set the bit at location 22
7800             }
7801         }
7802     }
7803     else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7804     {
7805         if (EA_SIZE(size) == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7806         {
7807             return 0x40000000; // set the bit at location 30
7808         }
7809     }
7810     return 0;
7811 }
7812
7813 /*****************************************************************************
7814  *
7815  *  Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7816  *
7817  */
7818
7819 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7820 {
7821     code_t result = 0;
7822
7823     // Check bit 29
7824     if ((code & 0x20000000) == 0)
7825     {
7826         // LDR literal
7827
7828         if (size == EA_16BYTE)
7829         {
7830             // set the operation size in bit 31
7831             result = 0x80000000;
7832         }
7833         else if (size == EA_8BYTE)
7834         {
7835             // set the operation size in bit 30
7836             result = 0x40000000;
7837         }
7838         else
7839         {
7840             assert(size == EA_4BYTE);
7841             // no bits are set
7842             result = 0x00000000;
7843         }
7844     }
7845     else
7846     {
7847         // LDR non-literal
7848
7849         if (size == EA_16BYTE)
7850         {
7851             // The operation size in bits 31 and 30 are zero
7852             // Bit 23 specifies a 128-bit Load/Store
7853             result = 0x00800000;
7854         }
7855         else if (size == EA_8BYTE)
7856         {
7857             // set the operation size in bits 31 and 30
7858             result = 0xC0000000;
7859         }
7860         else if (size == EA_4BYTE)
7861         {
7862             // set the operation size in bit 31
7863             result = 0x80000000;
7864         }
7865         else if (size == EA_2BYTE)
7866         {
7867             // set the operation size in bit 30
7868             result = 0x40000000;
7869         }
7870         else
7871         {
7872             assert(size == EA_1BYTE);
7873             // The operation size in bits 31 and 30 are zero
7874             result = 0x00000000;
7875         }
7876     }
7877
7878     // Or in bit 26 to indicate a Vector register is used as 'target'
7879     result |= 0x04000000;
7880
7881     return result;
7882 }
7883
7884 /*****************************************************************************
7885  *
7886  *  Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7887  *
7888  */
7889
7890 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7891 {
7892     code_t result = 0;
7893
7894     if (size == EA_16BYTE)
7895     {
7896         // The operation size in bits 31 and 30 are zero
7897         // Bit 23 specifies a 128-bit Load/Store
7898         result = 0x80000000;
7899     }
7900     else if (size == EA_8BYTE)
7901     {
7902         // set the operation size in bits 31 and 30
7903         result = 0x40000000;
7904     }
7905     else if (size == EA_4BYTE)
7906     {
7907         // set the operation size in bit 31
7908         result = 0x00000000;
7909     }
7910
7911     // Or in bit 26 to indicate a Vector register is used as 'target'
7912     result |= 0x04000000;
7913
7914     return result;
7915 }
7916
7917 /*****************************************************************************
7918  *
7919  *  Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
7920  *
7921  */
7922
7923 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
7924 {
7925     // is bit 30 equal to 0?
7926     if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
7927     {
7928         if (size == EA_8BYTE) // Do we need to set the sf and N bits?
7929         {
7930             return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
7931         }
7932     }
7933     return 0; // don't set any bits
7934 }
7935
7936 /*****************************************************************************
7937  *
7938  *  Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
7939  */
7940
7941 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
7942 {
7943     if (size == EA_16BYTE)
7944     {
7945         return 0x40000000; // set the bit at location 30
7946     }
7947     else
7948     {
7949         assert(size == EA_8BYTE);
7950         return 0;
7951     }
7952 }
7953
7954 /*****************************************************************************
7955  *
7956  *  Returns the encoding to select 'index' for an Arm64 vector elem instruction
7957  */
7958 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
7959 {
7960     code_t bits = (code_t)index;
7961     if (elemsize == EA_1BYTE)
7962     {
7963         bits <<= 1;
7964         bits |= 1;
7965     }
7966     else if (elemsize == EA_2BYTE)
7967     {
7968         bits <<= 2;
7969         bits |= 2;
7970     }
7971     else if (elemsize == EA_4BYTE)
7972     {
7973         bits <<= 3;
7974         bits |= 4;
7975     }
7976     else
7977     {
7978         assert(elemsize == EA_8BYTE);
7979         bits <<= 4;
7980         bits |= 8;
7981     }
7982     assert((bits >= 1) && (bits <= 0x1f));
7983
7984     return (bits << 16); // bits at locations [20,19,18,17,16]
7985 }
7986
7987 /*****************************************************************************
7988  *
7989  *  Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
7990  */
7991 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
7992 {
7993     code_t bits = (code_t)index2;
7994     if (elemsize == EA_1BYTE)
7995     {
7996         // bits are correct
7997     }
7998     else if (elemsize == EA_2BYTE)
7999     {
8000         bits <<= 1;
8001     }
8002     else if (elemsize == EA_4BYTE)
8003     {
8004         bits <<= 2;
8005     }
8006     else
8007     {
8008         assert(elemsize == EA_8BYTE);
8009         bits <<= 3;
8010     }
8011     assert((bits >= 0) && (bits <= 0xf));
8012
8013     return (bits << 11); // bits at locations [14,13,12,11]
8014 }
8015
8016 /*****************************************************************************
8017  *
8018  *  Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
8019  */
8020 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
8021 {
8022     code_t bits = 0;
8023
8024     if (elemsize == EA_2BYTE)
8025     {
8026         assert((index >= 0) && (index <= 7));
8027         if (index & 0x4)
8028         {
8029             bits |= (1 << 11); // set bit 11 'H'
8030         }
8031         if (index & 0x2)
8032         {
8033             bits |= (1 << 21); // set bit 21 'L'
8034         }
8035         if (index & 0x1)
8036         {
8037             bits |= (1 << 20); // set bit 20 'M'
8038         }
8039     }
8040     else if (elemsize == EA_4BYTE)
8041     {
8042         assert((index >= 0) && (index <= 3));
8043         if (index & 0x2)
8044         {
8045             bits |= (1 << 11); // set bit 11 'H'
8046         }
8047         if (index & 0x1)
8048         {
8049             bits |= (1 << 21); // set bit 21 'L'
8050         }
8051     }
8052     else
8053     {
8054         assert(!"Invalid 'elemsize' value");
8055     }
8056
8057     return bits;
8058 }
8059
8060 /*****************************************************************************
8061  *
8062  *   Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
8063  */
8064
8065 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
8066 {
8067     assert(shift < getBitWidth(size));
8068
8069     code_t imm = (code_t)(getBitWidth(size) + shift);
8070
8071     return imm << 16;
8072 }
8073
8074 /*****************************************************************************
8075  *
8076  *  Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
8077  */
8078
8079 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
8080 {
8081     if (size == EA_8BYTE)
8082     {
8083         return 0x00C00000; // set the bit at location 23 and 22
8084     }
8085     else if (size == EA_4BYTE)
8086     {
8087         return 0x00800000; // set the bit at location 23
8088     }
8089     else if (size == EA_2BYTE)
8090     {
8091         return 0x00400000; // set the bit at location 22
8092     }
8093     assert(size == EA_1BYTE);
8094     return 0x00000000;
8095 }
8096
8097 /*****************************************************************************
8098  *
8099  *  Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
8100  */
8101
8102 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
8103 {
8104     if (size == EA_8BYTE)
8105     {
8106         return 0x00400000; // set the bit at location 22
8107     }
8108     assert(size == EA_4BYTE);
8109     return 0x00000000;
8110 }
8111
8112 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
8113 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
8114 {
8115     code_t result = 0x00000000;
8116     if (elemsize == EA_8BYTE)
8117     {
8118         assert((index >= 0) && (index <= 1));
8119         if (index == 1)
8120         {
8121             result |= 0x00000800; // 'H' - set the bit at location 11
8122         }
8123     }
8124     else
8125     {
8126         assert(elemsize == EA_4BYTE);
8127         assert((index >= 0) && (index <= 3));
8128         if (index & 2)
8129         {
8130             result |= 0x00000800; // 'H' - set the bit at location 11
8131         }
8132         if (index & 1)
8133         {
8134             result |= 0x00200000; // 'L' - set the bit at location 21
8135         }
8136     }
8137     return result;
8138 }
8139
8140 /*****************************************************************************
8141  *
8142  *  Returns the encoding to select the fcvt operation for Arm64 instructions
8143  */
8144 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8145 {
8146     code_t result = 0;
8147     switch (conversion)
8148     {
8149         case INS_OPTS_S_TO_D: // Single to Double
8150             assert(fmt == IF_DV_2J);
8151             result = 0x00008000; // type=00, opc=01
8152             break;
8153
8154         case INS_OPTS_D_TO_S: // Double to Single
8155             assert(fmt == IF_DV_2J);
8156             result = 0x00400000; // type=01, opc=00
8157             break;
8158
8159         case INS_OPTS_H_TO_S: // Half to Single
8160             assert(fmt == IF_DV_2J);
8161             result = 0x00C00000; // type=11, opc=00
8162             break;
8163
8164         case INS_OPTS_H_TO_D: // Half to Double
8165             assert(fmt == IF_DV_2J);
8166             result = 0x00C08000; // type=11, opc=01
8167             break;
8168
8169         case INS_OPTS_S_TO_H: // Single to Half
8170             assert(fmt == IF_DV_2J);
8171             result = 0x00018000; // type=00, opc=11
8172             break;
8173
8174         case INS_OPTS_D_TO_H: // Double to Half
8175             assert(fmt == IF_DV_2J);
8176             result = 0x00418000; // type=01, opc=11
8177             break;
8178
8179         case INS_OPTS_S_TO_4BYTE: // Single to INT32
8180             assert(fmt == IF_DV_2H);
8181             result = 0x00000000; // sf=0, type=00
8182             break;
8183
8184         case INS_OPTS_D_TO_4BYTE: // Double to INT32
8185             assert(fmt == IF_DV_2H);
8186             result = 0x00400000; // sf=0, type=01
8187             break;
8188
8189         case INS_OPTS_S_TO_8BYTE: // Single to INT64
8190             assert(fmt == IF_DV_2H);
8191             result = 0x80000000; // sf=1, type=00
8192             break;
8193
8194         case INS_OPTS_D_TO_8BYTE: // Double to INT64
8195             assert(fmt == IF_DV_2H);
8196             result = 0x80400000; // sf=1, type=01
8197             break;
8198
8199         case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8200             assert(fmt == IF_DV_2I);
8201             result = 0x00000000; // sf=0, type=00
8202             break;
8203
8204         case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8205             assert(fmt == IF_DV_2I);
8206             result = 0x00400000; // sf=0, type=01
8207             break;
8208
8209         case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8210             assert(fmt == IF_DV_2I);
8211             result = 0x80000000; // sf=1, type=00
8212             break;
8213
8214         case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8215             assert(fmt == IF_DV_2I);
8216             result = 0x80400000; // sf=1, type=01
8217             break;
8218
8219         default:
8220             assert(!"Invalid 'conversion' value");
8221             break;
8222     }
8223     return result;
8224 }
8225
8226 /*****************************************************************************
8227  *
8228  *  Returns the encoding to have the Rn register be updated Pre/Post indexed
8229  *  or not updated
8230  */
8231
8232 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8233 {
8234     assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8235
8236     if (emitter::insOptsIndexed(opt))
8237     {
8238         if (emitter::insOptsPostIndex(opt))
8239         {
8240             return 0x00000400; // set the bit at location 10
8241         }
8242         else
8243         {
8244             assert(emitter::insOptsPreIndex(opt));
8245             return 0x00000C00; // set the bit at location 10 and 11
8246         }
8247     }
8248     else
8249     {
8250         assert(emitter::insOptsNone(opt));
8251         return 0; // bits 10 and 11 are zero
8252     }
8253 }
8254
8255 /*****************************************************************************
8256  *
8257  *  Returns the encoding for a ldp/stp instruction to have the Rn register
8258  *  be updated Pre/Post indexed or not updated
8259  */
8260
8261 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8262 {
8263     assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8264
8265     if ((ins == INS_ldnp) || (ins == INS_stnp))
8266     {
8267         assert(emitter::insOptsNone(opt));
8268         return 0; // bits 23 and 24 are zero
8269     }
8270     else
8271     {
8272         if (emitter::insOptsIndexed(opt))
8273         {
8274             if (emitter::insOptsPostIndex(opt))
8275             {
8276                 return 0x00800000; // set the bit at location 23
8277             }
8278             else
8279             {
8280                 assert(emitter::insOptsPreIndex(opt));
8281                 return 0x01800000; // set the bit at location 24 and 23
8282             }
8283         }
8284         else
8285         {
8286             assert(emitter::insOptsNone(opt));
8287             return 0x01000000; // set the bit at location 24
8288         }
8289     }
8290 }
8291
8292 /*****************************************************************************
8293  *
8294  *  Returns the encoding to apply a Shift Type on the Rm register
8295  */
8296
8297 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8298 {
8299     if (emitter::insOptsNone(opt))
8300     {
8301         // None implies the we encode LSL (with a zero immediate)
8302         opt = INS_OPTS_LSL;
8303     }
8304     assert(emitter::insOptsAnyShift(opt));
8305
8306     emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8307     assert(option <= 3);
8308
8309     return option << 22; // bits 23, 22
8310 }
8311
8312 /*****************************************************************************
8313  *
8314  *  Returns the encoding to apply a 12 bit left shift to the immediate
8315  */
8316
8317 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8318 {
8319     if (emitter::insOptsLSL12(opt))
8320     {
8321         return 0x00400000; // set the bit at location 22
8322     }
8323     return 0;
8324 }
8325
8326 /*****************************************************************************
8327  *
8328  *  Returns the encoding to have the Rm register use an extend operation
8329  */
8330
8331 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8332 {
8333     if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8334     {
8335         // None or LSL implies the we encode UXTX
8336         opt = INS_OPTS_UXTX;
8337     }
8338     assert(emitter::insOptsAnyExtend(opt));
8339
8340     emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8341     assert(option <= 7);
8342
8343     return option << 13; // bits 15,14,13
8344 }
8345
8346 /*****************************************************************************
8347  *
8348  *  Returns the encoding to scale the Rm register by {0,1,2,3,4}
8349  *  when using an extend operation
8350  */
8351
8352 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8353 {
8354     assert((imm >= 0) && (imm <= 4));
8355
8356     return (emitter::code_t)imm << 10; // bits 12,11,10
8357 }
8358
8359 /*****************************************************************************
8360  *
8361  *  Returns the encoding to have the Rm register be auto scaled by the ld/st size
8362  */
8363
8364 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8365 {
8366     if (isScaled)
8367     {
8368         return 0x00001000; // set the bit at location 12
8369     }
8370     else
8371     {
8372         return 0;
8373     }
8374 }
8375
8376 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8377 {
8378     instruction ins    = id->idIns();
8379     insFormat   fmt    = id->idInsFmt();
8380     regNumber   dstReg = id->idReg1();
8381     if (id->idjShort)
8382     {
8383         // adr x, [rel addr] --  compute address: current addr(ip) + rel addr.
8384         assert(ins == INS_adr);
8385         assert(fmt == IF_DI_1E);
8386         ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8387         dst             = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8388     }
8389     else
8390     {
8391         // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8392         assert(fmt == IF_LARGEADR);
8393         ssize_t relPageAddr =
8394             (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8395         dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8396
8397         // add x, x, page offs -- compute address = page addr + page offs
8398         ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8399         assert(isValidUimm12(imm12));
8400         code_t code =
8401             emitInsCode(INS_add, IF_DI_2A);  // DI_2A  X0010001shiiiiii iiiiiinnnnnddddd   1100 0000   imm(i12, sh)
8402         code |= insEncodeDatasize(EA_8BYTE); // X
8403         code |= ((code_t)imm12 << 10);       // iiiiiiiiiiii
8404         code |= insEncodeReg_Rd(dstReg);     // ddddd
8405         code |= insEncodeReg_Rn(dstReg);     // nnnnn
8406         dst += emitOutput_Instr(dst, code);
8407     }
8408     return dst;
8409 }
8410
8411 /*****************************************************************************
8412  *
8413  *  Output a local jump or other instruction with a pc-relative immediate.
8414  *  Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8415  *  to handle forward branch patching.
8416  */
8417
8418 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8419 {
8420     instrDescJmp* id = (instrDescJmp*)i;
8421
8422     unsigned srcOffs;
8423     unsigned dstOffs;
8424     BYTE*    srcAddr;
8425     BYTE*    dstAddr;
8426     ssize_t  distVal;
8427     ssize_t  loBits;
8428
8429     // Set default ins/fmt from id.
8430     instruction ins = id->idIns();
8431     insFormat   fmt = id->idInsFmt();
8432
8433     bool loadLabel    = false;
8434     bool isJump       = false;
8435     bool loadConstant = false;
8436
8437     switch (ins)
8438     {
8439         default:
8440             isJump = true;
8441             break;
8442
8443         case INS_tbz:
8444         case INS_tbnz:
8445         case INS_cbz:
8446         case INS_cbnz:
8447             isJump = true;
8448             break;
8449
8450         case INS_ldr:
8451         case INS_ldrsw:
8452             loadConstant = true;
8453             break;
8454
8455         case INS_adr:
8456         case INS_adrp:
8457             loadLabel = true;
8458             break;
8459     }
8460
8461     /* Figure out the distance to the target */
8462
8463     srcOffs = emitCurCodeOffs(dst);
8464     srcAddr = emitOffsetToPtr(srcOffs);
8465
8466     if (id->idAddr()->iiaIsJitDataOffset())
8467     {
8468         assert(loadConstant || loadLabel);
8469         int doff = id->idAddr()->iiaGetJitDataOffset();
8470         assert(doff >= 0);
8471         ssize_t imm = emitGetInsSC(id);
8472         assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8473
8474         unsigned dataOffs = (unsigned)(doff + imm);
8475         assert(dataOffs < emitDataSize());
8476         dstAddr = emitDataOffsetToPtr(dataOffs);
8477
8478         regNumber dstReg  = id->idReg1();
8479         regNumber addrReg = dstReg; // an integer register to compute long address.
8480         emitAttr  opSize  = id->idOpSize();
8481
8482         if (loadConstant)
8483         {
8484             if (id->idjShort)
8485             {
8486                 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8487                 assert(ins == INS_ldr);
8488                 assert(fmt == IF_LS_1A);
8489                 distVal = (ssize_t)(dstAddr - srcAddr);
8490                 dst     = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8491             }
8492             else
8493             {
8494                 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8495                 assert(fmt == IF_LARGELDC);
8496                 ssize_t relPageAddr =
8497                     (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8498                 if (isVectorRegister(dstReg))
8499                 {
8500                     // Update addrReg with the reserved integer register
8501                     // since we cannot use dstReg (vector) to load constant directly from memory.
8502                     addrReg = id->idReg2();
8503                     assert(isGeneralRegister(addrReg));
8504                 }
8505                 ins = INS_adrp;
8506                 fmt = IF_DI_1E;
8507                 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8508
8509                 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8510                 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8511                 assert(isValidUimm12(imm12));
8512                 ins = INS_ldr;
8513                 fmt = IF_LS_2B;
8514                 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8515
8516                 // fmov v, d -- copy constant in integer register to vector register.
8517                 // This is needed only for vector constant.
8518                 if (addrReg != dstReg)
8519                 {
8520                     //  fmov    Vd,Rn                DV_2I  X00111100X100111 000000nnnnnddddd   1E27 0000   Vd,Rn
8521                     //  (scalar, from general)
8522                     assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8523                     ins         = INS_fmov;
8524                     fmt         = IF_DV_2I;
8525                     code_t code = emitInsCode(ins, fmt);
8526
8527                     code |= insEncodeReg_Vd(dstReg);  // ddddd
8528                     code |= insEncodeReg_Rn(addrReg); // nnnnn
8529                     if (id->idOpSize() == EA_8BYTE)
8530                     {
8531                         code |= 0x80400000; // X ... X
8532                     }
8533                     dst += emitOutput_Instr(dst, code);
8534                 }
8535             }
8536         }
8537         else
8538         {
8539             assert(loadLabel);
8540             dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8541         }
8542
8543         return dst;
8544     }
8545
8546     assert(loadLabel || isJump);
8547
8548     if (id->idAddr()->iiaHasInstrCount())
8549     {
8550         assert(ig != NULL);
8551         int      instrCount = id->idAddr()->iiaGetInstrCount();
8552         unsigned insNum     = emitFindInsNum(ig, id);
8553         if (instrCount < 0)
8554         {
8555             // Backward branches using instruction count must be within the same instruction group.
8556             assert(insNum + 1 >= (unsigned)(-instrCount));
8557         }
8558         dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8559         dstAddr = emitOffsetToPtr(dstOffs);
8560     }
8561     else
8562     {
8563         dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8564         dstAddr = emitOffsetToPtr(dstOffs);
8565     }
8566
8567     distVal = (ssize_t)(dstAddr - srcAddr);
8568
8569     if (dstOffs <= srcOffs)
8570     {
8571 #if DEBUG_EMIT
8572         /* This is a backward jump - distance is known at this point */
8573
8574         if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8575         {
8576             size_t blkOffs = id->idjIG->igOffs;
8577
8578             if (INTERESTING_JUMP_NUM == 0)
8579                 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8580             printf("[3] Jump  block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8581             printf("[3] Jump        is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8582             printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8583         }
8584 #endif
8585     }
8586     else
8587     {
8588         /* This is a  forward jump - distance will be an upper limit */
8589
8590         emitFwdJumps = true;
8591
8592         /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8593            jump doesn't cross the hot-cold boundary. */
8594
8595         if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8596         {
8597             dstOffs -= emitOffsAdj;
8598             distVal -= emitOffsAdj;
8599         }
8600
8601         /* Record the location of the jump for later patching */
8602
8603         id->idjOffs = dstOffs;
8604
8605         /* Are we overflowing the id->idjOffs bitfield? */
8606         if (id->idjOffs != dstOffs)
8607             IMPL_LIMITATION("Method is too large");
8608
8609 #if DEBUG_EMIT
8610         if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8611         {
8612             size_t blkOffs = id->idjIG->igOffs;
8613
8614             if (INTERESTING_JUMP_NUM == 0)
8615                 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8616             printf("[4] Jump  block is at %08X\n", blkOffs);
8617             printf("[4] Jump        is at %08X\n", srcOffs);
8618             printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8619         }
8620 #endif
8621     }
8622
8623 #ifdef DEBUG
8624     if (0 && emitComp->verbose)
8625     {
8626         size_t sz          = 4;
8627         int    distValSize = id->idjShort ? 4 : 8;
8628         printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8629                dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8630     }
8631 #endif
8632
8633     /* For forward jumps, record the address of the distance value */
8634     id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8635
8636     if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8637     {
8638         assert(!id->idjShort);
8639         NYI_ARM64("Relocation Support for long address");
8640     }
8641
8642     assert(insOptsNone(id->idInsOpt()));
8643
8644     if (isJump)
8645     {
8646         if (id->idjShort)
8647         {
8648             // Short conditional/unconditional jump
8649             assert(!id->idjKeepLong);
8650             assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8651             assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8652         }
8653         else
8654         {
8655             // Long conditional jump
8656             assert(fmt == IF_LARGEJMP);
8657             // This is a pseudo-instruction format representing a large conditional branch, to allow
8658             // us to get a greater branch target range than we can get by using a straightforward conditional
8659             // branch. It is encoded as a short conditional branch that branches around a long unconditional
8660             // branch.
8661             //
8662             // Conceptually, we have:
8663             //
8664             //      b<cond> L_target
8665             //
8666             // The code we emit is:
8667             //
8668             //      b<!cond> L_not  // 4 bytes. Note that we reverse the condition.
8669             //      b L_target      // 4 bytes
8670             //   L_not:
8671             //
8672             // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8673             // the correct offset. Note also that this works for both integer and floating-point conditions, because
8674             // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8675             // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8676
8677             instruction reverseIns;
8678             insFormat   reverseFmt;
8679
8680             switch (ins)
8681             {
8682                 case INS_cbz:
8683                     reverseIns = INS_cbnz;
8684                     reverseFmt = IF_BI_1A;
8685                     break;
8686                 case INS_cbnz:
8687                     reverseIns = INS_cbz;
8688                     reverseFmt = IF_BI_1A;
8689                     break;
8690                 case INS_tbz:
8691                     reverseIns = INS_tbnz;
8692                     reverseFmt = IF_BI_1B;
8693                     break;
8694                 case INS_tbnz:
8695                     reverseIns = INS_tbz;
8696                     reverseFmt = IF_BI_1B;
8697                     break;
8698                 default:
8699                     reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8700                     reverseFmt = IF_BI_0B;
8701             }
8702
8703             dst =
8704                 emitOutputShortBranch(dst,
8705                                       reverseIns, // reverse the conditional instruction
8706                                       reverseFmt,
8707                                       8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8708                                       id);
8709
8710             // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8711             ins = INS_b;
8712             fmt = IF_BI_0A;
8713
8714             // The distVal was computed based on the beginning of the pseudo-instruction,
8715             // So subtract the size of the conditional branch so that it is relative to the
8716             // unconditional branch.
8717             distVal -= 4;
8718         }
8719
8720         dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8721     }
8722     else if (loadLabel)
8723     {
8724         dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8725     }
8726
8727     return dst;
8728 }
8729
8730 /*****************************************************************************
8731 *
8732 *  Output a short branch instruction.
8733 */
8734 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8735 {
8736     code_t code = emitInsCode(ins, fmt);
8737
8738     ssize_t loBits = (distVal & 3);
8739     noway_assert(loBits == 0);
8740     distVal >>= 2; // branch offset encodings are scaled by 4.
8741
8742     if (fmt == IF_BI_0A)
8743     {
8744         // INS_b or INS_bl_local
8745         noway_assert(isValidSimm26(distVal));
8746         distVal &= 0x3FFFFFFLL;
8747         code |= distVal;
8748     }
8749     else if (fmt == IF_BI_0B) // BI_0B   01010100iiiiiiii iiiiiiiiiiiXXXXX      simm19:00
8750     {
8751         // INS_beq, INS_bne, etc...
8752         noway_assert(isValidSimm19(distVal));
8753         distVal &= 0x7FFFFLL;
8754         code |= distVal << 5;
8755     }
8756     else if (fmt == IF_BI_1A) // BI_1A   X.......iiiiiiii iiiiiiiiiiittttt      Rt simm19:00
8757     {
8758         // INS_cbz or INS_cbnz
8759         assert(id != nullptr);
8760         code |= insEncodeDatasize(id->idOpSize()); // X
8761         code |= insEncodeReg_Rt(id->idReg1());     // ttttt
8762
8763         noway_assert(isValidSimm19(distVal));
8764         distVal &= 0x7FFFFLL; // 19 bits
8765         code |= distVal << 5;
8766     }
8767     else if (fmt == IF_BI_1B) // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
8768     {
8769         // INS_tbz or INS_tbnz
8770         assert(id != nullptr);
8771         ssize_t imm = emitGetInsSC(id);
8772         assert(isValidImmShift(imm, id->idOpSize()));
8773
8774         if (imm & 0x20) // test bit 32-63 ?
8775         {
8776             code |= 0x80000000; // B
8777         }
8778         code |= ((imm & 0x1F) << 19);          // bbbbb
8779         code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8780
8781         noway_assert(isValidSimm14(distVal));
8782         distVal &= 0x3FFFLL; // 14 bits
8783         code |= distVal << 5;
8784     }
8785     else
8786     {
8787         assert(!"Unknown fmt for emitOutputShortBranch");
8788     }
8789
8790     dst += emitOutput_Instr(dst, code);
8791
8792     return dst;
8793 }
8794
8795 /*****************************************************************************
8796 *
8797 *  Output a short address instruction.
8798 */
8799 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8800 {
8801     ssize_t loBits = (distVal & 3);
8802     distVal >>= 2;
8803
8804     code_t code = emitInsCode(ins, fmt);
8805     if (fmt == IF_DI_1E) // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd simm21
8806     {
8807         // INS_adr or INS_adrp
8808         code |= insEncodeReg_Rd(reg); // ddddd
8809
8810         noway_assert(isValidSimm19(distVal));
8811         distVal &= 0x7FFFFLL; // 19 bits
8812         code |= distVal << 5;
8813         code |= loBits << 29; //  2 bits
8814     }
8815     else
8816     {
8817         assert(!"Unknown fmt for emitOutputShortAddress");
8818     }
8819
8820     dst += emitOutput_Instr(dst, code);
8821
8822     return dst;
8823 }
8824
8825 /*****************************************************************************
8826 *
8827 *  Output a short constant instruction.
8828 */
8829 BYTE* emitter::emitOutputShortConstant(
8830     BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8831 {
8832     code_t code = emitInsCode(ins, fmt);
8833
8834     if (fmt == IF_LS_1A)
8835     {
8836         // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt simm21
8837         // INS_ldr or INS_ldrsw (PC-Relative)
8838
8839         ssize_t loBits = (imm & 3);
8840         noway_assert(loBits == 0);
8841         ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8842
8843         noway_assert(isValidSimm19(distVal));
8844
8845         // Is the target a vector register?
8846         if (isVectorRegister(reg))
8847         {
8848             code |= insEncodeDatasizeVLS(code, opSize); // XX V
8849             code |= insEncodeReg_Vt(reg);               // ttttt
8850         }
8851         else
8852         {
8853             assert(isGeneralRegister(reg));
8854             // insEncodeDatasizeLS is not quite right for this case.
8855             // So just specialize it.
8856             if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8857             {
8858                 // set the operation size in bit 30
8859                 code |= 0x40000000;
8860             }
8861
8862             code |= insEncodeReg_Rt(reg); // ttttt
8863         }
8864
8865         distVal &= 0x7FFFFLL; // 19 bits
8866         code |= distVal << 5;
8867     }
8868     else if (fmt == IF_LS_2B)
8869     {
8870         //  ldr     Rt,[Xn+pimm12]       LS_2B  1X11100101iiiiii iiiiiinnnnnttttt   B940 0000   imm(0-4095<<{2,3})
8871         // INS_ldr or INS_ldrsw (PC-Relative)
8872         noway_assert(isValidUimm12(imm));
8873         assert(isGeneralRegister(reg));
8874
8875         if (opSize == EA_8BYTE)
8876         {
8877             // insEncodeDatasizeLS is not quite right for this case.
8878             // So just specialize it.
8879             if (ins == INS_ldr)
8880             {
8881                 // set the operation size in bit 30
8882                 code |= 0x40000000;
8883             }
8884             // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8885             assert((imm & 7) == 0);
8886             imm >>= 3;
8887         }
8888         else
8889         {
8890             assert(opSize == EA_4BYTE);
8891             // Low 2 bits should be 0 -- 4 byte aligned data.
8892             assert((imm & 3) == 0);
8893             imm >>= 2;
8894         }
8895
8896         code |= insEncodeReg_Rt(reg); // ttttt
8897         code |= insEncodeReg_Rn(reg); // nnnnn
8898         code |= imm << 10;
8899     }
8900     else
8901     {
8902         assert(!"Unknown fmt for emitOutputShortConstant");
8903     }
8904
8905     dst += emitOutput_Instr(dst, code);
8906
8907     return dst;
8908 }
8909 /*****************************************************************************
8910  *
8911  *  Output a call instruction.
8912  */
8913
8914 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8915 {
8916     const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8917     regMaskTP           gcrefRegs;
8918     regMaskTP           byrefRegs;
8919
8920     VARSET_TP GCvars(VarSetOps::UninitVal());
8921
8922     // Is this a "fat" call descriptor?
8923     if (id->idIsLargeCall())
8924     {
8925         instrDescCGCA* idCall = (instrDescCGCA*)id;
8926         gcrefRegs             = idCall->idcGcrefRegs;
8927         byrefRegs             = idCall->idcByrefRegs;
8928         VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
8929     }
8930     else
8931     {
8932         assert(!id->idIsLargeDsp());
8933         assert(!id->idIsLargeCns());
8934
8935         gcrefRegs = emitDecodeCallGCregs(id);
8936         byrefRegs = 0;
8937         VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
8938     }
8939
8940     /* We update the GC info before the call as the variables cannot be
8941         used by the call. Killing variables before the call helps with
8942         boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
8943         If we ever track aliased variables (which could be used by the
8944         call), we would have to keep them alive past the call. */
8945
8946     emitUpdateLiveGCvars(GCvars, dst);
8947
8948     // Now output the call instruction and update the 'dst' pointer
8949     //
8950     unsigned outputInstrSize = emitOutput_Instr(dst, code);
8951     dst += outputInstrSize;
8952
8953     // All call instructions are 4-byte in size on ARM64
8954     //
8955     assert(outputInstrSize == callInstrSize);
8956
8957     // If the method returns a GC ref, mark INTRET (R0) appropriately.
8958     if (id->idGCref() == GCT_GCREF)
8959     {
8960         gcrefRegs |= RBM_INTRET;
8961     }
8962     else if (id->idGCref() == GCT_BYREF)
8963     {
8964         byrefRegs |= RBM_INTRET;
8965     }
8966
8967     // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
8968     if (id->idIsLargeCall())
8969     {
8970         instrDescCGCA* idCall = (instrDescCGCA*)id;
8971         if (idCall->idSecondGCref() == GCT_GCREF)
8972         {
8973             gcrefRegs |= RBM_INTRET_1;
8974         }
8975         else if (idCall->idSecondGCref() == GCT_BYREF)
8976         {
8977             byrefRegs |= RBM_INTRET_1;
8978         }
8979     }
8980
8981     // If the GC register set has changed, report the new set.
8982     if (gcrefRegs != emitThisGCrefRegs)
8983     {
8984         emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
8985     }
8986     // If the Byref register set has changed, report the new set.
8987     if (byrefRegs != emitThisByrefRegs)
8988     {
8989         emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
8990     }
8991
8992     // Some helper calls may be marked as not requiring GC info to be recorded.
8993     if ((!id->idIsNoGC()))
8994     {
8995         // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
8996         // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
8997         // to record the call for GC info purposes.  (It might be best to use an alternate call,
8998         // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
8999         emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
9000
9001         // Do we need to record a call location for GC purposes?
9002         //
9003         if (!emitFullGCinfo)
9004         {
9005             emitRecordGCcall(dst, callInstrSize);
9006         }
9007     }
9008     return callInstrSize;
9009 }
9010
9011 /*****************************************************************************
9012  *
9013  *  Emit a 32-bit Arm64 instruction
9014  */
9015
9016 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
9017 {
9018     assert(sizeof(code_t) == 4);
9019     *((code_t*)dst) = code;
9020
9021     return sizeof(code_t);
9022 }
9023
9024 /*****************************************************************************
9025 *
9026  *  Append the machine code corresponding to the given instruction descriptor
9027  *  to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
9028  *  is the instruction group that contains the instruction. Updates '*dp' to
9029  *  point past the generated code, and returns the size of the instruction
9030  *  descriptor in bytes.
9031  */
9032
9033 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
9034 {
9035     BYTE*         dst  = *dp;
9036     BYTE*         odst = dst;
9037     code_t        code = 0;
9038     size_t        sz   = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
9039     instruction   ins  = id->idIns();
9040     insFormat     fmt  = id->idInsFmt();
9041     emitAttr      size = id->idOpSize();
9042     unsigned char callInstrSize = 0;
9043     unsigned      condcode;
9044
9045 #ifdef DEBUG
9046 #if DUMP_GC_TABLES
9047     bool dspOffs = emitComp->opts.dspGCtbls;
9048 #else
9049     bool dspOffs = !emitComp->opts.disDiffable;
9050 #endif
9051 #endif // DEBUG
9052
9053     assert(REG_NA == (int)REG_NA);
9054
9055     VARSET_TP GCvars(VarSetOps::UninitVal());
9056
9057     /* What instruction format have we got? */
9058
9059     switch (fmt)
9060     {
9061         ssize_t  imm;
9062         ssize_t  index;
9063         ssize_t  index2;
9064         unsigned scale;
9065         unsigned cmode;
9066         unsigned immShift;
9067         bool     hasShift;
9068         emitAttr extSize;
9069         emitAttr elemsize;
9070         emitAttr datasize;
9071
9072         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
9073         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiii.....               simm19:00
9074         case IF_LARGEJMP:
9075             assert(id->idGCref() == GCT_NONE);
9076             assert(id->idIsBound());
9077             dst = emitOutputLJ(ig, dst, id);
9078             sz  = sizeof(instrDescJmp);
9079             break;
9080
9081         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
9082             code = emitInsCode(ins, fmt);
9083             sz   = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9084             dst += emitOutputCall(ig, dst, id, code);
9085             // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
9086             emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
9087             break;
9088
9089         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
9090             assert(insOptsNone(id->idInsOpt()));
9091             assert(id->idIsBound());
9092
9093             dst = emitOutputLJ(ig, dst, id);
9094             sz  = sizeof(instrDescJmp);
9095             break;
9096
9097         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
9098             assert(insOptsNone(id->idInsOpt()));
9099             assert(id->idIsBound());
9100
9101             dst = emitOutputLJ(ig, dst, id);
9102             sz  = sizeof(instrDescJmp);
9103             break;
9104
9105         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
9106             assert(insOptsNone(id->idInsOpt()));
9107             assert((ins == INS_ret) || (ins == INS_br));
9108             code = emitInsCode(ins, fmt);
9109             code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9110
9111             dst += emitOutput_Instr(dst, code);
9112             break;
9113
9114         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
9115             assert(insOptsNone(id->idInsOpt()));
9116             assert((ins == INS_br_tail) || (ins == INS_blr));
9117             code = emitInsCode(ins, fmt);
9118             code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9119
9120             sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9121             dst += emitOutputCall(ig, dst, id, code);
9122             break;
9123
9124         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
9125         case IF_LARGELDC:
9126             assert(insOptsNone(id->idInsOpt()));
9127             assert(id->idIsBound());
9128
9129             dst = emitOutputLJ(ig, dst, id);
9130             sz  = sizeof(instrDescJmp);
9131             break;
9132
9133         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
9134             assert(insOptsNone(id->idInsOpt()));
9135             code = emitInsCode(ins, fmt);
9136             // Is the target a vector register?
9137             if (isVectorRegister(id->idReg1()))
9138             {
9139                 code &= 0x3FFFFFFF;                                 // clear the size bits
9140                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9141                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9142             }
9143             else
9144             {
9145                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9146                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9147             }
9148             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9149             dst += emitOutput_Instr(dst, code);
9150             break;
9151
9152         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
9153             assert(insOptsNone(id->idInsOpt()));
9154             imm = emitGetInsSC(id);
9155             assert(isValidUimm12(imm));
9156             code = emitInsCode(ins, fmt);
9157             // Is the target a vector register?
9158             if (isVectorRegister(id->idReg1()))
9159             {
9160                 code &= 0x3FFFFFFF;                                 // clear the size bits
9161                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9162                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9163             }
9164             else
9165             {
9166                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9167                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9168             }
9169             code |= ((code_t)imm << 10);           // iiiiiiiiiiii
9170             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9171             dst += emitOutput_Instr(dst, code);
9172             break;
9173
9174         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
9175             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9176             imm = emitGetInsSC(id);
9177             assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9178             imm &= 0x1ff;                          // force into unsigned 9 bit representation
9179             code = emitInsCode(ins, fmt);
9180             // Is the target a vector register?
9181             if (isVectorRegister(id->idReg1()))
9182             {
9183                 code &= 0x3FFFFFFF;                                 // clear the size bits
9184                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9185                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9186             }
9187             else
9188             {
9189                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9190                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9191             }
9192             code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9193             code |= ((code_t)imm << 12);                 // iiiiiiiii
9194             code |= insEncodeReg_Rn(id->idReg2());       // nnnnn
9195             dst += emitOutput_Instr(dst, code);
9196             break;
9197
9198         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
9199             assert(insOptsLSExtend(id->idInsOpt()));
9200             code = emitInsCode(ins, fmt);
9201             // Is the target a vector register?
9202             if (isVectorRegister(id->idReg1()))
9203             {
9204                 code &= 0x3FFFFFFF;                                 // clear the size bits
9205                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9206                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9207             }
9208             else
9209             {
9210                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9211                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9212             }
9213             code |= insEncodeExtend(id->idInsOpt()); // ooo
9214             code |= insEncodeReg_Rn(id->idReg2());   // nnnnn
9215             if (id->idIsLclVar())
9216             {
9217                 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9218             }
9219             else
9220             {
9221                 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9222                 code |= insEncodeReg_Rm(id->idReg3());          // mmmmm
9223             }
9224             dst += emitOutput_Instr(dst, code);
9225             break;
9226
9227         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnddddd      Rd Ra Rn
9228             assert(insOptsNone(id->idInsOpt()));
9229             code = emitInsCode(ins, fmt);
9230             // Is the target a vector register?
9231             if (isVectorRegister(id->idReg1()))
9232             {
9233                 code &= 0x3FFFFFFF;                                  // clear the size bits
9234                 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9235                 code |= insEncodeReg_Vt(id->idReg1());               // ttttt
9236                 code |= insEncodeReg_Va(id->idReg2());               // aaaaa
9237             }
9238             else
9239             {
9240                 code |= insEncodeDatasize(id->idOpSize()); // X
9241                 code |= insEncodeReg_Rt(id->idReg1());     // ttttt
9242                 code |= insEncodeReg_Ra(id->idReg2());     // aaaaa
9243             }
9244             code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9245             dst += emitOutput_Instr(dst, code);
9246             break;
9247
9248         case IF_LS_3C: // LS_3C   X......PP.iiiiii iaaaaannnnnddddd      Rd Ra Rn imm(im7,sh)
9249             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9250             imm = emitGetInsSC(id);
9251             assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9252             imm &= 0x7f;                         // force into unsigned 7 bit representation
9253             code = emitInsCode(ins, fmt);
9254             // Is the target a vector register?
9255             if (isVectorRegister(id->idReg1()))
9256             {
9257                 code &= 0x3FFFFFFF;                                  // clear the size bits
9258                 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9259                 code |= insEncodeReg_Vt(id->idReg1());               // ttttt
9260                 code |= insEncodeReg_Va(id->idReg2());               // aaaaa
9261             }
9262             else
9263             {
9264                 code |= insEncodeDatasize(id->idOpSize()); // X
9265                 code |= insEncodeReg_Rt(id->idReg1());     // ttttt
9266                 code |= insEncodeReg_Ra(id->idReg2());     // aaaaa
9267             }
9268             code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9269             code |= ((code_t)imm << 15);                          // iiiiiiiii
9270             code |= insEncodeReg_Rn(id->idReg3());                // nnnnn
9271             dst += emitOutput_Instr(dst, code);
9272             break;
9273
9274         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
9275             code = emitInsCode(ins, fmt);
9276             // Arm64 store exclusive unpredictable cases
9277             assert(id->idReg1() != id->idReg2());
9278             assert(id->idReg1() != id->idReg3());
9279             code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9280             code |= insEncodeReg_Rm(id->idReg1());             // mmmmm
9281             code |= insEncodeReg_Rt(id->idReg2());             // ttttt
9282             code |= insEncodeReg_Rn(id->idReg3());             // nnnnn
9283             dst += emitOutput_Instr(dst, code);
9284             break;
9285
9286         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....         Rn    imm(i12,sh)
9287             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9288             imm = emitGetInsSC(id);
9289             assert(isValidUimm12(imm));
9290             code = emitInsCode(ins, fmt);
9291             code |= insEncodeDatasize(id->idOpSize());   // X
9292             code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9293             code |= ((code_t)imm << 10);                 // iiiiiiiiiiii
9294             code |= insEncodeReg_Rn(id->idReg1());       // nnnnn
9295             dst += emitOutput_Instr(dst, code);
9296             break;
9297
9298         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
9299             imm = emitGetInsSC(id);
9300             assert(isValidImmHWVal(imm, id->idOpSize()));
9301             code = emitInsCode(ins, fmt);
9302             code |= insEncodeDatasize(id->idOpSize()); // X
9303             code |= ((code_t)imm << 5);                // hwiiiii iiiiiiiiiii
9304             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9305             dst += emitOutput_Instr(dst, code);
9306             break;
9307
9308         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    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_Rn(id->idReg1());     // nnnnn
9315             dst += emitOutput_Instr(dst, code);
9316             break;
9317
9318         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
9319             imm = emitGetInsSC(id);
9320             assert(isValidImmNRS(imm, id->idOpSize()));
9321             code = emitInsCode(ins, fmt);
9322             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9323             code |= insEncodeDatasize(id->idOpSize()); // X
9324             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9325             dst += emitOutput_Instr(dst, code);
9326             break;
9327
9328         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
9329         case IF_LARGEADR:
9330             assert(insOptsNone(id->idInsOpt()));
9331             if (id->idIsReloc())
9332             {
9333                 code = emitInsCode(ins, fmt);
9334                 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9335                 dst += emitOutput_Instr(dst, code);
9336                 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9337             }
9338             else
9339             {
9340                 // Local jmp/load case which does not need a relocation.
9341                 assert(id->idIsBound());
9342                 dst = emitOutputLJ(ig, dst, id);
9343             }
9344             sz = sizeof(instrDescJmp);
9345             break;
9346
9347         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
9348             imm = emitGetInsSC(id);
9349             assert(isValidImmCondFlagsImm5(imm));
9350             {
9351                 condFlagsImm cfi;
9352                 cfi.immCFVal = (unsigned)imm;
9353                 code         = emitInsCode(ins, fmt);
9354                 code |= insEncodeDatasize(id->idOpSize()); // X
9355                 code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9356                 code |= ((code_t)cfi.imm5 << 16);          // iiiii
9357                 code |= insEncodeFlags(cfi.flags);         // nzcv
9358                 code |= insEncodeCond(cfi.cond);           // cccc
9359                 dst += emitOutput_Instr(dst, code);
9360             }
9361             break;
9362
9363         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
9364             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9365             imm = emitGetInsSC(id);
9366             assert(isValidUimm12(imm));
9367             code = emitInsCode(ins, fmt);
9368             code |= insEncodeDatasize(id->idOpSize());   // X
9369             code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9370             code |= ((code_t)imm << 10);                 // iiiiiiiiiiii
9371             code |= insEncodeReg_Rd(id->idReg1());       // ddddd
9372             code |= insEncodeReg_Rn(id->idReg2());       // nnnnn
9373             dst += emitOutput_Instr(dst, code);
9374
9375             if (id->idIsReloc())
9376             {
9377                 assert(sz == sizeof(instrDesc));
9378                 assert(id->idAddr()->iiaAddr != nullptr);
9379                 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9380             }
9381             break;
9382
9383         case IF_DI_2B: // DI_2B   X.........Xnnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
9384             code = emitInsCode(ins, fmt);
9385             imm  = emitGetInsSC(id);
9386             assert(isValidImmShift(imm, id->idOpSize()));
9387             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9388             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9389             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9390             code |= insEncodeReg_Rm(id->idReg2());             // Reg2 also in mmmmm
9391             code |= insEncodeShiftCount(imm, id->idOpSize());  // ssssss
9392             dst += emitOutput_Instr(dst, code);
9393             break;
9394
9395         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
9396             imm = emitGetInsSC(id);
9397             assert(isValidImmNRS(imm, id->idOpSize()));
9398             code = emitInsCode(ins, fmt);
9399             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9400             code |= insEncodeDatasize(id->idOpSize()); // X
9401             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9402             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9403             dst += emitOutput_Instr(dst, code);
9404             break;
9405
9406         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, imms   (N,r,s)
9407             if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9408             {
9409                 imm = emitGetInsSC(id);
9410                 assert(isValidImmShift(imm, id->idOpSize()));
9411
9412                 // Shift immediates are aliases of the SBFM/UBFM instructions
9413                 // that actually take 2 registers and 2 constants,
9414                 // Since we stored the shift immediate value
9415                 // we need to calculate the N,R and S values here.
9416
9417                 bitMaskImm bmi;
9418                 bmi.immNRS = 0;
9419
9420                 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9421                 bmi.immR = imm;
9422                 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9423
9424                 // immR and immS are now set correctly for INS_asr and INS_lsr
9425                 // but for INS_lsl we have to adjust the values for immR and immS
9426                 //
9427                 if (ins == INS_lsl)
9428                 {
9429                     bmi.immR = -imm & bmi.immS;
9430                     bmi.immS = bmi.immS - imm;
9431                 }
9432
9433                 // setup imm with the proper 13 bit value N:R:S
9434                 //
9435                 imm = bmi.immNRS;
9436             }
9437             else
9438             {
9439                 // The other instructions have already have encoded N,R and S values
9440                 imm = emitGetInsSC(id);
9441             }
9442             assert(isValidImmNRS(imm, id->idOpSize()));
9443
9444             code = emitInsCode(ins, fmt);
9445             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9446             code |= insEncodeDatasize(id->idOpSize()); // X
9447             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9448             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9449             dst += emitOutput_Instr(dst, code);
9450             break;
9451
9452         case IF_DR_1D: // DR_1D   X............... cccc.......ddddd      Rd       cond
9453             imm = emitGetInsSC(id);
9454             assert(isValidImmCond(imm));
9455             {
9456                 condFlagsImm cfi;
9457                 cfi.immCFVal = (unsigned)imm;
9458                 code         = emitInsCode(ins, fmt);
9459                 code |= insEncodeDatasize(id->idOpSize()); // X
9460                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9461                 code |= insEncodeInvertedCond(cfi.cond);   // cccc
9462                 dst += emitOutput_Instr(dst, code);
9463             }
9464             break;
9465
9466         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
9467             assert(insOptsNone(id->idInsOpt()));
9468             code = emitInsCode(ins, fmt);
9469             code |= insEncodeDatasize(id->idOpSize()); // X
9470             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9471             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9472             dst += emitOutput_Instr(dst, code);
9473             break;
9474
9475         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9476             code = emitInsCode(ins, fmt);
9477             imm  = emitGetInsSC(id);
9478             assert(isValidImmShift(imm, id->idOpSize()));
9479             code |= insEncodeDatasize(id->idOpSize());        // X
9480             code |= insEncodeShiftType(id->idInsOpt());       // sh
9481             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9482             code |= insEncodeReg_Rn(id->idReg1());            // nnnnn
9483             code |= insEncodeReg_Rm(id->idReg2());            // mmmmm
9484             dst += emitOutput_Instr(dst, code);
9485             break;
9486
9487         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
9488             code = emitInsCode(ins, fmt);
9489             imm  = emitGetInsSC(id);
9490             assert((imm >= 0) && (imm <= 4));          // imm [0..4]
9491             code |= insEncodeDatasize(id->idOpSize()); // X
9492             code |= insEncodeExtend(id->idInsOpt());   // ooo
9493             code |= insEncodeExtendScale(imm);         // sss
9494             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9495             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9496             dst += emitOutput_Instr(dst, code);
9497             break;
9498
9499         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
9500             imm = emitGetInsSC(id);
9501             assert(isValidImmCond(imm));
9502             {
9503                 condFlagsImm cfi;
9504                 cfi.immCFVal = (unsigned)imm;
9505                 code         = emitInsCode(ins, fmt);
9506                 code |= insEncodeDatasize(id->idOpSize()); // X
9507                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9508                 code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9509                 code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9510                 code |= insEncodeInvertedCond(cfi.cond);   // cccc
9511                 dst += emitOutput_Instr(dst, code);
9512             }
9513             break;
9514
9515         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
9516             code = emitInsCode(ins, fmt);
9517             code |= insEncodeDatasize(id->idOpSize()); // X
9518             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9519             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9520             dst += emitOutput_Instr(dst, code);
9521             break;
9522
9523         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
9524             code = emitInsCode(ins, fmt);
9525             imm  = emitGetInsSC(id);
9526             assert(isValidImmShift(imm, id->idOpSize()));
9527             code |= insEncodeDatasize(id->idOpSize());        // X
9528             code |= insEncodeShiftType(id->idInsOpt());       // sh
9529             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9530             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9531             code |= insEncodeReg_Rm(id->idReg2());            // mmmmm
9532             dst += emitOutput_Instr(dst, code);
9533             break;
9534
9535         case IF_DR_2G: // DR_2G   X............... .....xnnnnnddddd      Rd Rn
9536             code = emitInsCode(ins, fmt);
9537             code |= insEncodeDatasize(id->idOpSize()); // X
9538             if (ins == INS_rev)
9539             {
9540                 if (size == EA_8BYTE)
9541                 {
9542                     code |= 0x00000400; // x - bit at location 10
9543                 }
9544             }
9545             code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9546             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9547             dst += emitOutput_Instr(dst, code);
9548             break;
9549
9550         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
9551             code = emitInsCode(ins, fmt);
9552             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9553             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9554             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9555             dst += emitOutput_Instr(dst, code);
9556             break;
9557
9558         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
9559             imm = emitGetInsSC(id);
9560             assert(isValidImmCondFlags(imm));
9561             {
9562                 condFlagsImm cfi;
9563                 cfi.immCFVal = (unsigned)imm;
9564                 code         = emitInsCode(ins, fmt);
9565                 code |= insEncodeDatasize(id->idOpSize()); // X
9566                 code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9567                 code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9568                 code |= insEncodeFlags(cfi.flags);         // nzcv
9569                 code |= insEncodeCond(cfi.cond);           // cccc
9570                 dst += emitOutput_Instr(dst, code);
9571             }
9572             break;
9573
9574         case IF_DR_2J: // DR_2J   ................ ......nnnnnddddd      Sd Sn   (sha1h)
9575             code = emitInsCode(ins, fmt);
9576             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9577             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9578             dst += emitOutput_Instr(dst, code);
9579             break;
9580
9581         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
9582             code = emitInsCode(ins, fmt);
9583             code |= insEncodeDatasize(id->idOpSize()); // X
9584             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9585             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9586             if (id->idIsLclVar())
9587             {
9588                 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9589             }
9590             else
9591             {
9592                 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9593             }
9594             dst += emitOutput_Instr(dst, code);
9595             break;
9596
9597         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9598             code = emitInsCode(ins, fmt);
9599             imm  = emitGetInsSC(id);
9600             assert(isValidImmShift(imm, id->idOpSize()));
9601             code |= insEncodeDatasize(id->idOpSize());        // X
9602             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9603             code |= insEncodeReg_Rn(id->idReg2());            // nnnnn
9604             code |= insEncodeReg_Rm(id->idReg3());            // mmmmm
9605             code |= insEncodeShiftType(id->idInsOpt());       // sh
9606             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9607             dst += emitOutput_Instr(dst, code);
9608             break;
9609
9610         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
9611             code = emitInsCode(ins, fmt);
9612             imm  = emitGetInsSC(id);
9613             assert((imm >= 0) && (imm <= 4));          // imm [0..4]
9614             code |= insEncodeDatasize(id->idOpSize()); // X
9615             code |= insEncodeExtend(id->idInsOpt());   // ooo
9616             code |= insEncodeExtendScale(imm);         // sss
9617             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9618             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9619             code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9620             dst += emitOutput_Instr(dst, code);
9621             break;
9622
9623         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnddddd      Rd Rn Rm cond
9624             imm = emitGetInsSC(id);
9625             assert(isValidImmCond(imm));
9626             {
9627                 condFlagsImm cfi;
9628                 cfi.immCFVal = (unsigned)imm;
9629                 code         = emitInsCode(ins, fmt);
9630                 code |= insEncodeDatasize(id->idOpSize()); // X
9631                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9632                 code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9633                 code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9634                 code |= insEncodeCond(cfi.cond);           // cccc
9635                 dst += emitOutput_Instr(dst, code);
9636             }
9637             break;
9638
9639         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
9640             code = emitInsCode(ins, fmt);
9641             imm  = emitGetInsSC(id);
9642             assert(isValidImmShift(imm, id->idOpSize()));
9643             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9644             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9645             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9646             code |= insEncodeReg_Rm(id->idReg3());             // mmmmm
9647             code |= insEncodeShiftCount(imm, id->idOpSize());  // ssssss
9648             dst += emitOutput_Instr(dst, code);
9649             break;
9650
9651         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnmmmmm      Rd Rn Rm Ra
9652             code = emitInsCode(ins, fmt);
9653             code |= insEncodeDatasize(id->idOpSize()); // X
9654             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9655             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9656             code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9657             code |= insEncodeReg_Ra(id->idReg4());     // aaaaa
9658             dst += emitOutput_Instr(dst, code);
9659             break;
9660
9661         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8    (fmov - immediate scalar)
9662             imm      = emitGetInsSC(id);
9663             elemsize = id->idOpSize();
9664             code     = emitInsCode(ins, fmt);
9665             code |= insEncodeFloatElemsize(elemsize); // X
9666             code |= ((code_t)imm << 13);              // iiiii iii
9667             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9668             dst += emitOutput_Instr(dst, code);
9669             break;
9670
9671         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8    (immediate vector)
9672             imm      = emitGetInsSC(id) & 0x0ff;
9673             immShift = (emitGetInsSC(id) & 0x700) >> 8;
9674             elemsize = optGetElemsize(id->idInsOpt());
9675             cmode    = 0;
9676             switch (elemsize)
9677             { // cmode
9678                 case EA_1BYTE:
9679                     cmode = 0xE; // 1110
9680                     break;
9681                 case EA_2BYTE:
9682                     cmode = 0x8;
9683                     cmode |= (immShift << 1); // 10x0
9684                     break;
9685                 case EA_4BYTE:
9686                     if (immShift < 4)
9687                     {
9688                         cmode = 0x0;
9689                         cmode |= (immShift << 1); // 0xx0
9690                     }
9691                     else // MSL
9692                     {
9693                         cmode = 0xC;
9694                         if (immShift & 2)
9695                             cmode |= 1; // 110x
9696                     }
9697                     break;
9698                 case EA_8BYTE:
9699                     cmode = 0xE; // 1110
9700                     break;
9701                 default:
9702                     unreached();
9703                     break;
9704             }
9705
9706             code = emitInsCode(ins, fmt);
9707             code |= insEncodeVectorsize(id->idOpSize()); // Q
9708             if ((ins == INS_fmov) || (ins == INS_movi))
9709             {
9710                 if (elemsize == EA_8BYTE)
9711                 {
9712                     code |= 0x20000000; // X
9713                 }
9714             }
9715             if (ins != INS_fmov)
9716             {
9717                 assert((cmode >= 0) && (cmode <= 0xF));
9718                 code |= (cmode << 12); // cmod
9719             }
9720             code |= (((code_t)imm >> 5) << 16);    // iii
9721             code |= (((code_t)imm & 0x1f) << 5);   // iiiii
9722             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9723             dst += emitOutput_Instr(dst, code);
9724             break;
9725
9726         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0    (fcmp - with zero)
9727             elemsize = id->idOpSize();
9728             code     = emitInsCode(ins, fmt);
9729             code |= insEncodeFloatElemsize(elemsize); // X
9730             code |= insEncodeReg_Vn(id->idReg1());    // nnnnn
9731             dst += emitOutput_Instr(dst, code);
9732             break;
9733
9734         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn      (fabs, fcvt - vector)
9735             elemsize = optGetElemsize(id->idInsOpt());
9736             code     = emitInsCode(ins, fmt);
9737             code |= insEncodeVectorsize(id->idOpSize()); // Q
9738             code |= insEncodeFloatElemsize(elemsize);    // X
9739             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9740             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9741             dst += emitOutput_Instr(dst, code);
9742             break;
9743
9744         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[] (umov/smov    - to general)
9745             elemsize = id->idOpSize();
9746             index    = emitGetInsSC(id);
9747             datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9748             if (ins == INS_smov)
9749             {
9750                 datasize = EA_16BYTE;
9751             }
9752             code = emitInsCode(ins, fmt);
9753             code |= insEncodeVectorsize(datasize);         // Q
9754             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9755             code |= insEncodeReg_Rd(id->idReg1());         // ddddd
9756             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9757             dst += emitOutput_Instr(dst, code);
9758             break;
9759
9760         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn   (dup/ins - vector from general)
9761             if (ins == INS_dup)
9762             {
9763                 datasize = id->idOpSize();
9764                 elemsize = optGetElemsize(id->idInsOpt());
9765                 index    = 0;
9766             }
9767             else // INS_ins
9768             {
9769                 datasize = EA_16BYTE;
9770                 elemsize = id->idOpSize();
9771                 index    = emitGetInsSC(id);
9772             }
9773             code = emitInsCode(ins, fmt);
9774             code |= insEncodeVectorsize(datasize);         // Q
9775             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9776             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9777             code |= insEncodeReg_Rn(id->idReg2());         // nnnnn
9778             dst += emitOutput_Instr(dst, code);
9779             break;
9780
9781         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]   (dup - vector)
9782             index    = emitGetInsSC(id);
9783             elemsize = optGetElemsize(id->idInsOpt());
9784             code     = emitInsCode(ins, fmt);
9785             code |= insEncodeVectorsize(id->idOpSize());   // Q
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_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]   (dup - scalar)
9793             index    = emitGetInsSC(id);
9794             elemsize = id->idOpSize();
9795             code     = emitInsCode(ins, fmt);
9796             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9797             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9798             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9799             dst += emitOutput_Instr(dst, code);
9800             break;
9801
9802         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
9803             elemsize = id->idOpSize();
9804             imm      = emitGetInsSC(id);
9805             index    = (imm >> 4) & 0xf;
9806             index2   = imm & 0xf;
9807             code     = emitInsCode(ins, fmt);
9808             code |= insEncodeVectorIndex(elemsize, index);   // iiiii
9809             code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9810             code |= insEncodeReg_Vd(id->idReg1());           // ddddd
9811             code |= insEncodeReg_Vn(id->idReg2());           // nnnnn
9812             dst += emitOutput_Instr(dst, code);
9813             break;
9814
9815         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov,fcvtXX - register)
9816             elemsize = id->idOpSize();
9817             code     = emitInsCode(ins, fmt);
9818             code |= insEncodeFloatElemsize(elemsize); // X
9819             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9820             code |= insEncodeReg_Vn(id->idReg2());    // nnnnn
9821             dst += emitOutput_Instr(dst, code);
9822             break;
9823
9824         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov - to general)
9825             elemsize = id->idOpSize();
9826             code     = emitInsCode(ins, fmt);
9827             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X   X
9828             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9829             code |= insEncodeReg_Vn(id->idReg2());            // nnnnn
9830             dst += emitOutput_Instr(dst, code);
9831             break;
9832
9833         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov - from general)
9834             elemsize = id->idOpSize();
9835             code     = emitInsCode(ins, fmt);
9836             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X   X
9837             code |= insEncodeReg_Vd(id->idReg1());            // ddddd
9838             code |= insEncodeReg_Rn(id->idReg2());            // nnnnn
9839             dst += emitOutput_Instr(dst, code);
9840             break;
9841
9842         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
9843             code = emitInsCode(ins, fmt);
9844             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9845             code |= insEncodeReg_Vd(id->idReg1());            // ddddd
9846             code |= insEncodeReg_Vn(id->idReg2());            // nnnnn
9847             dst += emitOutput_Instr(dst, code);
9848             break;
9849
9850         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
9851             elemsize = id->idOpSize();
9852             code     = emitInsCode(ins, fmt);
9853             code |= insEncodeFloatElemsize(elemsize); // X
9854             code |= insEncodeReg_Vn(id->idReg1());    // nnnnn
9855             code |= insEncodeReg_Vm(id->idReg2());    // mmmmm
9856             dst += emitOutput_Instr(dst, code);
9857             break;
9858
9859         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
9860             elemsize = id->idOpSize();
9861             code     = emitInsCode(ins, fmt);
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_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn      (abs, neg   - vector)
9869             elemsize = optGetElemsize(id->idInsOpt());
9870             code     = emitInsCode(ins, fmt);
9871             code |= insEncodeVectorsize(id->idOpSize()); // Q
9872             code |= insEncodeElemsize(elemsize);         // XX
9873             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9874             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9875             dst += emitOutput_Instr(dst, code);
9876             break;
9877
9878         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
9879             imm  = emitGetInsSC(id);
9880             code = emitInsCode(ins, fmt);
9881             code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9882             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9883             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9884             dst += emitOutput_Instr(dst, code);
9885             break;
9886
9887         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
9888             imm      = emitGetInsSC(id);
9889             elemsize = optGetElemsize(id->idInsOpt());
9890             code     = emitInsCode(ins, fmt);
9891             code |= insEncodeVectorsize(id->idOpSize()); // Q
9892             code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9893             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9894             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9895             dst += emitOutput_Instr(dst, code);
9896             break;
9897
9898         case IF_DV_2P: // DV_2P   ............... ......nnnnnddddd      Vd Vn      (aes*, sha1su1)
9899             elemsize = optGetElemsize(id->idInsOpt());
9900             code     = emitInsCode(ins, fmt);
9901             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9902             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9903             dst += emitOutput_Instr(dst, code);
9904             break;
9905
9906         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9907             code     = emitInsCode(ins, fmt);
9908             elemsize = optGetElemsize(id->idInsOpt());
9909             code |= insEncodeVectorsize(id->idOpSize()); // Q
9910             code |= insEncodeElemsize(elemsize);         // XX
9911             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9912             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9913             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9914             dst += emitOutput_Instr(dst, code);
9915             break;
9916
9917         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector)
9918             code     = emitInsCode(ins, fmt);
9919             imm      = emitGetInsSC(id);
9920             elemsize = optGetElemsize(id->idInsOpt());
9921             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9922             code |= insEncodeVectorsize(id->idOpSize());    // Q
9923             code |= insEncodeElemsize(elemsize);            // XX
9924             code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
9925             code |= insEncodeReg_Vd(id->idReg1());          // ddddd
9926             code |= insEncodeReg_Vn(id->idReg2());          // nnnnn
9927             code |= insEncodeReg_Vm(id->idReg3());          // mmmmm
9928             dst += emitOutput_Instr(dst, code);
9929             break;
9930
9931         case IF_DV_3B: // DV_3B   .Q.......X.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9932             code     = emitInsCode(ins, fmt);
9933             elemsize = optGetElemsize(id->idInsOpt());
9934             code |= insEncodeVectorsize(id->idOpSize()); // Q
9935             code |= insEncodeFloatElemsize(elemsize);    // X
9936             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9937             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9938             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9939             dst += emitOutput_Instr(dst, code);
9940             break;
9941
9942         case IF_DV_3BI: // DV_3BI  .Q.......XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
9943             code     = emitInsCode(ins, fmt);
9944             imm      = emitGetInsSC(id);
9945             elemsize = optGetElemsize(id->idInsOpt());
9946             assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
9947             code |= insEncodeVectorsize(id->idOpSize()); // Q
9948             code |= insEncodeFloatElemsize(elemsize);    // X
9949             code |= insEncodeFloatIndex(elemsize, imm);  // L H
9950             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9951             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9952             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9953             dst += emitOutput_Instr(dst, code);
9954             break;
9955
9956         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9957             code = emitInsCode(ins, fmt);
9958             code |= insEncodeVectorsize(id->idOpSize()); // Q
9959             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9960             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9961             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9962             dst += emitOutput_Instr(dst, code);
9963             break;
9964
9965         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
9966             code = emitInsCode(ins, fmt);
9967             code |= insEncodeFloatElemsize(id->idOpSize()); // X
9968             code |= insEncodeReg_Vd(id->idReg1());          // ddddd
9969             code |= insEncodeReg_Vn(id->idReg2());          // nnnnn
9970             code |= insEncodeReg_Vm(id->idReg3());          // mmmmm
9971             dst += emitOutput_Instr(dst, code);
9972             break;
9973
9974         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
9975             code     = emitInsCode(ins, fmt);
9976             imm      = emitGetInsSC(id);
9977             elemsize = id->idOpSize();
9978             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9979             code |= insEncodeFloatElemsize(elemsize);   // X
9980             code |= insEncodeFloatIndex(elemsize, imm); // L H
9981             code |= insEncodeReg_Vd(id->idReg1());      // ddddd
9982             code |= insEncodeReg_Vn(id->idReg2());      // nnnnn
9983             code |= insEncodeReg_Vm(id->idReg3());      // mmmmm
9984             dst += emitOutput_Instr(dst, code);
9985             break;
9986
9987         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
9988         case IF_DV_3F: // DV_3F   ...........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector) - source dest regs overlap
9989             code = emitInsCode(ins, fmt);
9990             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9991             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9992             code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9993             dst += emitOutput_Instr(dst, code);
9994             break;
9995
9996         case IF_DV_4A: // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
9997             code     = emitInsCode(ins, fmt);
9998             elemsize = id->idOpSize();
9999             code |= insEncodeFloatElemsize(elemsize); // X
10000             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
10001             code |= insEncodeReg_Vn(id->idReg2());    // nnnnn
10002             code |= insEncodeReg_Vm(id->idReg3());    // mmmmm
10003             code |= insEncodeReg_Va(id->idReg4());    // aaaaa
10004             dst += emitOutput_Instr(dst, code);
10005             break;
10006
10007         case IF_SN_0A: // SN_0A   ................ ................
10008             code = emitInsCode(ins, fmt);
10009             dst += emitOutput_Instr(dst, code);
10010             break;
10011
10012         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
10013             imm = emitGetInsSC(id);
10014             assert(isValidUimm16(imm));
10015             code = emitInsCode(ins, fmt);
10016             code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
10017             dst += emitOutput_Instr(dst, code);
10018             break;
10019
10020         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
10021             imm = emitGetInsSC(id);
10022             assert((imm >= 0) && (imm <= 15));
10023             code = emitInsCode(ins, fmt);
10024             code |= ((code_t)imm << 8); // bbbb
10025             dst += emitOutput_Instr(dst, code);
10026             break;
10027
10028         default:
10029             assert(!"Unexpected format");
10030             break;
10031     }
10032
10033     // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
10034     // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
10035     // GC ref to register "id->idReg1()".  (It may, apparently, also not be GC_NONE in other cases, such as
10036     // for stores, but we ignore those cases here.)
10037     if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
10038     {
10039         // We assume that "idReg1" is the primary destination register for all instructions
10040         if (id->idGCref() != GCT_NONE)
10041         {
10042             emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
10043         }
10044         else
10045         {
10046             emitGCregDeadUpd(id->idReg1(), dst);
10047         }
10048
10049         if (emitInsMayWriteMultipleRegs(id))
10050         {
10051             // INS_ldp etc...
10052             // "idReg2" is the secondary destination register
10053             if (id->idGCrefReg2() != GCT_NONE)
10054             {
10055                 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
10056             }
10057             else
10058             {
10059                 emitGCregDeadUpd(id->idReg2(), dst);
10060             }
10061         }
10062     }
10063
10064     // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
10065     // ref or overwritten one.
10066     if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
10067     {
10068         int      varNum = id->idAddr()->iiaLclVar.lvaVarNum();
10069         unsigned ofs    = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
10070         bool     FPbased;
10071         int      adr = emitComp->lvaFrameAddress(varNum, &FPbased);
10072         if (id->idGCref() != GCT_NONE)
10073         {
10074             emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
10075         }
10076         else
10077         {
10078             // If the type of the local is a gc ref type, update the liveness.
10079             var_types vt;
10080             if (varNum >= 0)
10081             {
10082                 // "Regular" (non-spill-temp) local.
10083                 vt = var_types(emitComp->lvaTable[varNum].lvType);
10084             }
10085             else
10086             {
10087                 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10088                 vt              = tmpDsc->tdTempType();
10089             }
10090             if (vt == TYP_REF || vt == TYP_BYREF)
10091                 emitGCvarDeadUpd(adr + ofs, dst);
10092         }
10093         if (emitInsWritesToLclVarStackLocPair(id))
10094         {
10095             unsigned ofs2 = ofs + TARGET_POINTER_SIZE;
10096             if (id->idGCrefReg2() != GCT_NONE)
10097             {
10098                 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
10099             }
10100             else
10101             {
10102                 // If the type of the local is a gc ref type, update the liveness.
10103                 var_types vt;
10104                 if (varNum >= 0)
10105                 {
10106                     // "Regular" (non-spill-temp) local.
10107                     vt = var_types(emitComp->lvaTable[varNum].lvType);
10108                 }
10109                 else
10110                 {
10111                     TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10112                     vt              = tmpDsc->tdTempType();
10113                 }
10114                 if (vt == TYP_REF || vt == TYP_BYREF)
10115                     emitGCvarDeadUpd(adr + ofs2, dst);
10116             }
10117         }
10118     }
10119
10120 #ifdef DEBUG
10121     /* Make sure we set the instruction descriptor size correctly */
10122
10123     size_t expected = emitSizeOfInsDsc(id);
10124     assert(sz == expected);
10125
10126     if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
10127     {
10128         emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
10129     }
10130
10131     if (emitComp->compDebugBreak)
10132     {
10133         // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
10134         // emitting instruction a6, (i.e. IN00a6 in jitdump).
10135         if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
10136         {
10137             assert(!"JitBreakEmitOutputInstr reached");
10138         }
10139     }
10140 #endif
10141
10142     /* All instructions are expected to generate code */
10143
10144     assert(*dp != dst);
10145
10146     *dp = dst;
10147
10148     return sz;
10149 }
10150
10151 /*****************************************************************************/
10152 /*****************************************************************************/
10153
10154 #ifdef DEBUG
10155
10156 /*****************************************************************************
10157  *
10158  *  Display the instruction name
10159  */
10160 void emitter::emitDispInst(instruction ins)
10161 {
10162     const char* insstr = codeGen->genInsName(ins);
10163     size_t      len    = strlen(insstr);
10164
10165     /* Display the instruction name */
10166
10167     printf("%s", insstr);
10168
10169     //
10170     // Add at least one space after the instruction name
10171     // and add spaces until we have reach the normal size of 8
10172     do
10173     {
10174         printf(" ");
10175         len++;
10176     } while (len < 8);
10177 }
10178
10179 /*****************************************************************************
10180  *
10181  *  Display an reloc value
10182  *  If we are formatting for an assembly listing don't print the hex value
10183  *  since it will prevent us from doing assembly diffs
10184  */
10185 void emitter::emitDispReloc(int value, bool addComma)
10186 {
10187     if (emitComp->opts.disAsm)
10188     {
10189         printf("(reloc)");
10190     }
10191     else
10192     {
10193         printf("(reloc 0x%x)", dspPtr(value));
10194     }
10195
10196     if (addComma)
10197         printf(", ");
10198 }
10199
10200 /*****************************************************************************
10201  *
10202  *  Display an immediate value
10203  */
10204 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10205 {
10206     if (strictArmAsm)
10207     {
10208         printf("#");
10209     }
10210
10211     // Munge any pointers if we want diff-able disassembly.
10212     // Since some may be emitted as partial words, print as diffable anything that has
10213     // significant bits beyond the lowest 8-bits.
10214     if (emitComp->opts.disDiffable)
10215     {
10216         ssize_t top56bits = (imm >> 8);
10217         if ((top56bits != 0) && (top56bits != -1))
10218             imm = 0xD1FFAB1E;
10219     }
10220
10221     if (!alwaysHex && (imm > -1000) && (imm < 1000))
10222     {
10223         printf("%d", imm);
10224     }
10225     else
10226     {
10227         if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10228         {
10229             printf("-");
10230             imm = -imm;
10231         }
10232
10233         if ((imm & 0xFFFFFFFF00000000LL) != 0)
10234         {
10235             printf("0x%llx", imm);
10236         }
10237         else
10238         {
10239             printf("0x%02x", imm);
10240         }
10241     }
10242
10243     if (addComma)
10244         printf(", ");
10245 }
10246
10247 /*****************************************************************************
10248  *
10249  *  Display a float zero constant
10250  */
10251 void emitter::emitDispFloatZero()
10252 {
10253     if (strictArmAsm)
10254     {
10255         printf("#");
10256     }
10257     printf("0.0");
10258 }
10259
10260 /*****************************************************************************
10261  *
10262  *  Display an encoded float constant value
10263  */
10264 void emitter::emitDispFloatImm(ssize_t imm8)
10265 {
10266     assert((0 <= imm8) && (imm8 <= 0x0ff));
10267     if (strictArmAsm)
10268     {
10269         printf("#");
10270     }
10271
10272     floatImm8 fpImm;
10273     fpImm.immFPIVal = (unsigned)imm8;
10274     double result   = emitDecodeFloatImm8(fpImm);
10275
10276     printf("%.4f", result);
10277 }
10278
10279 /*****************************************************************************
10280  *
10281  *  Display an immediate that is optionally LSL12.
10282  */
10283 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10284 {
10285     if (!strictArmAsm && insOptsLSL12(opt))
10286     {
10287         imm <<= 12;
10288     }
10289     emitDispImm(imm, false);
10290     if (strictArmAsm && insOptsLSL12(opt))
10291     {
10292         printf(", LSL #12");
10293     }
10294 }
10295
10296 /*****************************************************************************
10297  *
10298  *  Display an ARM64 condition code for the conditional instructions
10299  */
10300 void emitter::emitDispCond(insCond cond)
10301 {
10302     const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10303                                       "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10304     unsigned imm = (unsigned)cond;
10305     assert((0 <= imm) && (imm < ArrLen(armCond)));
10306     printf(armCond[imm]);
10307 }
10308
10309 /*****************************************************************************
10310  *
10311  *  Display an ARM64 flags for the conditional instructions
10312  */
10313 void emitter::emitDispFlags(insCflags flags)
10314 {
10315     const static char* armFlags[16] = {"0", "v",  "c",  "cv",  "z",  "zv",  "zc",  "zcv",
10316                                        "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10317     unsigned imm = (unsigned)flags;
10318     assert((0 <= imm) && (imm < ArrLen(armFlags)));
10319     printf(armFlags[imm]);
10320 }
10321
10322 /*****************************************************************************
10323  *
10324  *  Display an ARM64 'barrier' for the memory barrier instructions
10325  */
10326 void emitter::emitDispBarrier(insBarrier barrier)
10327 {
10328     const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4",  "nshld", "nshst", "nsh",
10329                                           "#8", "ishld", "ishst", "ish", "#12", "ld",    "st",    "sy"};
10330     unsigned imm = (unsigned)barrier;
10331     assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10332     printf(armBarriers[imm]);
10333 }
10334
10335 /*****************************************************************************
10336  *
10337  *  Prints the encoding for the Shift Type encoding
10338  */
10339
10340 void emitter::emitDispShiftOpts(insOpts opt)
10341 {
10342     if (opt == INS_OPTS_LSL)
10343         printf(" LSL ");
10344     else if (opt == INS_OPTS_LSR)
10345         printf(" LSR ");
10346     else if (opt == INS_OPTS_ASR)
10347         printf(" ASR ");
10348     else if (opt == INS_OPTS_ROR)
10349         printf(" ROR ");
10350     else if (opt == INS_OPTS_MSL)
10351         printf(" MSL ");
10352     else
10353         assert(!"Bad value");
10354 }
10355
10356 /*****************************************************************************
10357  *
10358  *  Prints the encoding for the Extend Type encoding
10359  */
10360
10361 void emitter::emitDispExtendOpts(insOpts opt)
10362 {
10363     if (opt == INS_OPTS_UXTB)
10364         printf("UXTB");
10365     else if (opt == INS_OPTS_UXTH)
10366         printf("UXTH");
10367     else if (opt == INS_OPTS_UXTW)
10368         printf("UXTW");
10369     else if (opt == INS_OPTS_UXTX)
10370         printf("UXTX");
10371     else if (opt == INS_OPTS_SXTB)
10372         printf("SXTB");
10373     else if (opt == INS_OPTS_SXTH)
10374         printf("SXTH");
10375     else if (opt == INS_OPTS_SXTW)
10376         printf("SXTW");
10377     else if (opt == INS_OPTS_SXTX)
10378         printf("SXTX");
10379     else
10380         assert(!"Bad value");
10381 }
10382
10383 /*****************************************************************************
10384  *
10385  *  Prints the encoding for the Extend Type encoding in loads/stores
10386  */
10387
10388 void emitter::emitDispLSExtendOpts(insOpts opt)
10389 {
10390     if (opt == INS_OPTS_LSL)
10391         printf("LSL");
10392     else if (opt == INS_OPTS_UXTW)
10393         printf("UXTW");
10394     else if (opt == INS_OPTS_UXTX)
10395         printf("UXTX");
10396     else if (opt == INS_OPTS_SXTW)
10397         printf("SXTW");
10398     else if (opt == INS_OPTS_SXTX)
10399         printf("SXTX");
10400     else
10401         assert(!"Bad value");
10402 }
10403
10404 /*****************************************************************************
10405  *
10406  *  Display a register
10407  */
10408 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10409 {
10410     emitAttr size = EA_SIZE(attr);
10411     printf(emitRegName(reg, size));
10412
10413     if (addComma)
10414         printf(", ");
10415 }
10416
10417 /*****************************************************************************
10418  *
10419  *  Display a vector register with an arrangement suffix
10420  */
10421 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10422 {
10423     assert(isVectorRegister(reg));
10424     printf(emitVectorRegName(reg));
10425     emitDispArrangement(opt);
10426
10427     if (addComma)
10428         printf(", ");
10429 }
10430
10431 /*****************************************************************************
10432  *
10433  *  Display an vector register index suffix
10434  */
10435 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10436 {
10437     assert(isVectorRegister(reg));
10438     printf(emitVectorRegName(reg));
10439
10440     switch (elemsize)
10441     {
10442         case EA_1BYTE:
10443             printf(".b");
10444             break;
10445         case EA_2BYTE:
10446             printf(".h");
10447             break;
10448         case EA_4BYTE:
10449             printf(".s");
10450             break;
10451         case EA_8BYTE:
10452             printf(".d");
10453             break;
10454         default:
10455             assert(!"invalid elemsize");
10456             break;
10457     }
10458
10459     printf("[%d]", index);
10460
10461     if (addComma)
10462         printf(", ");
10463 }
10464
10465 /*****************************************************************************
10466  *
10467  *  Display an arrangement suffix
10468  */
10469 void emitter::emitDispArrangement(insOpts opt)
10470 {
10471     const char* str = "???";
10472
10473     switch (opt)
10474     {
10475         case INS_OPTS_8B:
10476             str = "8b";
10477             break;
10478         case INS_OPTS_16B:
10479             str = "16b";
10480             break;
10481         case INS_OPTS_4H:
10482             str = "4h";
10483             break;
10484         case INS_OPTS_8H:
10485             str = "8h";
10486             break;
10487         case INS_OPTS_2S:
10488             str = "2s";
10489             break;
10490         case INS_OPTS_4S:
10491             str = "4s";
10492             break;
10493         case INS_OPTS_1D:
10494             str = "1d";
10495             break;
10496         case INS_OPTS_2D:
10497             str = "2d";
10498             break;
10499
10500         default:
10501             assert(!"Invalid insOpt for vector register");
10502     }
10503     printf(".");
10504     printf(str);
10505 }
10506
10507 /*****************************************************************************
10508  *
10509  *  Display a register with an optional shift operation
10510  */
10511 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10512 {
10513     emitAttr size = EA_SIZE(attr);
10514     assert((imm & 0x003F) == imm);
10515     assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10516
10517     printf(emitRegName(reg, size));
10518
10519     if (imm > 0)
10520     {
10521         if (strictArmAsm)
10522         {
10523             printf(",");
10524         }
10525         emitDispShiftOpts(opt);
10526         emitDispImm(imm, false);
10527     }
10528 }
10529
10530 /*****************************************************************************
10531  *
10532  *  Display a register with an optional extend and scale operations
10533  */
10534 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10535 {
10536     assert((imm >= 0) && (imm <= 4));
10537     assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10538
10539     // size is based on the extend option, not the instr size.
10540     emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10541
10542     if (strictArmAsm)
10543     {
10544         if (insOptsNone(opt))
10545         {
10546             emitDispReg(reg, size, false);
10547         }
10548         else
10549         {
10550             emitDispReg(reg, size, true);
10551             if (opt == INS_OPTS_LSL)
10552                 printf("LSL");
10553             else
10554                 emitDispExtendOpts(opt);
10555             if ((imm > 0) || (opt == INS_OPTS_LSL))
10556             {
10557                 printf(" ");
10558                 emitDispImm(imm, false);
10559             }
10560         }
10561     }
10562     else // !strictArmAsm
10563     {
10564         if (insOptsNone(opt))
10565         {
10566             emitDispReg(reg, size, false);
10567         }
10568         else
10569         {
10570             if (opt != INS_OPTS_LSL)
10571             {
10572                 emitDispExtendOpts(opt);
10573                 printf("(");
10574                 emitDispReg(reg, size, false);
10575                 printf(")");
10576             }
10577         }
10578         if (imm > 0)
10579         {
10580             printf("*");
10581             emitDispImm(1 << imm, false);
10582         }
10583     }
10584 }
10585
10586 /*****************************************************************************
10587  *
10588  *  Display an addressing operand [reg + imm]
10589  */
10590 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10591 {
10592     reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10593
10594     if (strictArmAsm)
10595     {
10596         printf("[");
10597
10598         emitDispReg(reg, EA_8BYTE, false);
10599
10600         if (!insOptsPostIndex(opt) && (imm != 0))
10601         {
10602             printf(",");
10603             emitDispImm(imm, false);
10604         }
10605         printf("]");
10606
10607         if (insOptsPreIndex(opt))
10608         {
10609             printf("!");
10610         }
10611         else if (insOptsPostIndex(opt))
10612         {
10613             printf(",");
10614             emitDispImm(imm, false);
10615         }
10616     }
10617     else // !strictArmAsm
10618     {
10619         printf("[");
10620
10621         const char* operStr = "++";
10622         if (imm < 0)
10623         {
10624             operStr = "--";
10625             imm     = -imm;
10626         }
10627
10628         if (insOptsPreIndex(opt))
10629         {
10630             printf(operStr);
10631         }
10632
10633         emitDispReg(reg, EA_8BYTE, false);
10634
10635         if (insOptsPostIndex(opt))
10636         {
10637             printf(operStr);
10638         }
10639
10640         if (insOptsIndexed(opt))
10641         {
10642             printf(", ");
10643         }
10644         else
10645         {
10646             printf("%c", operStr[1]);
10647         }
10648         emitDispImm(imm, false);
10649         printf("]");
10650     }
10651 }
10652
10653 /*****************************************************************************
10654  *
10655  *  Display an addressing operand [reg + extended reg]
10656  */
10657 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10658 {
10659     reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10660
10661     unsigned scale = 0;
10662     if (isScaled)
10663     {
10664         scale = NaturalScale_helper(size);
10665     }
10666
10667     printf("[");
10668
10669     if (strictArmAsm)
10670     {
10671         emitDispReg(reg1, EA_8BYTE, true);
10672         emitDispExtendReg(reg2, opt, scale);
10673     }
10674     else // !strictArmAsm
10675     {
10676         emitDispReg(reg1, EA_8BYTE, false);
10677         printf("+");
10678         emitDispExtendReg(reg2, opt, scale);
10679     }
10680
10681     printf("]");
10682 }
10683
10684 /*****************************************************************************
10685  *
10686  *  Display (optionally) the instruction encoding in hex
10687  */
10688
10689 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10690 {
10691     // We do not display the instruction hex if we want diff-able disassembly
10692     if (!emitComp->opts.disDiffable)
10693     {
10694         if (sz == 4)
10695         {
10696             printf("  %08X    ", (*((code_t*)code)));
10697         }
10698         else
10699         {
10700             printf("              ");
10701         }
10702     }
10703 }
10704
10705 /****************************************************************************
10706  *
10707  *  Display the given instruction.
10708  */
10709
10710 void emitter::emitDispIns(
10711     instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10712 {
10713     if (EMITVERBOSE)
10714     {
10715         unsigned idNum =
10716             id->idDebugOnlyInfo()->idNum; // Do not remove this!  It is needed for VisualStudio conditional breakpoints
10717
10718         printf("IN%04x: ", idNum);
10719     }
10720
10721     if (pCode == NULL)
10722         sz = 0;
10723
10724     if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10725         doffs = true;
10726
10727     /* Display the instruction offset */
10728
10729     emitDispInsOffs(offset, doffs);
10730
10731     /* Display the instruction hex code */
10732
10733     emitDispInsHex(pCode, sz);
10734
10735     printf("      ");
10736
10737     /* Get the instruction and format */
10738
10739     instruction ins = id->idIns();
10740     insFormat   fmt = id->idInsFmt();
10741
10742     emitDispInst(ins);
10743
10744     /* If this instruction has just been added, check its size */
10745
10746     assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10747
10748     /* Figure out the operand size */
10749     emitAttr size = id->idOpSize();
10750     emitAttr attr = size;
10751     if (id->idGCref() == GCT_GCREF)
10752         attr = EA_GCREF;
10753     else if (id->idGCref() == GCT_BYREF)
10754         attr = EA_BYREF;
10755
10756     switch (fmt)
10757     {
10758         code_t       code;
10759         ssize_t      imm;
10760         int          doffs;
10761         bool         isExtendAlias;
10762         bool         canEncode;
10763         bitMaskImm   bmi;
10764         halfwordImm  hwi;
10765         condFlagsImm cfi;
10766         unsigned     scale;
10767         unsigned     immShift;
10768         bool         hasShift;
10769         ssize_t      offs;
10770         const char*  methodName;
10771         emitAttr     elemsize;
10772         emitAttr     datasize;
10773         emitAttr     srcsize;
10774         emitAttr     dstsize;
10775         ssize_t      index;
10776         ssize_t      index2;
10777
10778         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
10779         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiii.....               simm19:00
10780         case IF_LARGEJMP:
10781         {
10782             if (fmt == IF_LARGEJMP)
10783             {
10784                 printf("(LARGEJMP)");
10785             }
10786             if (id->idAddr()->iiaHasInstrCount())
10787             {
10788                 int instrCount = id->idAddr()->iiaGetInstrCount();
10789
10790                 if (ig == nullptr)
10791                 {
10792                     printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10793                 }
10794                 else
10795                 {
10796                     unsigned       insNum  = emitFindInsNum(ig, id);
10797                     UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10798                     UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10799                     ssize_t        relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10800                     printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10801                 }
10802             }
10803             else if (id->idIsBound())
10804             {
10805                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10806             }
10807             else
10808             {
10809                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10810             }
10811         }
10812         break;
10813
10814         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
10815             if (id->idIsCallAddr())
10816             {
10817                 offs       = (ssize_t)id->idAddr()->iiaAddr;
10818                 methodName = "";
10819             }
10820             else
10821             {
10822                 offs       = 0;
10823                 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10824             }
10825
10826             if (offs)
10827             {
10828                 if (id->idIsDspReloc())
10829                     printf("reloc ");
10830                 printf("%08X", offs);
10831             }
10832             else
10833             {
10834                 printf("%s", methodName);
10835             }
10836             break;
10837
10838         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
10839             assert(insOptsNone(id->idInsOpt()));
10840             emitDispReg(id->idReg1(), size, true);
10841             if (id->idIsBound())
10842             {
10843                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10844             }
10845             else
10846             {
10847                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10848             }
10849             break;
10850
10851         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
10852             assert(insOptsNone(id->idInsOpt()));
10853             emitDispReg(id->idReg1(), size, true);
10854             emitDispImm(emitGetInsSC(id), true);
10855             if (id->idIsBound())
10856             {
10857                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10858             }
10859             else
10860             {
10861                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10862             }
10863             break;
10864
10865         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
10866             assert(insOptsNone(id->idInsOpt()));
10867             emitDispReg(id->idReg1(), size, false);
10868             break;
10869
10870         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
10871             assert(insOptsNone(id->idInsOpt()));
10872             emitDispReg(id->idReg3(), size, false);
10873             break;
10874
10875         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
10876         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
10877         case IF_LARGELDC:
10878         case IF_LARGEADR:
10879             assert(insOptsNone(id->idInsOpt()));
10880             emitDispReg(id->idReg1(), size, true);
10881             imm = emitGetInsSC(id);
10882
10883             /* Is this actually a reference to a data section? */
10884             if (fmt == IF_LARGEADR)
10885             {
10886                 printf("(LARGEADR)");
10887             }
10888             else if (fmt == IF_LARGELDC)
10889             {
10890                 printf("(LARGELDC)");
10891             }
10892
10893             printf("[");
10894             if (id->idAddr()->iiaIsJitDataOffset())
10895             {
10896                 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10897                 /* Display a data section reference */
10898
10899                 if (doffs & 1)
10900                     printf("@CNS%02u", doffs - 1);
10901                 else
10902                     printf("@RWD%02u", doffs);
10903
10904                 if (imm != 0)
10905                     printf("%+Id", imm);
10906             }
10907             else
10908             {
10909                 assert(imm == 0);
10910                 if (id->idIsReloc())
10911                 {
10912                     printf("RELOC ");
10913                     emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
10914                 }
10915                 else if (id->idIsBound())
10916                 {
10917                     printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10918                 }
10919                 else
10920                 {
10921                     printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10922                 }
10923             }
10924             printf("]");
10925             break;
10926
10927         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
10928             assert(insOptsNone(id->idInsOpt()));
10929             assert(emitGetInsSC(id) == 0);
10930             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10931             emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
10932             break;
10933
10934         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
10935             assert(insOptsNone(id->idInsOpt()));
10936             imm   = emitGetInsSC(id);
10937             scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10938             imm <<= scale; // The immediate is scaled by the size of the ld/st
10939             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10940             emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10941             break;
10942
10943         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
10944             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10945             imm = emitGetInsSC(id);
10946             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10947             emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10948             break;
10949
10950         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
10951             assert(insOptsLSExtend(id->idInsOpt()));
10952             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10953             if (id->idIsLclVar())
10954             {
10955                 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
10956             }
10957             else
10958             {
10959                 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
10960             }
10961             break;
10962
10963         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnddddd      Rt Ra Rn
10964             assert(insOptsNone(id->idInsOpt()));
10965             assert(emitGetInsSC(id) == 0);
10966             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10967             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10968             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10969             break;
10970
10971         case IF_LS_3C: // LS_3C   X.........iiiiii iaaaaannnnnddddd      Rt Ra Rn imm(im7,sh)
10972             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10973             imm   = emitGetInsSC(id);
10974             scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10975             imm <<= scale;
10976             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10977             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10978             emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
10979             break;
10980
10981         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
10982             assert(insOptsNone(id->idInsOpt()));
10983             emitDispReg(id->idReg1(), EA_4BYTE, true);
10984             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10985             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10986             break;
10987
10988         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....      Rn       imm(i12,sh)
10989             emitDispReg(id->idReg1(), size, true);
10990             emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10991             break;
10992
10993         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
10994             emitDispReg(id->idReg1(), size, true);
10995             hwi.immHWVal = (unsigned)emitGetInsSC(id);
10996             if (ins == INS_mov)
10997             {
10998                 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
10999             }
11000             else // movz, movn, movk
11001             {
11002                 emitDispImm(hwi.immVal, false);
11003                 if (hwi.immHW != 0)
11004                 {
11005                     emitDispShiftOpts(INS_OPTS_LSL);
11006                     emitDispImm(hwi.immHW * 16, false);
11007                 }
11008             }
11009             break;
11010
11011         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
11012             emitDispReg(id->idReg1(), size, true);
11013             bmi.immNRS = (unsigned)emitGetInsSC(id);
11014             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11015             break;
11016
11017         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
11018             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11019             bmi.immNRS = (unsigned)emitGetInsSC(id);
11020             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11021             break;
11022
11023         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
11024             if ((ins == INS_add) || (ins == INS_sub))
11025             {
11026                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11027                 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11028             }
11029             else
11030             {
11031                 emitDispReg(id->idReg1(), size, true);
11032                 emitDispReg(id->idReg2(), size, true);
11033             }
11034             emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
11035             break;
11036
11037         case IF_DI_2B: // DI_2B   X........X.nnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
11038             emitDispReg(id->idReg1(), size, true);
11039             emitDispReg(id->idReg2(), size, true);
11040             emitDispImm(emitGetInsSC(id), false);
11041             break;
11042
11043         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
11044             if (ins == INS_ands)
11045             {
11046                 emitDispReg(id->idReg1(), size, true);
11047             }
11048             else
11049             {
11050                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11051             }
11052             emitDispReg(id->idReg2(), size, true);
11053             bmi.immNRS = (unsigned)emitGetInsSC(id);
11054             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11055             break;
11056
11057         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, ims   (N,r,s)
11058             emitDispReg(id->idReg1(), size, true);
11059             emitDispReg(id->idReg2(), size, true);
11060
11061             imm        = emitGetInsSC(id);
11062             bmi.immNRS = (unsigned)imm;
11063
11064             switch (ins)
11065             {
11066                 case INS_bfm:
11067                 case INS_sbfm:
11068                 case INS_ubfm:
11069                     emitDispImm(bmi.immR, true);
11070                     emitDispImm(bmi.immS, false);
11071                     break;
11072
11073                 case INS_bfi:
11074                 case INS_sbfiz:
11075                 case INS_ubfiz:
11076                     emitDispImm(getBitWidth(size) - bmi.immR, true);
11077                     emitDispImm(bmi.immS + 1, false);
11078                     break;
11079
11080                 case INS_bfxil:
11081                 case INS_sbfx:
11082                 case INS_ubfx:
11083                     emitDispImm(bmi.immR, true);
11084                     emitDispImm(bmi.immS - bmi.immR + 1, false);
11085                     break;
11086
11087                 case INS_asr:
11088                 case INS_lsr:
11089                 case INS_lsl:
11090                     emitDispImm(imm, false);
11091                     break;
11092
11093                 default:
11094                     assert(!"Unexpected instruction in IF_DI_2D");
11095             }
11096
11097             break;
11098
11099         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
11100             emitDispReg(id->idReg1(), size, true);
11101             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11102             emitDispImm(cfi.imm5, true);
11103             emitDispFlags(cfi.flags);
11104             printf(",");
11105             emitDispCond(cfi.cond);
11106             break;
11107
11108         case IF_DR_1D: // DR_1D   X............... cccc.......mmmmm      Rd       cond
11109             emitDispReg(id->idReg1(), size, true);
11110             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11111             emitDispCond(cfi.cond);
11112             break;
11113
11114         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
11115             emitDispReg(id->idReg1(), size, true);
11116             emitDispReg(id->idReg2(), size, false);
11117             break;
11118
11119         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
11120             emitDispReg(id->idReg1(), size, true);
11121             emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11122             break;
11123
11124         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
11125             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11126             imm = emitGetInsSC(id);
11127             emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
11128             break;
11129
11130         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
11131             emitDispReg(id->idReg1(), size, true);
11132             emitDispReg(id->idReg2(), size, true);
11133             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11134             emitDispCond(cfi.cond);
11135             break;
11136
11137         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
11138         case IF_DR_2J: // DR_2J   ................ ......nnnnnddddd      Sd    Sn
11139             emitDispReg(id->idReg1(), size, true);
11140             emitDispReg(id->idReg2(), size, false);
11141             break;
11142
11143         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
11144             emitDispReg(id->idReg1(), size, true);
11145             emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11146             break;
11147
11148         case IF_DR_2G: // DR_2G   X............... ......nnnnnddddd      Rd Rn
11149             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11150             emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11151             break;
11152
11153         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
11154             emitDispReg(id->idReg1(), size, true);
11155             emitDispReg(id->idReg2(), size, false);
11156             break;
11157
11158         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
11159             emitDispReg(id->idReg1(), size, true);
11160             emitDispReg(id->idReg2(), size, true);
11161             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11162             emitDispFlags(cfi.flags);
11163             printf(",");
11164             emitDispCond(cfi.cond);
11165             break;
11166
11167         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
11168             if ((ins == INS_add) || (ins == INS_sub))
11169             {
11170                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11171                 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11172             }
11173             else if ((ins == INS_smull) || (ins == INS_smulh))
11174             {
11175                 // Rd is always 8 bytes
11176                 emitDispReg(id->idReg1(), EA_8BYTE, true);
11177
11178                 // Rn, Rm effective size depends on instruction type
11179                 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11180                 emitDispReg(id->idReg2(), size, true);
11181             }
11182             else
11183             {
11184                 emitDispReg(id->idReg1(), size, true);
11185                 emitDispReg(id->idReg2(), size, true);
11186             }
11187             if (id->idIsLclVar())
11188             {
11189                 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11190             }
11191             else
11192             {
11193                 emitDispReg(id->idReg3(), size, false);
11194             }
11195
11196             break;
11197
11198         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11199             emitDispReg(id->idReg1(), size, true);
11200             emitDispReg(id->idReg2(), size, true);
11201             emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11202             break;
11203
11204         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
11205             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11206             emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11207             imm = emitGetInsSC(id);
11208             emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11209             break;
11210
11211         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnmmmmm      Rd Rn Rm cond
11212             emitDispReg(id->idReg1(), size, true);
11213             emitDispReg(id->idReg2(), size, true);
11214             emitDispReg(id->idReg3(), size, true);
11215             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11216             emitDispCond(cfi.cond);
11217             break;
11218
11219         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
11220             emitDispReg(id->idReg1(), size, true);
11221             emitDispReg(id->idReg2(), size, true);
11222             emitDispReg(id->idReg3(), size, true);
11223             emitDispImm(emitGetInsSC(id), false);
11224             break;
11225
11226         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnmmmmm      Rd Rn Rm Ra
11227             emitDispReg(id->idReg1(), size, true);
11228             emitDispReg(id->idReg2(), size, true);
11229             emitDispReg(id->idReg3(), size, true);
11230             emitDispReg(id->idReg4(), size, false);
11231             break;
11232
11233         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8 (fmov - immediate scalar)
11234             elemsize = id->idOpSize();
11235             emitDispReg(id->idReg1(), elemsize, true);
11236             emitDispFloatImm(emitGetInsSC(id));
11237             break;
11238
11239         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8 (immediate vector)
11240             imm      = emitGetInsSC(id) & 0x0ff;
11241             immShift = (emitGetInsSC(id) & 0x700) >> 8;
11242             hasShift = (immShift != 0);
11243             elemsize = optGetElemsize(id->idInsOpt());
11244             if (id->idInsOpt() == INS_OPTS_1D)
11245             {
11246                 assert(elemsize == size);
11247                 emitDispReg(id->idReg1(), size, true);
11248             }
11249             else
11250             {
11251                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11252             }
11253             if (ins == INS_fmov)
11254             {
11255                 emitDispFloatImm(imm);
11256                 assert(hasShift == false);
11257             }
11258             else
11259             {
11260                 if (elemsize == EA_8BYTE)
11261                 {
11262                     assert(ins == INS_movi);
11263                     ssize_t       imm64 = 0;
11264                     const ssize_t mask8 = 0xFF;
11265                     for (unsigned b = 0; b < 8; b++)
11266                     {
11267                         if (imm & (1 << b))
11268                         {
11269                             imm64 |= (mask8 << (b * 8));
11270                         }
11271                     }
11272                     emitDispImm(imm64, hasShift, true);
11273                 }
11274                 else
11275                 {
11276                     emitDispImm(imm, hasShift, true);
11277                 }
11278                 if (hasShift)
11279                 {
11280                     insOpts  opt   = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11281                     unsigned shift = (immShift & 0x3) * 8;
11282                     emitDispShiftOpts(opt);
11283                     emitDispImm(shift, false);
11284                 }
11285             }
11286             break;
11287
11288         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0 (fcmp - with zero)
11289             elemsize = id->idOpSize();
11290             emitDispReg(id->idReg1(), elemsize, true);
11291             emitDispFloatZero();
11292             break;
11293
11294         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn   (fabs, fcvt - vector)
11295         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn   (abs, neg   - vector)
11296         case IF_DV_2P: // DV_2P   ................ ......nnnnnddddd      Vd Vn   (aes*, sha1su1)
11297             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11298             emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11299             break;
11300
11301         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
11302             elemsize = id->idOpSize();
11303             emitDispReg(id->idReg1(), elemsize, true);
11304             emitDispReg(id->idReg2(), elemsize, true);
11305             emitDispImm(emitGetInsSC(id), false);
11306             break;
11307
11308         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
11309             imm = emitGetInsSC(id);
11310             // Do we have a sxtl or uxtl instruction?
11311             isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11312             code          = emitInsCode(ins, fmt);
11313             if (code & 0x00008000) // widen/narrow opcodes
11314             {
11315                 if (code & 0x00002000) // SHL opcodes
11316                 {
11317                     emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11318                     emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11319                 }
11320                 else // SHR opcodes
11321                 {
11322                     emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11323                     emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11324                 }
11325             }
11326             else
11327             {
11328                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11329                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11330             }
11331             // Print the immediate unless we have a sxtl or uxtl instruction
11332             if (!isExtendAlias)
11333             {
11334                 emitDispImm(imm, false);
11335             }
11336             break;
11337
11338         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[] (umov/smov    - to general)
11339             srcsize = id->idOpSize();
11340             index   = emitGetInsSC(id);
11341             if (ins == INS_smov)
11342             {
11343                 dstsize = EA_8BYTE;
11344             }
11345             else // INS_umov or INS_mov
11346             {
11347                 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11348             }
11349             emitDispReg(id->idReg1(), dstsize, true);
11350             emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11351             break;
11352
11353         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn   (dup/ins - vector from general)
11354             if (ins == INS_dup)
11355             {
11356                 datasize = id->idOpSize();
11357                 assert(isValidVectorDatasize(datasize));
11358                 assert(isValidArrangement(datasize, id->idInsOpt()));
11359                 elemsize = optGetElemsize(id->idInsOpt());
11360                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11361             }
11362             else // INS_ins
11363             {
11364                 elemsize = id->idOpSize();
11365                 index    = emitGetInsSC(id);
11366                 assert(isValidVectorElemsize(elemsize));
11367                 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11368             }
11369             emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11370             break;
11371
11372         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]   (dup - vector)
11373             datasize = id->idOpSize();
11374             assert(isValidVectorDatasize(datasize));
11375             assert(isValidArrangement(datasize, id->idInsOpt()));
11376             elemsize = optGetElemsize(id->idInsOpt());
11377             index    = emitGetInsSC(id);
11378             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11379             emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11380             break;
11381
11382         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]   (dup - scalar)
11383             elemsize = id->idOpSize();
11384             index    = emitGetInsSC(id);
11385             emitDispReg(id->idReg1(), elemsize, true);
11386             emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11387             break;
11388
11389         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
11390             imm      = emitGetInsSC(id);
11391             index    = (imm >> 4) & 0xf;
11392             index2   = imm & 0xf;
11393             elemsize = id->idOpSize();
11394             emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11395             emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11396             break;
11397
11398         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov, fcvtXX - register)
11399         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
11400         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
11401             elemsize = id->idOpSize();
11402             emitDispReg(id->idReg1(), elemsize, true);
11403             emitDispReg(id->idReg2(), elemsize, false);
11404             break;
11405
11406         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov, fcvtXX - to general)
11407         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov, Xcvtf - from general)
11408         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
11409             dstsize = optGetDstsize(id->idInsOpt());
11410             srcsize = optGetSrcsize(id->idInsOpt());
11411
11412             emitDispReg(id->idReg1(), dstsize, true);
11413             emitDispReg(id->idReg2(), srcsize, false);
11414             break;
11415
11416         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11417         case IF_DV_3B: // DV_3B   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11418             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11419             emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11420             emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11421             break;
11422
11423         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11424             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11425             if (ins != INS_mov)
11426             {
11427                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11428             }
11429             emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11430             break;
11431
11432         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
11433         case IF_DV_3BI: // DV_3BI  .Q........Lmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
11434             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11435             emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11436             elemsize = optGetElemsize(id->idInsOpt());
11437             emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11438             break;
11439
11440         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
11441         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
11442             emitDispReg(id->idReg1(), size, true);
11443             emitDispReg(id->idReg2(), size, true);
11444             emitDispReg(id->idReg3(), size, false);
11445             break;
11446
11447         case IF_DV_3F: // DV_3F   ..........mmmmm ......nnnnnddddd       Vd Vn Vm (vector)
11448             if ((ins == INS_sha1c) || (ins == INS_sha1m) || (ins == INS_sha1p))
11449             {
11450                 // Qd, Sn, Vm (vector)
11451                 emitDispReg(id->idReg1(), size, true);
11452                 emitDispReg(id->idReg2(), EA_4BYTE, true);
11453                 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11454             }
11455             else if ((ins == INS_sha256h) || (ins == INS_sha256h2))
11456             {
11457                 // Qd Qn Vm (vector)
11458                 emitDispReg(id->idReg1(), size, true);
11459                 emitDispReg(id->idReg2(), size, true);
11460                 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11461             }
11462             else // INS_sha1su0, INS_sha256su1
11463             {
11464                 // Vd, Vn, Vm   (vector)
11465                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11466                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11467                 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11468             }
11469             break;
11470
11471         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
11472             emitDispReg(id->idReg1(), size, true);
11473             emitDispReg(id->idReg2(), size, true);
11474             elemsize = size;
11475             emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11476             break;
11477
11478         case IF_DV_4A: // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
11479             emitDispReg(id->idReg1(), size, true);
11480             emitDispReg(id->idReg2(), size, true);
11481             emitDispReg(id->idReg3(), size, true);
11482             emitDispReg(id->idReg4(), size, false);
11483             break;
11484
11485         case IF_SN_0A: // SN_0A   ................ ................
11486             break;
11487
11488         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
11489             emitDispImm(emitGetInsSC(id), false);
11490             break;
11491
11492         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
11493             emitDispBarrier((insBarrier)emitGetInsSC(id));
11494             break;
11495
11496         default:
11497             printf("unexpected format %s", emitIfName(id->idInsFmt()));
11498             assert(!"unexpectedFormat");
11499             break;
11500     }
11501
11502     if (id->idDebugOnlyInfo()->idVarRefOffs)
11503     {
11504         printf("\t// ");
11505         emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11506                          id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11507     }
11508
11509     printf("\n");
11510 }
11511
11512 /*****************************************************************************
11513  *
11514  *  Display a stack frame reference.
11515  */
11516
11517 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11518 {
11519     printf("[");
11520
11521     if (varx < 0)
11522         printf("TEMP_%02u", -varx);
11523     else
11524         emitComp->gtDispLclVar(+varx, false);
11525
11526     if (disp < 0)
11527         printf("-0x%02x", -disp);
11528     else if (disp > 0)
11529         printf("+0x%02x", +disp);
11530
11531     printf("]");
11532
11533     if (varx >= 0 && emitComp->opts.varNames)
11534     {
11535         LclVarDsc*  varDsc;
11536         const char* varName;
11537
11538         assert((unsigned)varx < emitComp->lvaCount);
11539         varDsc  = emitComp->lvaTable + varx;
11540         varName = emitComp->compLocalVarName(varx, offs);
11541
11542         if (varName)
11543         {
11544             printf("'%s", varName);
11545
11546             if (disp < 0)
11547                 printf("-%d", -disp);
11548             else if (disp > 0)
11549                 printf("+%d", +disp);
11550
11551             printf("'");
11552         }
11553     }
11554 }
11555
11556 #endif // DEBUG
11557
11558 // Generate code for a load or store operation with a potentially complex addressing mode
11559 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11560 // Since Arm64 does not directly support this complex of an addressing mode
11561 // we may generates up to three instructions for this for Arm64
11562 //
11563 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11564 {
11565     emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11566
11567     GenTree* addr = indir->Addr();
11568
11569     if (addr->isContained())
11570     {
11571         assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11572
11573         int   offset = 0;
11574         DWORD lsl    = 0;
11575
11576         if (addr->OperGet() == GT_LEA)
11577         {
11578             offset = addr->AsAddrMode()->Offset();
11579             if (addr->AsAddrMode()->gtScale > 0)
11580             {
11581                 assert(isPow2(addr->AsAddrMode()->gtScale));
11582                 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11583             }
11584         }
11585
11586         GenTree* memBase = indir->Base();
11587
11588         if (indir->HasIndex())
11589         {
11590             GenTree* index = indir->Index();
11591
11592             if (offset != 0)
11593             {
11594                 regNumber tmpReg = indir->GetSingleTempReg();
11595
11596                 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11597
11598                 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11599                 {
11600                     if (lsl > 0)
11601                     {
11602                         // Generate code to set tmpReg = base + index*scale
11603                         emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11604                                         INS_OPTS_LSL);
11605                     }
11606                     else // no scale
11607                     {
11608                         // Generate code to set tmpReg = base + index
11609                         emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11610                     }
11611
11612                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11613
11614                     // Then load/store dataReg from/to [tmpReg + offset]
11615                     emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11616                 }
11617                 else // large offset
11618                 {
11619                     // First load/store tmpReg with the large offset constant
11620                     codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11621                     // Then add the base register
11622                     //      rd = rd + base
11623                     emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11624
11625                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11626                     noway_assert(tmpReg != index->gtRegNum);
11627
11628                     // Then load/store dataReg from/to [tmpReg + index*scale]
11629                     emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11630                 }
11631             }
11632             else // (offset == 0)
11633             {
11634                 if (lsl > 0)
11635                 {
11636                     // Then load/store dataReg from/to [memBase + index*scale]
11637                     emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11638                 }
11639                 else // no scale
11640                 {
11641                     // Then load/store dataReg from/to [memBase + index]
11642                     emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11643                 }
11644             }
11645         }
11646         else // no Index register
11647         {
11648             if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11649             {
11650                 // Then load/store dataReg from/to [memBase + offset]
11651                 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11652             }
11653             else
11654             {
11655                 // We require a tmpReg to hold the offset
11656                 regNumber tmpReg = indir->GetSingleTempReg();
11657
11658                 // First load/store tmpReg with the large offset constant
11659                 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11660
11661                 // Then load/store dataReg from/to [memBase + tmpReg]
11662                 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11663             }
11664         }
11665     }
11666     else // addr is not contained, so we evaluate it into a register
11667     {
11668         // Then load/store dataReg from/to [addrReg]
11669         emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11670     }
11671 }
11672
11673 // The callee must call genConsumeReg() for any non-contained srcs
11674 // and genProduceReg() for any non-contained dsts.
11675
11676 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11677 {
11678     regNumber result = REG_NA;
11679
11680     // dst can only be a reg
11681     assert(!dst->isContained());
11682
11683     // src can be immed or reg
11684     assert(!src->isContained() || src->isContainedIntOrIImmed());
11685
11686     // find immed (if any) - it cannot be a dst
11687     GenTreeIntConCommon* intConst = nullptr;
11688     if (src->isContainedIntOrIImmed())
11689     {
11690         intConst = src->AsIntConCommon();
11691     }
11692
11693     if (intConst)
11694     {
11695         emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11696         return dst->gtRegNum;
11697     }
11698     else
11699     {
11700         emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11701         return dst->gtRegNum;
11702     }
11703 }
11704
11705 // The callee must call genConsumeReg() for any non-contained srcs
11706 // and genProduceReg() for any non-contained dsts.
11707
11708 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11709 {
11710     regNumber result = REG_NA;
11711
11712     // dst can only be a reg
11713     assert(!dst->isContained());
11714
11715     // find immed (if any) - it cannot be a dst
11716     // Only one src can be an int.
11717     GenTreeIntConCommon* intConst  = nullptr;
11718     GenTree*             nonIntReg = nullptr;
11719
11720     if (varTypeIsFloating(dst))
11721     {
11722         // src1 can only be a reg
11723         assert(!src1->isContained());
11724         // src2 can only be a reg
11725         assert(!src2->isContained());
11726     }
11727     else // not floating point
11728     {
11729         // src2 can be immed or reg
11730         assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11731
11732         // Check src2 first as we can always allow it to be a contained immediate
11733         if (src2->isContainedIntOrIImmed())
11734         {
11735             intConst  = src2->AsIntConCommon();
11736             nonIntReg = src1;
11737         }
11738         // Only for commutative operations do we check src1 and allow it to be a contained immediate
11739         else if (dst->OperIsCommutative())
11740         {
11741             // src1 can be immed or reg
11742             assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11743
11744             // Check src1 and allow it to be a contained immediate
11745             if (src1->isContainedIntOrIImmed())
11746             {
11747                 assert(!src2->isContainedIntOrIImmed());
11748                 intConst  = src1->AsIntConCommon();
11749                 nonIntReg = src2;
11750             }
11751         }
11752         else
11753         {
11754             // src1 can only be a reg
11755             assert(!src1->isContained());
11756         }
11757     }
11758
11759     bool isMulOverflow = false;
11760     if (dst->gtOverflowEx())
11761     {
11762         if ((ins == INS_add) || (ins == INS_adds))
11763         {
11764             ins = INS_adds;
11765         }
11766         else if ((ins == INS_sub) || (ins == INS_subs))
11767         {
11768             ins = INS_subs;
11769         }
11770         else if (ins == INS_mul)
11771         {
11772             isMulOverflow = true;
11773             assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11774         }
11775         else
11776         {
11777             assert(!"Invalid ins for overflow check");
11778         }
11779     }
11780     if (intConst != nullptr)
11781     {
11782         emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11783     }
11784     else
11785     {
11786         if (isMulOverflow)
11787         {
11788             regNumber extraReg = dst->GetSingleTempReg();
11789             assert(extraReg != dst->gtRegNum);
11790
11791             if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11792             {
11793                 if (attr == EA_4BYTE)
11794                 {
11795                     // Compute 8 byte results from 4 byte by 4 byte multiplication.
11796                     emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11797
11798                     // Get the high result by shifting dst.
11799                     emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11800                 }
11801                 else
11802                 {
11803                     assert(attr == EA_8BYTE);
11804                     // Compute the high result.
11805                     emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11806
11807                     // Now multiply without skewing the high result.
11808                     emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11809                 }
11810
11811                 // zero-sign bit comparison to detect overflow.
11812                 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11813             }
11814             else
11815             {
11816                 int bitShift = 0;
11817                 if (attr == EA_4BYTE)
11818                 {
11819                     // Compute 8 byte results from 4 byte by 4 byte multiplication.
11820                     emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11821
11822                     // Get the high result by shifting dst.
11823                     emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11824
11825                     bitShift = 31;
11826                 }
11827                 else
11828                 {
11829                     assert(attr == EA_8BYTE);
11830                     // Save the high result in a temporary register.
11831                     emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11832
11833                     // Now multiply without skewing the high result.
11834                     emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11835
11836                     bitShift = 63;
11837                 }
11838
11839                 // Sign bit comparison to detect overflow.
11840                 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11841             }
11842         }
11843         else
11844         {
11845             // We can just multiply.
11846             emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11847         }
11848     }
11849
11850     if (dst->gtOverflowEx())
11851     {
11852         assert(!varTypeIsFloating(dst));
11853         codeGen->genCheckOverflow(dst);
11854     }
11855
11856     return dst->gtRegNum;
11857 }
11858
11859 #endif // defined(_TARGET_ARM64_)