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