Merge pull request #6620 from hqueue/fix/typo_20160805
[platform/upstream/coreclr.git] / src / jit / emitarm64.h
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
6 #if defined(_TARGET_ARM64_)
7
8 // The ARM64 instructions are all 32 bits in size.
9 // we use an unsigned int to hold the encoded instructions.
10 // This typedef defines the type that we use to hold encoded instructions.
11 //
12 typedef unsigned int code_t;
13
14
15     static bool strictArmAsm;
16
17     /************************************************************************/
18     /*         Routines that compute the size of / encode instructions      */
19     /************************************************************************/
20
21     struct CnsVal
22     {
23         ssize_t cnsVal;
24 #ifdef RELOC_SUPPORT
25         bool cnsReloc;
26 #endif
27     };
28
29 #ifdef  DEBUG
30
31     /************************************************************************/
32     /*             Debug-only routines to display instructions              */
33     /************************************************************************/
34
35     const   char *  emitFPregName   (unsigned       reg,
36                                      bool           varName = true);
37     const   char *  emitVectorRegName(regNumber reg);
38
39     void            emitDispInst    (instruction ins);
40     void            emitDispReloc   (int value, bool addComma);
41     void            emitDispImm     (ssize_t imm, bool addComma, bool alwaysHex = false);
42     void            emitDispFloatZero();
43     void            emitDispFloatImm(ssize_t imm8);
44     void            emitDispImmOptsLSL12(ssize_t imm, insOpts opt);
45     void            emitDispCond    (insCond    cond);
46     void            emitDispFlags   (insCflags  flags);
47     void            emitDispBarrier (insBarrier barrier);
48     void            emitDispShiftOpts(insOpts opt);
49     void            emitDispExtendOpts(insOpts opt);
50     void            emitDispLSExtendOpts(insOpts opt);
51     void            emitDispReg     (regNumber reg, emitAttr  attr, bool addComma);
52     void            emitDispVectorReg (regNumber reg, insOpts opt, bool addComma);
53     void            emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma);
54     void            emitDispArrangement(insOpts opt);
55     void            emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr);
56     void            emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm);
57     void            emitDispAddrRI  (regNumber reg, insOpts opt, ssize_t imm);
58     void            emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size);
59
60     void            emitDispIns     (instrDesc *id, bool isNew, bool doffs, bool asmfm, 
61                                      unsigned offs = 0, BYTE * pCode = 0, size_t sz = 0,
62                                      insGroup *ig = NULL);
63 #endif // DEBUG
64
65     /************************************************************************/
66     /*  Private members that deal with target-dependent instr. descriptors  */
67     /************************************************************************/
68
69 private:
70
71     instrDesc      *emitNewInstrAmd     (emitAttr attr, int dsp);
72     instrDesc      *emitNewInstrAmdCns  (emitAttr attr, int dsp, int cns);
73
74     instrDesc      *emitNewInstrCallDir (int        argCnt,
75                                          VARSET_VALARG_TP GCvars,
76                                          regMaskTP  gcrefRegs,
77                                          regMaskTP  byrefRegs,
78                                          emitAttr   retSize,
79                                          emitAttr  secondRetSize);
80
81     instrDesc      *emitNewInstrCallInd( int        argCnt,
82                                          ssize_t    disp,
83                                          VARSET_VALARG_TP GCvars,
84                                          regMaskTP  gcrefRegs,
85                                          regMaskTP  byrefRegs,
86                                          emitAttr   retSize,
87                                          emitAttr  secondRetSize);
88
89     void            emitGetInsCns   (instrDesc *id, CnsVal *cv);
90     ssize_t         emitGetInsAmdCns(instrDesc *id, CnsVal *cv);
91     void            emitGetInsDcmCns(instrDesc *id, CnsVal *cv);
92     ssize_t         emitGetInsAmdAny(instrDesc *id);
93
94     /************************************************************************/
95     /*               Private helpers for instruction output                 */
96     /************************************************************************/
97
98 private:
99
100     bool                    emitInsIsCompare(instruction ins);
101     bool                    emitInsIsLoad   (instruction ins);
102     bool                    emitInsIsStore  (instruction ins);
103     bool                    emitInsIsLoadOrStore(instruction ins);
104     emitAttr                emitInsAdjustLoadStoreAttr(instruction ins, emitAttr attr);
105     emitAttr                emitInsTargetRegSize(instrDesc *id);
106     emitAttr                emitInsLoadStoreSize(instrDesc *id);
107
108     emitter::insFormat      emitInsFormat(instruction ins);
109     emitter::code_t         emitInsCode(instruction ins, insFormat fmt);
110
111     // Generate code for a load or store operation and handle the case of contained GT_LEA op1 with [base + index<<scale + offset]
112     void                    emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir);
113
114     //  Emit the 32-bit Arm64 instruction 'code' into the 'dst'  buffer
115     static unsigned         emitOutput_Instr(BYTE *dst, code_t code);
116
117     // A helper method to return the natural scale for an EA 'size'
118     static unsigned NaturalScale_helper(emitAttr size);
119
120     // A helper method to perform a Rotate-Right shift operation 
121     static UINT64  ROR_helper(UINT64 value, unsigned sh, unsigned width);
122
123     // A helper method to perform a 'NOT' bitwise complement operation 
124     static UINT64  NOT_helper(UINT64 value, unsigned width);
125
126     // A helper method to perform a bit Replicate operation
127     static UINT64  Replicate_helper(UINT64 value, unsigned width, emitAttr size);
128
129
130     /************************************************************************
131     *
132     * This union is used to to encode/decode the special ARM64 immediate values
133     * that is listed as imm(N,r,s) and referred to as 'bitmask immediate'
134     */
135
136     union bitMaskImm
137     {
138         struct {
139             unsigned immS:6;   // bits 0..5
140             unsigned immR:6;   // bits 6..11
141             unsigned immN:1;   // bits 12
142         };
143         unsigned immNRS;  // concat N:R:S forming a 13-bit unsigned immediate
144     };
145
146     /************************************************************************
147     *
148     *  Convert between a 64-bit immediate and its 'bitmask immediate'
149     *   representation imm(i16,hw)
150     */
151
152     static emitter::bitMaskImm emitEncodeBitMaskImm(INT64 imm,  emitAttr size);
153
154     static INT64               emitDecodeBitMaskImm(const emitter::bitMaskImm bmImm,
155                                                     emitAttr size);
156
157
158     /************************************************************************
159     *
160     * This union is used to to encode/decode the special ARM64 immediate values
161     * that is listed as imm(i16,hw) and referred to as 'halfword immediate'
162     */
163
164     union halfwordImm
165     {
166         struct {
167             unsigned immVal:16;   // bits  0..15
168             unsigned immHW:2;     // bits 16..17
169         };
170         unsigned immHWVal;  // concat HW:Val forming a 18-bit unsigned immediate
171     };
172
173     /************************************************************************
174     *
175     *  Convert between a 64-bit immediate and its 'halfword immediate'
176     *   representation imm(i16,hw)
177     */
178
179     static emitter::halfwordImm emitEncodeHalfwordImm(INT64 imm,  emitAttr size);
180
181     static INT64                emitDecodeHalfwordImm(const emitter::halfwordImm hwImm,
182                                                       emitAttr size);
183
184     /************************************************************************
185     *
186     * This union is used to encode/decode the special ARM64 immediate values
187     * that is listed as imm(i16,by) and referred to as 'byteShifted immediate'
188     */
189
190     union byteShiftedImm
191     {
192         struct {
193             unsigned immVal:8;   // bits  0..7
194             unsigned immBY:2;    // bits  8..9
195             unsigned immOnes:1;  // bit   10
196         };
197         unsigned immBSVal;  // concat Ones:BY:Val forming a 10-bit unsigned immediate
198     };
199
200     /************************************************************************
201     *
202     *  Convert between a 16/32-bit immediate and its 'byteShifted immediate'
203     *   representation imm(i8,by)
204     */
205
206     static emitter::byteShiftedImm  emitEncodeByteShiftedImm(INT64 imm, emitAttr size, bool allow_MSL);
207
208     static INT32  emitDecodeByteShiftedImm(const emitter::byteShiftedImm bsImm,
209                                            emitAttr size);
210
211     /************************************************************************
212     *
213     * This union is used to to encode/decode the special ARM64 immediate values
214     * that are use for FMOV immediate and referred to as 'float 8-bit immediate'
215     */
216
217     union floatImm8
218     {
219         struct {
220             unsigned immMant:4;   // bits 0..3
221             unsigned immExp:3;    // bits 4..6
222             unsigned immSign:1;   // bits 7
223         };
224         unsigned immFPIVal;  // concat Sign:Exp:Mant forming an 8-bit unsigned immediate
225     };
226
227     /************************************************************************
228     *
229     *  Convert between a double and its 'float 8-bit immediate' representation
230     */
231
232     static emitter::floatImm8   emitEncodeFloatImm8(double immDbl);
233
234     static double               emitDecodeFloatImm8(const emitter::floatImm8 fpImm);
235
236     /************************************************************************
237     *
238     *  This union is used to to encode/decode the cond, nzcv and imm5 values for 
239     *   instructions that use them in the small constant immediate field
240     */
241
242     union condFlagsImm
243     {
244         struct {
245             insCond    cond :4;     // bits  0..3
246             insCflags  flags:4;     // bits  4..7
247             unsigned   imm5 :5;     // bits  8..12
248         };
249         unsigned immCFVal;          // concat imm5:flags:cond forming an 13-bit unsigned immediate
250     };
251
252     // Returns an encoding for the specified register used in the 'Rd' position
253     static code_t  insEncodeReg_Rd(regNumber reg);
254
255     // Returns an encoding for the specified register used in the 'Rt' position
256     static code_t  insEncodeReg_Rt(regNumber reg);
257
258     // Returns an encoding for the specified register used in the 'Rn' position
259     static code_t  insEncodeReg_Rn(regNumber reg);
260
261     // Returns an encoding for the specified register used in the 'Rm' position
262     static code_t  insEncodeReg_Rm(regNumber reg);
263
264     // Returns an encoding for the specified register used in the 'Ra' position
265     static code_t  insEncodeReg_Ra(regNumber reg);
266
267     // Returns an encoding for the specified register used in the 'Vd' position
268     static code_t  insEncodeReg_Vd(regNumber reg);
269
270     // Returns an encoding for the specified register used in the 'Vt' position
271     static code_t  insEncodeReg_Vt(regNumber reg);
272
273     // Returns an encoding for the specified register used in the 'Vn' position
274     static code_t  insEncodeReg_Vn(regNumber reg);
275
276     // Returns an encoding for the specified register used in the 'Vm' position
277     static code_t  insEncodeReg_Vm(regNumber reg);
278
279     // Returns an encoding for the specified register used in the 'Va' position
280     static code_t  insEncodeReg_Va(regNumber reg);
281
282     // Returns an encoding for the imm which represents the condition code.
283     static code_t  insEncodeCond(insCond cond);
284
285     // Returns an encoding for the imm whioch represents the 'condition code' 
286     //  with the lowest bit inverted (marked by invert(<cond>) in the architecture manual.
287     static code_t  insEncodeInvertedCond(insCond cond);
288
289     // Returns an encoding for the imm which represents the flags.
290     static code_t  insEncodeFlags(insCflags flags);
291
292     // Returns the encoding for the Shift Count bits to be used for Arm64 encodings
293     static code_t  insEncodeShiftCount(ssize_t imm, emitAttr  size);
294
295     // Returns the encoding to select the datasize for most Arm64 instructions
296     static code_t  insEncodeDatasize(emitAttr  size);
297
298     // Returns the encoding to select the datasize for the general load/store Arm64 instructions
299     static code_t  insEncodeDatasizeLS(code_t code, emitAttr  size);
300
301     // Returns the encoding to select the datasize for the vector load/store Arm64 instructions
302     static code_t  insEncodeDatasizeVLS(code_t code, emitAttr size);
303
304     // Returns the encoding to select the datasize for the vector load/store pair Arm64 instructions
305     static code_t  insEncodeDatasizeVPLS(code_t code, emitAttr size);
306
307     // Returns the encoding to select the datasize for bitfield Arm64 instructions
308     static code_t  insEncodeDatasizeBF(code_t code, emitAttr  size);
309
310     // Returns the encoding to select the vectorsize for SIMD Arm64 instructions
311     static code_t  insEncodeVectorsize(emitAttr  size);
312
313     // Returns the encoding to select 'index' for an Arm64 vector elem instruction
314     static code_t  insEncodeVectorIndex(emitAttr elemsize, ssize_t index);
315
316     // Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
317     static code_t  insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2);
318
319     // Returns the encoding to select 'index' for an Arm64 'mul' elem instruction
320     static code_t  insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index);
321
322     // Returns the encoding to shift by 'shift' bits for an Arm64 vector or scalar instruction
323     static code_t  insEncodeVectorShift(emitAttr size, ssize_t shift);
324
325     // Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
326     static code_t  insEncodeElemsize(emitAttr  size);
327
328     // Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
329     static code_t  insEncodeFloatElemsize(emitAttr  size);
330
331      // Returns the encoding to select the index for an Arm64 float vector by elem instruction
332     static code_t  insEncodeFloatIndex(emitAttr elemsize, ssize_t index);
333
334     // Returns the encoding to select the 'conversion' operation for a type 'fmt' Arm64 instruction
335     static code_t  insEncodeConvertOpt(insFormat fmt, insOpts conversion);
336
337     // Returns the encoding to have the Rn register of a ld/st reg be Pre/Post/Not indexed updated
338     static code_t  insEncodeIndexedOpt(insOpts opt);
339
340     // Returns the encoding to have the Rn register of a ld/st pair be Pre/Post/Not indexed updated
341     static code_t  insEncodePairIndexedOpt(instruction ins, insOpts opt);
342
343     // Returns the encoding to apply a Shift Type on the Rm register
344     static code_t  insEncodeShiftType(insOpts opt);
345
346     // Returns the encoding to apply a 12 bit left shift to the immediate
347     static code_t  insEncodeShiftImm12(insOpts opt);
348
349     // Returns the encoding to have the Rm register use an extend operation 
350     static code_t  insEncodeExtend(insOpts opt);
351
352     // Returns the encoding to scale the Rm register by {0,1,2,3,4} in an extend operation
353     static code_t  insEncodeExtendScale(ssize_t imm);
354
355     // Returns the encoding to have the Rm register be auto scaled by the ld/st size 
356     static code_t  insEncodeReg3Scale(bool isScaled);
357
358     // Returns true if 'reg' represents an integer register.
359     static bool isIntegerRegister (regNumber reg)
360                 { return (reg >= REG_INT_FIRST) && (reg <= REG_INT_LAST); }
361
362     // Returns true if 'value' is a legal unsigned immediate 8 bit encoding (such as for fMOV).
363     static bool isValidUimm8(ssize_t value)
364                 { return (0 <= value) && (value <= 0xFFLL); };
365
366     // Returns true if 'value' is a legal unsigned immediate 12 bit encoding (such as for CMP, CMN).
367     static bool isValidUimm12(ssize_t value)
368                 { return (0 <= value) && (value <= 0xFFFLL); };
369
370     // Returns true if 'value' is a legal unsigned immediate 16 bit encoding (such as for MOVZ, MOVN, MOVK).
371     static bool isValidUimm16(ssize_t value)
372                 { return (0 <= value) && (value <= 0xFFFFLL); };
373
374     // Returns true if 'value' is a legal signed immediate 26 bit encoding (such as for B or BL).
375     static bool isValidSimm26(ssize_t value)
376                 { return (-0x2000000LL <= value) && (value <= 0x1FFFFFFLL); };
377
378     // Returns true if 'value' is a legal signed immediate 19 bit encoding (such as for B.cond, CBNZ, CBZ).
379     static bool isValidSimm19(ssize_t value)
380                 { return (-0x40000LL <= value) && (value <= 0x3FFFFLL); };
381
382     // Returns true if 'value' is a legal signed immediate 14 bit encoding (such as for TBNZ, TBZ).
383     static bool isValidSimm14(ssize_t value)
384                 { return (-0x2000LL <= value) && (value <= 0x1FFFLL); };
385
386     // Returns true if 'value' represents a valid 'bitmask immediate' encoding.
387     static bool isValidImmNRS (size_t value, emitAttr size)
388                 { return (value >= 0) && (value < 0x2000); }       // any unsigned 13-bit immediate
389
390     // Returns true if 'value' represents a valid 'halfword immediate' encoding.
391     static bool isValidImmHWVal (size_t value, emitAttr size)
392                 { return (value >= 0) && (value < 0x40000); }      // any unsigned 18-bit immediate
393
394     // Returns true if 'value' represents a valid 'byteShifted immediate' encoding.
395     static bool isValidImmBSVal (size_t value, emitAttr size)
396                 { return (value >= 0) && (value < 0x800); }        // any unsigned 11-bit immediate
397
398     //  The return value replaces REG_ZR with REG_SP
399     static regNumber encodingZRtoSP(regNumber reg)
400                      { return (reg == REG_ZR) ? REG_SP : reg; }    // ZR (R31) encodes the SP register 
401
402     //  The return value replaces REG_SP with REG_ZR
403     static regNumber encodingSPtoZR(regNumber reg)
404                      { return (reg == REG_SP) ? REG_ZR : reg; }    // SP is encoded using ZR (R31)
405
406     //  For the given 'ins' returns the reverse instruction, if one exists, otherwise returns INS_INVALID
407     static instruction  insReverse(instruction ins);
408
409     //  For the given 'datasize' and 'elemsize' returns the insOpts that specifies the vector register arrangement
410     static insOpts      optMakeArrangement(emitAttr datasize, emitAttr elemsize);
411
412     //    For the given 'datasize' and 'opt' returns true if it specifies a valid vector register arrangement
413     static bool         isValidArrangement(emitAttr datasize, insOpts opt);
414
415     //  For the given 'arrangement' returns the 'datasize' specified by the vector register arrangement
416     static emitAttr     optGetDatasize(insOpts arrangement);
417
418     //  For the given 'arrangement' returns the 'elemsize' specified by the vector register arrangement
419     static emitAttr     optGetElemsize(insOpts arrangement);
420
421     //  For the given 'arrangement' returns the 'widen-arrangement' specified by the vector register arrangement
422     static insOpts     optWidenElemsize(insOpts arrangement);
423
424     //  For the given 'conversion' returns the 'dstsize' specified by the conversion option
425     static emitAttr     optGetDstsize(insOpts conversion);
426
427     //  For the given 'conversion' returns the 'srcsize' specified by the conversion option
428     static emitAttr     optGetSrcsize(insOpts conversion);
429
430     //    For the given 'datasize', 'elemsize' and 'index' returns true, if it specifies a valid 'index' 
431     //    for an element of size 'elemsize' in a vector register of size 'datasize'
432     static bool         isValidVectorIndex(emitAttr datasize, emitAttr elemsize, ssize_t index);
433
434     /************************************************************************/
435     /*           Public inline informational methods                        */
436     /************************************************************************/
437
438 public:
439
440     // true if this 'imm' can be encoded as a input operand to a mov instruction 
441     static bool              emitIns_valid_imm_for_mov(INT64 imm, emitAttr size);
442
443     // true if this 'imm' can be encoded as a input operand to a vector movi instruction 
444     static bool              emitIns_valid_imm_for_movi(INT64 imm, emitAttr size);
445
446     // true if this 'immDbl' can be encoded as a input operand to a fmov instruction 
447     static bool              emitIns_valid_imm_for_fmov(double immDbl);
448
449     // true if this 'imm' can be encoded as a input operand to an add instruction 
450     static bool              emitIns_valid_imm_for_add(INT64 imm, emitAttr size);
451
452     // true if this 'imm' can be encoded as a input operand to a cmp instruction 
453     static bool              emitIns_valid_imm_for_cmp(INT64 imm, emitAttr size);
454
455     // true if this 'imm' can be encoded as a input operand to an alu instruction 
456     static bool              emitIns_valid_imm_for_alu(INT64 imm, emitAttr size);
457
458     // true if this 'imm' can be encoded as the offset in a ldr/str instruction 
459     static bool              emitIns_valid_imm_for_ldst_offset(INT64 imm, emitAttr size);
460
461     // true if 'imm' can use the left shifted by 12 bits encoding
462     static bool              canEncodeWithShiftImmBy12(INT64 imm);
463
464     // Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
465     static INT64             normalizeImm64(INT64 imm, emitAttr size);
466
467     // Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
468     static INT32             normalizeImm32(INT32 imm, emitAttr size);
469
470     // true if 'imm' can be encoded using a 'bitmask immediate', also returns the encoding if wbBMI is non-null
471     static bool              canEncodeBitMaskImm(INT64  imm,  emitAttr  size,
472                                                  emitter::bitMaskImm*  wbBMI = nullptr);
473
474     // true if 'imm' can be encoded using a 'halfword immediate', also returns the encoding if wbHWI is non-null
475     static bool              canEncodeHalfwordImm(INT64  imm,  emitAttr  size,
476                                                   emitter::halfwordImm*  wbHWI = nullptr);
477
478     // true if 'imm' can be encoded using a 'byteShifted immediate', also returns the encoding if wbBSI is non-null
479     static bool              canEncodeByteShiftedImm(INT64  imm,  emitAttr  size, bool allow_MSL,
480                                                      emitter::byteShiftedImm*  wbBSI = nullptr);
481
482     // true if 'immDbl' can be encoded using a 'float immediate', also returns the encoding if wbFPI is non-null
483     static bool              canEncodeFloatImm8(double  immDbl,  
484                                                 emitter::floatImm8*  wbFPI = nullptr);
485
486     // Returns the number of bits used by the given 'size'.
487     inline static unsigned   getBitWidth       (emitAttr  size)
488                              { assert(size <= EA_8BYTE); return (unsigned)size * BITS_PER_BYTE; }
489
490     // Returns true if the imm represents a valid bit shift or bit position for the given 'size' [0..31] or [0..63]
491     inline static unsigned   isValidImmShift   (ssize_t imm, emitAttr  size)
492                              { return (imm >= 0) && (imm < getBitWidth(size));      }
493
494     inline static bool       isValidGeneralDatasize   (emitAttr  size)
495                              { return (size == EA_8BYTE) || (size == EA_4BYTE);     }
496
497     inline static bool       isValidScalarDatasize    (emitAttr  size)
498                              { return (size == EA_8BYTE) || (size == EA_4BYTE);     }
499
500     inline static bool       isValidVectorDatasize    (emitAttr  size)
501                              { return (size == EA_16BYTE) || (size == EA_8BYTE);    }
502
503     inline static bool       isValidGeneralLSDatasize (emitAttr  size)
504                              { return (size == EA_8BYTE)  || (size == EA_4BYTE)  ||
505                                       (size == EA_2BYTE)  || (size == EA_1BYTE);    }
506
507     inline static bool       isValidVectorLSDatasize  (emitAttr  size)
508                              { return (size == EA_16BYTE) ||
509                                       (size == EA_8BYTE)  || (size == EA_4BYTE)  ||
510                                       (size == EA_2BYTE)  || (size == EA_1BYTE);    }
511
512     inline static bool       isValidVectorLSPDatasize (emitAttr  size)
513                              { return (size == EA_16BYTE) ||
514                                       (size == EA_8BYTE)  || (size == EA_4BYTE);   }
515
516     inline static bool       isValidVectorElemsize    (emitAttr  size)
517                              { return (size == EA_8BYTE) || (size == EA_4BYTE) ||
518                                       (size == EA_2BYTE) || (size == EA_1BYTE);    }
519
520     inline static bool       isValidVectorFcvtsize(emitAttr  size)
521                              { return (size == EA_8BYTE) || (size == EA_4BYTE) ||
522                                       (size == EA_2BYTE);                          }    
523
524     inline static bool       isValidVectorElemsizeFloat (emitAttr  size)
525                              { return (size == EA_8BYTE) || (size == EA_4BYTE);    }
526
527     inline static bool       isGeneralRegister (regNumber reg)
528                              { return (reg >= REG_INT_FIRST) && (reg <= REG_LR);    }   // Excludes REG_ZR
529
530     inline static bool       isGeneralRegisterOrZR (regNumber reg)
531                              { return (reg >= REG_INT_FIRST) && (reg <= REG_ZR);    }   // Includes REG_ZR
532
533     inline static bool       isGeneralRegisterOrSP (regNumber reg)
534                              { return isGeneralRegister(reg) || (reg == REG_SP);    }   // Includes REG_SP, Excludes REG_ZR
535
536     inline static bool       isVectorRegister      (regNumber reg)
537                              { return (reg >= REG_FP_FIRST && reg <= REG_FP_LAST);  }
538
539     inline static bool       isFloatReg       (regNumber reg)
540                              { return isVectorRegister(reg);             }
541  
542     inline static bool       insOptsNone       (insOpts  opt)
543                              { return (opt == INS_OPTS_NONE);            }
544
545     inline static bool       insOptsIndexed    (insOpts  opt)
546                              { return (opt == INS_OPTS_PRE_INDEX)  ||
547                                       (opt == INS_OPTS_POST_INDEX);      }
548
549     inline static bool       insOptsPreIndex    (insOpts  opt)
550                              { return (opt == INS_OPTS_PRE_INDEX);       }
551
552     inline static bool       insOptsPostIndex   (insOpts  opt)
553                              { return (opt == INS_OPTS_POST_INDEX);      }
554
555     inline static bool       insOptsLSL12       (insOpts  opt)             // special 12-bit shift only used for imm12
556                              { return (opt == INS_OPTS_LSL12);           }
557
558     inline static bool       insOptsAnyShift    (insOpts  opt)
559                              { return ((opt >= INS_OPTS_LSL) && 
560                                        (opt <= INS_OPTS_ROR)    );       }
561
562     inline static bool       insOptsAluShift    (insOpts  opt)             // excludes ROR
563                              { return ((opt >= INS_OPTS_LSL) && 
564                                        (opt <= INS_OPTS_ASR)    );       }
565
566     inline static bool       insOptsVectorImmShift (insOpts  opt)
567                              { return ((opt == INS_OPTS_LSL) || 
568                                        (opt == INS_OPTS_MSL)    );       }
569
570     inline static bool       insOptsLSL         (insOpts  opt)
571                              { return (opt == INS_OPTS_LSL);             }
572
573     inline static bool       insOptsLSR         (insOpts  opt)
574                              { return (opt == INS_OPTS_LSR);             }
575
576     inline static bool       insOptsASR         (insOpts  opt)
577                              { return (opt == INS_OPTS_ASR);             }
578
579     inline static bool       insOptsROR         (insOpts  opt)
580                              { return (opt == INS_OPTS_ROR);             }
581
582     inline static bool       insOptsAnyExtend   (insOpts  opt)
583                              { return ((opt >= INS_OPTS_UXTB) && 
584                                        (opt <= INS_OPTS_SXTX)    );      }
585
586     inline static bool       insOptsLSExtend    (insOpts  opt)
587                              { return ((opt == INS_OPTS_NONE) || (opt == INS_OPTS_LSL)  || 
588                                        (opt == INS_OPTS_UXTW) || (opt == INS_OPTS_SXTW) ||
589                                        (opt == INS_OPTS_UXTX) || (opt == INS_OPTS_SXTX)    );  }
590
591     inline static bool       insOpts32BitExtend (insOpts  opt)
592                              { return ((opt == INS_OPTS_UXTW) || (opt == INS_OPTS_SXTW));  }
593
594     inline static bool       insOpts64BitExtend (insOpts  opt)
595                              { return ((opt == INS_OPTS_UXTX) || (opt == INS_OPTS_SXTX));  }
596
597     inline static bool       insOptsAnyArrangement(insOpts  opt)
598                              { return ((opt >= INS_OPTS_8B) && (opt <= INS_OPTS_2D));  }
599
600     inline static bool       insOptsConvertFloatToFloat (insOpts  opt)
601                              { return ((opt >= INS_OPTS_S_TO_D) && (opt <= INS_OPTS_D_TO_H));  }
602
603     inline static bool       insOptsConvertFloatToInt   (insOpts  opt)
604                              { return ((opt >= INS_OPTS_S_TO_4BYTE) && (opt <= INS_OPTS_D_TO_8BYTE));  }
605
606     inline static bool       insOptsConvertIntToFloat   (insOpts  opt)
607                              { return ((opt >= INS_OPTS_4BYTE_TO_S) && (opt <= INS_OPTS_8BYTE_TO_D));  }
608
609     static bool             isValidImmCond          (ssize_t imm);
610     static bool             isValidImmCondFlags     (ssize_t imm);
611     static bool             isValidImmCondFlagsImm5 (ssize_t imm);
612
613     /************************************************************************/
614     /*           The public entry points to output instructions             */
615     /************************************************************************/
616
617 public:
618
619     void            emitIns        (instruction ins);
620
621     void            emitIns_I      (instruction ins,
622                                     emitAttr    attr,
623                                     ssize_t     imm);
624
625     void            emitIns_R      (instruction ins,
626                                     emitAttr    attr,
627                                     regNumber   reg);
628
629     void            emitIns_R_I    (instruction ins,
630                                     emitAttr    attr,
631                                     regNumber   reg,
632                                     ssize_t     imm,
633                                     insOpts     opt   = INS_OPTS_NONE);
634
635     void            emitIns_R_F    (instruction ins,
636                                     emitAttr    attr,
637                                     regNumber   reg,
638                                     double      immDbl,
639                                     insOpts     opt   = INS_OPTS_NONE);
640
641     void            emitIns_R_R    (instruction ins,
642                                     emitAttr    attr,
643                                     regNumber   reg1,
644                                     regNumber   reg2,
645                                     insOpts     opt   = INS_OPTS_NONE);
646
647     void            emitIns_R_R    (instruction ins,
648                                     emitAttr    attr,
649                                     regNumber   reg1,
650                                     regNumber   reg2,
651                                     insFlags    flags)
652     {
653         emitIns_R_R(ins,attr,reg1,reg2);
654     }
655
656     void            emitIns_R_I_I  (instruction ins,
657                                     emitAttr    attr,
658                                     regNumber   reg1,
659                                     ssize_t     imm1,
660                                     ssize_t     imm2,
661                                     insOpts     opt   = INS_OPTS_NONE);
662
663     void            emitIns_R_R_I  (instruction ins,
664                                     emitAttr    attr,
665                                     regNumber   reg1,
666                                     regNumber   reg2,
667                                     ssize_t     imm,
668                                     insOpts     opt   = INS_OPTS_NONE);
669
670     // Checks for a large immediate that needs a second instruction 
671     void            emitIns_R_R_Imm(instruction ins,
672                                     emitAttr    attr,
673                                     regNumber   reg1,
674                                     regNumber   reg2,
675                                     ssize_t     imm);
676
677     void            emitIns_R_R_R  (instruction ins,
678                                     emitAttr    attr,
679                                     regNumber   reg1,
680                                     regNumber   reg2,
681                                     regNumber   reg3,
682                                     insOpts     opt   = INS_OPTS_NONE);
683
684     void            emitIns_R_R_R_I(instruction ins,
685                                     emitAttr    attr,
686                                     regNumber   reg1,
687                                     regNumber   reg2,
688                                     regNumber   reg3,
689                                     ssize_t     imm,
690                                     insOpts     opt   = INS_OPTS_NONE);
691
692     void            emitIns_R_R_R_Ext(instruction ins,
693                                       emitAttr    attr,
694                                       regNumber   reg1,
695                                       regNumber   reg2,
696                                       regNumber   reg3,
697                                       insOpts     opt = INS_OPTS_NONE,
698                                       int         shiftAmount = -1);
699
700     void            emitIns_R_R_I_I(instruction ins,
701                                     emitAttr    attr,
702                                     regNumber   reg1,
703                                     regNumber   reg2,
704                                     int         imm1,
705                                     int         imm2);
706
707     void            emitIns_R_R_R_R(instruction ins,
708                                     emitAttr    attr,
709                                     regNumber   reg1,
710                                     regNumber   reg2,
711                                     regNumber   reg3,
712                                     regNumber   reg4);
713
714     void            emitIns_R_COND (instruction ins,
715                                     emitAttr    attr,
716                                     regNumber   reg,
717                                     insCond     cond);
718
719     void            emitIns_R_R_COND (instruction ins,
720                                       emitAttr    attr,
721                                       regNumber   reg1,
722                                       regNumber   reg2,
723                                       insCond     cond);
724
725     void            emitIns_R_R_R_COND (instruction ins,
726                                         emitAttr    attr,
727                                         regNumber   reg1,
728                                         regNumber   reg2,
729                                         regNumber   reg3,
730                                         insCond     cond);
731
732     void            emitIns_R_R_FLAGS_COND (instruction ins,
733                                             emitAttr    attr,
734                                             regNumber   reg1,
735                                             regNumber   reg2,
736                                             insCflags   flags,
737                                             insCond     cond);
738
739     void            emitIns_R_I_FLAGS_COND (instruction ins,
740                                             emitAttr    attr,
741                                             regNumber   reg1,
742                                             int         imm,
743                                             insCflags   flags,
744                                             insCond     cond);
745
746     void            emitIns_BARR   (instruction  ins,
747                                     insBarrier   barrier);
748
749     void            emitIns_C      (instruction  ins,
750                                     emitAttr     attr,
751                                     CORINFO_FIELD_HANDLE fdlHnd,
752                                     int          offs);
753
754     void            emitIns_S      (instruction ins,
755                                     emitAttr    attr,
756                                     int         varx,
757                                     int         offs);
758
759     void            emitIns_S_R    (instruction ins,
760                                     emitAttr    attr,
761                                     regNumber   ireg,
762                                     int         varx,
763                                     int         offs);
764
765     void            emitIns_R_S    (instruction ins,
766                                     emitAttr    attr,
767                                     regNumber   ireg,
768                                     int         varx,
769                                     int         offs);
770
771     void            emitIns_S_I    (instruction ins,
772                                     emitAttr    attr,
773                                     int         varx,
774                                     int         offs,
775                                     int         val);
776
777     void            emitIns_R_C    (instruction  ins,
778                                     emitAttr     attr,
779                                     regNumber    reg,
780                                     regNumber    tmpReg,
781                                     CORINFO_FIELD_HANDLE fldHnd,
782                                     int          offs);
783
784     void            emitIns_C_R    (instruction  ins,
785                                     emitAttr     attr,
786                                     CORINFO_FIELD_HANDLE fldHnd,
787                                     regNumber    reg,
788                                     int          offs);
789
790     void            emitIns_C_I    (instruction  ins,
791                                     emitAttr     attr,
792                                     CORINFO_FIELD_HANDLE fdlHnd,
793                                     ssize_t      offs,
794                                     ssize_t      val);
795
796     void            emitIns_R_L    (instruction   ins,
797                                     emitAttr      attr,
798                                     BasicBlock *  dst,
799                                     regNumber     reg);
800     
801     void            emitIns_R_D    (instruction   ins,
802                                     emitAttr      attr,
803                                     unsigned      offs,
804                                     regNumber     reg);
805
806     void            emitIns_J_R    (instruction ins,
807                                     emitAttr    attr,
808                                     BasicBlock *dst,
809                                     regNumber   reg);
810
811     void            emitIns_I_AR   (instruction ins,
812                                     emitAttr    attr,
813                                     int         val,
814                                     regNumber   reg,
815                                     int         offs,
816                                     int         memCookie = 0,
817                                     void *      clsCookie = NULL);
818
819     void            emitIns_R_AR   (instruction ins,
820                                     emitAttr    attr,
821                                     regNumber   ireg,
822                                     regNumber   reg,
823                                     int         offs,
824                                     int         memCookie = 0,
825                                     void *      clsCookie = NULL);
826
827     void            emitIns_R_AI   (instruction ins,
828                                     emitAttr    attr,
829                                     regNumber   ireg,
830                                     ssize_t     disp);
831
832     void            emitIns_AR_R   (instruction ins,
833                                     emitAttr    attr,
834                                     regNumber   ireg,
835                                     regNumber   reg,
836                                     int         offs,
837                                     int         memCookie = 0,
838                                     void *      clsCookie = NULL);
839
840     void            emitIns_R_ARR  (instruction ins,
841                                     emitAttr    attr,
842                                     regNumber   ireg,
843                                     regNumber   reg,
844                                     regNumber   rg2,
845                                     int         disp);
846
847     void            emitIns_ARR_R  (instruction ins,
848                                     emitAttr    attr,
849                                     regNumber   ireg,
850                                     regNumber   reg,
851                                     regNumber   rg2,
852                                     int         disp);
853
854     void            emitIns_R_ARX  (instruction ins,
855                                     emitAttr    attr,
856                                     regNumber   ireg,
857                                     regNumber   reg,
858                                     regNumber   rg2,
859                                     unsigned    mul,
860                                     int         disp);
861
862     enum EmitCallType
863     {
864
865     // I have included here, but commented out, all the values used by the x86 emitter.
866     // However, ARM has a much reduced instruction set, and so the ARM emitter only
867     // supports a subset of the x86 variants.  By leaving them commented out, it becomes
868     // a compile time error if code tries to use them (and hopefully see this comment
869     // and know why they are unavailible on ARM), while making it easier to stay
870     // in-sync with x86 and possibly add them back in if needed.
871
872         EC_FUNC_TOKEN,          //   Direct call to a helper/static/nonvirtual/global method
873     //  EC_FUNC_TOKEN_INDIR,    // Indirect call to a helper/static/nonvirtual/global method
874         EC_FUNC_ADDR,           // Direct call to an absolute address
875
876     //  EC_FUNC_VIRTUAL,        // Call to a virtual method (using the vtable)
877         EC_INDIR_R,             // Indirect call via register
878     //  EC_INDIR_SR,            // Indirect call via stack-reference (local var)
879     //  EC_INDIR_C,             // Indirect call via static class var
880     //  EC_INDIR_ARD,           // Indirect call via an addressing mode
881
882         EC_COUNT
883     };
884
885     void            emitIns_Call   (EmitCallType    callType,
886                                     CORINFO_METHOD_HANDLE methHnd,
887                                     INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo)     // used to report call sites to the EE
888                                     void*           addr,
889                                     ssize_t         argSize,
890                                     emitAttr        retSize,
891                                     emitAttr        secondRetSize,
892                                     VARSET_VALARG_TP ptrVars,
893                                     regMaskTP       gcrefRegs,
894                                     regMaskTP       byrefRegs,
895                                     IL_OFFSETX      ilOffset = BAD_IL_OFFSET,
896                                     regNumber       ireg = REG_NA,
897                                     regNumber       xreg = REG_NA,                                    
898                                     unsigned        xmul = 0,
899                                     ssize_t         disp = 0,
900                                     bool            isJump = false,
901                                     bool            isNoGC = false,
902                                     bool            isProfLeaveCB = false);
903
904     BYTE*           emitOutputLJ  (insGroup  *ig, BYTE *dst, instrDesc *i);
905     unsigned        emitOutputCall(insGroup  *ig, BYTE *dst, instrDesc *i, code_t code);
906     BYTE*           emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id);
907     BYTE*           emitOutputShortBranch(BYTE *dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id);
908     BYTE*           emitOutputShortAddress(BYTE *dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg);
909     BYTE*           emitOutputShortConstant(BYTE *dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg, emitAttr opSize);
910
911 /*****************************************************************************
912  *
913  *  Given an instrDesc, return true if it's a conditional jump.
914  */
915
916 inline bool        emitIsCondJump(instrDesc *jmp)
917 {
918     return ((jmp->idInsFmt() == IF_BI_0B) ||
919             (jmp->idInsFmt() == IF_LARGEJMP));
920 }
921
922
923 /*****************************************************************************
924  *
925  *  Given an instrDesc, return true if it's a compare and jump.
926  */
927
928 inline bool        emitIsCmpJump(instrDesc *jmp)
929 {
930     return ((jmp->idInsFmt() == IF_BI_1A) ||
931             (jmp->idInsFmt() == IF_BI_1B));
932 }
933
934 /*****************************************************************************
935  *
936  *  Given a instrDesc, return true if it's an unconditional jump.
937  */
938
939 inline bool        emitIsUncondJump(instrDesc *jmp)
940 {
941     return (jmp->idInsFmt() == IF_BI_0A);
942 }
943
944 /*****************************************************************************
945  *
946  *  Given a instrDesc, return true if it's a direct call.
947  */
948
949 inline bool        emitIsDirectCall(instrDesc *call)
950 {
951     return (call->idInsFmt() == IF_BI_0C);
952 }
953
954 /*****************************************************************************
955  *
956  *  Given a instrDesc, return true if it's a load label instruction.
957  */
958
959 inline bool        emitIsLoadLabel(instrDesc *jmp)
960 {
961     return ((jmp->idInsFmt() == IF_DI_1E) || // adr or arp
962             (jmp->idInsFmt() == IF_LARGEADR));
963 }
964
965 /*****************************************************************************
966 *
967 *  Given a instrDesc, return true if it's a load constant instruction.
968 */
969
970 inline bool        emitIsLoadConstant(instrDesc *jmp)
971 {
972     return ((jmp->idInsFmt() == IF_LS_1A) || // ldr
973             (jmp->idInsFmt() == IF_LARGELDC));
974 }
975
976 #endif // _TARGET_ARM64_