5f6fa7c29a5ee6d830a5ff6acfa8bc8390829f47
[platform/upstream/coreclr.git] / src / jit / target.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 #ifndef _TARGET_H_
7 #define _TARGET_H_
8
9 #if defined(FEATURE_CORECLR) && defined(_TARGET_UNIX_)
10 #define FEATURE_VARARG 0
11 #else // !(defined(FEATURE_CORECLR) && defined(_TARGET_UNIX_))
12 #define FEATURE_VARARG 1
13 #endif // !(defined(FEATURE_CORECLR) && defined(_TARGET_UNIX_))
14
15 /*****************************************************************************/
16 // The following are human readable names for the target architectures
17 #if defined(_TARGET_X86_)
18 #define TARGET_READABLE_NAME "X86"
19 #elif defined(_TARGET_AMD64_)
20 #define TARGET_READABLE_NAME "AMD64"
21 #elif defined(_TARGET_ARM_)
22 #define TARGET_READABLE_NAME "ARM"
23 #elif defined(_TARGET_ARM64_)
24 #define TARGET_READABLE_NAME "ARM64"
25 #else
26 #error Unsupported or unset target architecture
27 #endif
28
29 /*****************************************************************************/
30 // The following are intended to capture only those #defines that cannot be replaced
31 // with static const members of Target
32 #if defined(_TARGET_X86_) && defined(LEGACY_BACKEND)
33 #define REGMASK_BITS 8 // number of bits used to represent register mask
34 #elif defined(_TARGET_XARCH_)
35 #define REGMASK_BITS 32
36
37 #elif defined(_TARGET_ARM_)
38 #define REGMASK_BITS 64
39
40 #elif defined(_TARGET_ARM64_)
41 #define REGMASK_BITS 64
42
43 #else
44 #error Unsupported or unset target architecture
45 #endif
46
47 /*****************************************************************************/
48
49 #if defined(_TARGET_ARM_)
50 DECLARE_TYPED_ENUM(_regNumber_enum, unsigned)
51 {
52 #define REGDEF(name, rnum, mask, sname) REG_##name = rnum,
53 #define REGALIAS(alias, realname) REG_##alias = REG_##realname,
54 #include "register.h"
55
56     REG_COUNT, REG_NA = REG_COUNT, ACTUAL_REG_COUNT = REG_COUNT - 1 // everything but REG_STK (only real regs)
57 }
58 END_DECLARE_TYPED_ENUM(_regNumber_enum, unsigned)
59
60 DECLARE_TYPED_ENUM(_regMask_enum, unsigned __int64)
61 {
62     RBM_NONE = 0,
63 #define REGDEF(name, rnum, mask, sname) RBM_##name = mask,
64 #define REGALIAS(alias, realname) RBM_##alias = RBM_##realname,
65 #include "register.h"
66 }
67 END_DECLARE_TYPED_ENUM(_regMask_enum, unsigned __int64)
68
69 #elif defined(_TARGET_ARM64_)
70
71 DECLARE_TYPED_ENUM(_regNumber_enum, unsigned)
72 {
73 #define REGDEF(name, rnum, mask, xname, wname) REG_##name = rnum,
74 #define REGALIAS(alias, realname) REG_##alias = REG_##realname,
75 #include "register.h"
76
77     REG_COUNT, REG_NA = REG_COUNT, ACTUAL_REG_COUNT = REG_COUNT - 1 // everything but REG_STK (only real regs)
78 }
79 END_DECLARE_TYPED_ENUM(_regNumber_enum, unsigned)
80
81 DECLARE_TYPED_ENUM(_regMask_enum, unsigned __int64)
82 {
83     RBM_NONE = 0,
84 #define REGDEF(name, rnum, mask, xname, wname) RBM_##name = mask,
85 #define REGALIAS(alias, realname) RBM_##alias = RBM_##realname,
86 #include "register.h"
87 }
88 END_DECLARE_TYPED_ENUM(_regMask_enum, unsigned __int64)
89
90 #elif defined(_TARGET_AMD64_)
91
92 DECLARE_TYPED_ENUM(_regNumber_enum, unsigned)
93 {
94 #define REGDEF(name, rnum, mask, sname) REG_##name = rnum,
95 #define REGALIAS(alias, realname) REG_##alias = REG_##realname,
96 #include "register.h"
97
98     REG_COUNT, REG_NA = REG_COUNT, ACTUAL_REG_COUNT = REG_COUNT - 1 // everything but REG_STK (only real regs)
99 }
100 END_DECLARE_TYPED_ENUM(_regNumber_enum, unsigned)
101
102 DECLARE_TYPED_ENUM(_regMask_enum, unsigned)
103 {
104     RBM_NONE = 0,
105
106 #define REGDEF(name, rnum, mask, sname) RBM_##name = mask,
107 #define REGALIAS(alias, realname) RBM_##alias = RBM_##realname,
108 #include "register.h"
109 }
110 END_DECLARE_TYPED_ENUM(_regMask_enum, unsigned)
111
112 #elif defined(_TARGET_X86_)
113
114 #ifndef LEGACY_BACKEND
115 DECLARE_TYPED_ENUM(_regNumber_enum, unsigned)
116 {
117 #define REGDEF(name, rnum, mask, sname) REG_##name = rnum,
118 #define REGALIAS(alias, realname) REG_##alias = REG_##realname,
119 #include "register.h"
120
121     REG_COUNT, REG_NA = REG_COUNT, ACTUAL_REG_COUNT = REG_COUNT - 1 // everything but REG_STK (only real regs)
122 }
123 END_DECLARE_TYPED_ENUM(_regNumber_enum, unsigned)
124
125 DECLARE_TYPED_ENUM(_regMask_enum, unsigned)
126 {
127     RBM_NONE = 0,
128
129 #define REGDEF(name, rnum, mask, sname) RBM_##name = mask,
130 #define REGALIAS(alias, realname) RBM_##alias = RBM_##realname,
131 #include "register.h"
132 }
133 END_DECLARE_TYPED_ENUM(_regMask_enum, unsigned)
134 #else // LEGACY_BACKEND
135 DECLARE_TYPED_ENUM(_regNumber_enum, unsigned)
136 {
137 #define REGDEF(name, rnum, mask, sname) REG_##name = rnum,
138 #define REGALIAS(alias, realname) REG_##alias = REG_##realname,
139 #include "register.h"
140
141     REG_COUNT, REG_NA = REG_COUNT,
142                ACTUAL_REG_COUNT = REG_COUNT - 1, // everything but REG_STK (only real regs)
143
144 #define REGDEF(name, rnum, mask, sname) REG_##name = rnum,
145 #include "registerfp.h"
146
147         REG_FPCOUNT, REG_FPNONE = REG_FPCOUNT,
148
149 #define REGDEF(name, rnum, mask, sname) REG_##name = rnum,
150 #include "registerxmm.h"
151
152                REG_XMMCOUNT
153 }
154 END_DECLARE_TYPED_ENUM(_regNumber_enum, unsigned)
155
156 DECLARE_TYPED_ENUM(_regMask_enum, unsigned)
157 {
158     RBM_NONE = 0,
159
160 #define REGDEF(name, rnum, mask, sname) RBM_##name = mask,
161 #define REGALIAS(alias, realname) RBM_##alias = RBM_##realname,
162 #include "register.h"
163
164 #define REGDEF(name, rnum, mask, sname) RBM_##name = mask,
165 #include "registerfp.h"
166
167 #define REGDEF(name, rnum, mask, sname) RBM_##name = mask,
168 #include "registerxmm.h"
169 }
170 END_DECLARE_TYPED_ENUM(_regMask_enum, unsigned)
171
172 #endif // LEGACY_BACKEND
173 #else
174 #error Unsupported target architecture
175 #endif
176
177 /* The following are used to hold 'long' (64-bit integer) operands */
178
179 /*
180     The following yield the number of bits and the mask of a register
181     number in a register pair.
182  */
183
184 #ifdef _TARGET_ARM_
185 #define REG_PAIR_NBITS 6
186 #else
187 #define REG_PAIR_NBITS 4
188 #endif
189 #define REG_PAIR_NMASK ((1 << REG_PAIR_NBITS) - 1)
190
191 #ifdef DEBUG
192 // Under DEBUG, we want to make sure that code doesn't accidentally confuse a reg pair value
193 // with a simple register number. Thus, we offset the reg pair numbers so they are distinct
194 // from all register numbers. Note that this increases the minimum size of a regPairNoSmall
195 // type due to the additional bits used for this offset.
196 #define REG_PAIR_FIRST (7 << REG_PAIR_NBITS)
197 #define REG_PAIR_NBITS_DEBUG                                                                                           \
198     (REG_PAIR_NBITS +                                                                                                  \
199      3) // extra bits needed by the debug shifting (3 instead of 0 because we shift "7", not "1", above).
200 C_ASSERT(REG_COUNT < REG_PAIR_FIRST); // make sure the register numbers (including REG_NA, ignoring fp/xmm regs on
201                                       // x86/x64) are distinct from the pair numbers
202 #else
203 #define REG_PAIR_FIRST 0
204 #endif
205
206 DECLARE_TYPED_ENUM(_regPairNo_enum, unsigned)
207 {
208 #define PAIRDEF(rlo, rhi) REG_PAIR_##rlo##rhi = REG_##rlo + (REG_##rhi << REG_PAIR_NBITS) + REG_PAIR_FIRST,
209 #include "regpair.h"
210
211     REG_PAIR_LAST = (REG_COUNT - 1) + ((REG_COUNT - 1) << REG_PAIR_NBITS) + REG_PAIR_FIRST,
212
213     REG_PAIR_NONE = REG_PAIR_LAST + 1
214 }
215 END_DECLARE_TYPED_ENUM(_regPairNo_enum, unsigned)
216
217 enum regPairMask
218 {
219 #define PAIRDEF(rlo, rhi) RBM_PAIR_##rlo##rhi = (RBM_##rlo | RBM_##rhi),
220 #include "regpair.h"
221 };
222
223 /*****************************************************************************/
224
225 // TODO-Cleanup: The types defined below are mildly confusing: why are there both?
226 // regMaskSmall is large enough to represent the entire set of registers.
227 // If regMaskSmall is smaller than a "natural" integer type, regMaskTP is wider, based
228 // on a belief by the original authors of the JIT that in some situations it is more
229 // efficient to have the wider representation.  This belief should be tested, and if it
230 // is false, then we should coalesce these two types into one (the Small width, probably).
231 // In any case, we believe that is OK to freely cast between these types; no information will
232 // be lost.
233
234 #ifdef _TARGET_ARMARCH_
235 typedef unsigned __int64 regMaskTP;
236 #else
237 typedef unsigned       regMaskTP;
238 #endif
239
240 #if REGMASK_BITS == 8
241 typedef unsigned char regMaskSmall;
242 #define REG_MASK_INT_FMT "%02X"
243 #define REG_MASK_ALL_FMT "%02X"
244 #elif REGMASK_BITS == 16
245 typedef unsigned short regMaskSmall;
246 #define REG_MASK_INT_FMT "%04X"
247 #define REG_MASK_ALL_FMT "%04X"
248 #elif REGMASK_BITS == 32
249 typedef unsigned regMaskSmall;
250 #define REG_MASK_INT_FMT "%08X"
251 #define REG_MASK_ALL_FMT "%08X"
252 #else
253 typedef unsigned __int64 regMaskSmall;
254 #define REG_MASK_INT_FMT "%04llX"
255 #define REG_MASK_ALL_FMT "%016llX"
256 #endif
257
258 typedef _regNumber_enum regNumber;
259 typedef _regPairNo_enum regPairNo;
260
261 // LSRA currently converts freely between regNumber and regPairNo, so make sure they are the same size.
262 C_ASSERT(sizeof(regPairNo) == sizeof(regNumber));
263
264 typedef unsigned char regNumberSmall;
265
266 #ifdef DEBUG
267
268 // Under DEBUG, we shift the reg pair numbers to be independent of the regNumber range,
269 // so we need additional bits. See the definition of REG_PAIR_FIRST for details.
270
271 #if ((2 * REG_PAIR_NBITS) + REG_PAIR_NBITS_DEBUG) <= 16
272 C_ASSERT(((2 * REG_PAIR_NBITS) + REG_PAIR_NBITS_DEBUG) > 8); // assert that nobody fits in 8 bits
273 typedef unsigned short regPairNoSmall;                       // x86/x64: need 15 bits
274 #else
275 C_ASSERT(((2 * REG_PAIR_NBITS) + REG_PAIR_NBITS_DEBUG) <= 32);
276 typedef unsigned regPairNoSmall; // arm: need 21 bits
277 #endif
278
279 #else // DEBUG
280
281 #if (2 * REG_PAIR_NBITS) <= 8
282 typedef unsigned char  regPairNoSmall; // x86/x64: need 8 bits
283 #else
284 C_ASSERT((2 * REG_PAIR_NBITS) <= 16);  // assert that nobody needs more than 16 bits
285 typedef unsigned short regPairNoSmall; // arm: need 12 bits
286 #endif
287
288 #endif // DEBUG
289
290 /*****************************************************************************/
291
292 #define LEA_AVAILABLE 1
293 #define SCALED_ADDR_MODES 1
294
295 /*****************************************************************************/
296
297 #ifdef DEBUG
298 #define DSP_SRC_OPER_LEFT 0
299 #define DSP_SRC_OPER_RIGHT 1
300 #define DSP_DST_OPER_LEFT 1
301 #define DSP_DST_OPER_RIGHT 0
302 #endif
303
304 /*****************************************************************************/
305
306 // The pseudorandom nop insertion is not necessary for current CoreCLR scenarios
307 // #if defined(FEATURE_CORECLR) && !defined(_TARGET_ARM_)
308 // #define PSEUDORANDOM_NOP_INSERTION
309 // #endif
310
311 /*****************************************************************************/
312
313 // clang-format off
314 #if defined(_TARGET_X86_)
315
316   #define CPU_LOAD_STORE_ARCH      0
317
318 #ifdef LEGACY_BACKEND
319   #define CPU_LONG_USES_REGPAIR    1
320 #else
321   #define CPU_LONG_USES_REGPAIR    0       // RyuJIT x86 doesn't use the regPairNo field to record register pairs for long
322                                            // type tree nodes, and instead either decomposes them (for non-atomic operations)
323                                            // or stores multiple regNumber values for operations such as calls where the
324                                            // register definitions are effectively "atomic".
325 #endif // LEGACY_BACKEND
326
327   #define CPU_HAS_FP_SUPPORT       1
328   #define ROUND_FLOAT              1       // round intermed float expression results
329   #define CPU_HAS_BYTE_REGS        1
330   #define CPU_USES_BLOCK_MOVE      1 
331
332 #ifndef LEGACY_BACKEND
333   // TODO-CQ: Fine tune the following xxBlk threshold values:
334
335 #define CPBLK_MOVS_LIMIT         16      // When generating code for CpBlk, this is the buffer size 
336                                            // threshold to stop generating rep movs and switch to the helper call.
337                                            // NOTE: Using rep movs is currently disabled since we found it has bad performance
338                                            //       on pre-Ivy Bridge hardware.
339                                            
340   #define CPBLK_UNROLL_LIMIT       64      // Upper bound to let the code generator to loop unroll CpBlk.
341   #define INITBLK_STOS_LIMIT       64      // When generating code for InitBlk, this is the buffer size 
342                                            // NOTE: Using rep stos is currently disabled since we found it has bad performance
343                                            //       on pre-Ivy Bridge hardware.
344                                            // threshold to stop generating rep movs and switch to the helper call.
345   #define INITBLK_UNROLL_LIMIT     128     // Upper bound to let the code generator to loop unroll InitBlk.
346   #define CPOBJ_NONGC_SLOTS_LIMIT  4       // For CpObj code generation, this is the the threshold of the number 
347                                            // of contiguous non-gc slots that trigger generating rep movsq instead of 
348                                            // sequences of movsq instructions
349                                            // The way we're currently disabling rep movs/stos is by setting a limit less than
350                                            // its unrolling counterparts.  When lower takes the decision on which one to make it
351                                            // always asks for the unrolling limit first so you can say the JIT 'favors' unrolling.
352                                            // Setting the limit to something lower than that makes lower to never consider it.
353
354 #endif // !LEGACY_BACKEND
355
356 #ifdef FEATURE_SIMD
357   #define ALIGN_SIMD_TYPES         1       // whether SIMD type locals are to be aligned
358 #endif // FEATURE_SIMD
359
360   #define FEATURE_WRITE_BARRIER    1       // Generate the proper WriteBarrier calls for GC
361   #define FEATURE_FIXED_OUT_ARGS   0       // X86 uses push instructions to pass args
362   #define FEATURE_STRUCTPROMOTE    1       // JIT Optimization to promote fields of structs into registers
363   #define FEATURE_MULTIREG_STRUCT_PROMOTE  0  // True when we want to promote fields of a multireg struct into registers
364   #define FEATURE_FASTTAILCALL     0       // Tail calls made as epilog+jmp
365   #define FEATURE_TAILCALL_OPT     0       // opportunistic Tail calls (without ".tail" prefix) made as fast tail calls.
366   #define FEATURE_SET_FLAGS        0       // Set to true to force the JIT to mark the trees with GTF_SET_FLAGS when
367                                            // the flags need to be set
368 #ifdef LEGACY_BACKEND
369   #define FEATURE_MULTIREG_ARGS_OR_RET  0  // Support for passing and/or returning single values in more than one register
370   #define FEATURE_MULTIREG_ARGS         0  // Support for passing a single argument in more than one register  
371   #define FEATURE_MULTIREG_RET          0  // Support for returning a single value in more than one register
372   #define MAX_PASS_MULTIREG_BYTES       0  // No multireg arguments 
373   #define MAX_RET_MULTIREG_BYTES        0  // No multireg return values 
374 #else
375   #define FEATURE_MULTIREG_ARGS_OR_RET  1  // Support for passing and/or returning single values in more than one register
376   #define FEATURE_MULTIREG_ARGS         0  // Support for passing a single argument in more than one register  
377   #define FEATURE_MULTIREG_RET          1  // Support for returning a single value in more than one register
378   #define MAX_PASS_MULTIREG_BYTES       0  // No multireg arguments (note this seems wrong as MAX_ARG_REG_COUNT is 2)
379   #define MAX_RET_MULTIREG_BYTES        8  // Maximum size of a struct that could be returned in more than one register
380 #endif
381
382   #define MAX_ARG_REG_COUNT             2  // Maximum registers used to pass an argument.
383   #define MAX_RET_REG_COUNT             2  // Maximum registers used to return a value.
384
385 #ifdef FEATURE_USE_ASM_GC_WRITE_BARRIERS
386   #define NOGC_WRITE_BARRIERS      1       // We have specialized WriteBarrier JIT Helpers that DO-NOT trash the
387                                            // RBM_CALLEE_TRASH registers
388 #else
389   #define NOGC_WRITE_BARRIERS      0       // Do not modify this -- modify the definition above.  (If we're not using
390                                            // ASM barriers we definitely don't have NOGC barriers).
391 #endif
392   #define USER_ARGS_COME_LAST      0
393   #define EMIT_TRACK_STACK_DEPTH   1
394   #define TARGET_POINTER_SIZE      4       // equal to sizeof(void*) and the managed pointer size in bytes for this
395                                            // target
396   #define FEATURE_EH               1       // To aid platform bring-up, eliminate exceptional EH clauses (catch, filter,
397                                            // filter-handler, fault) and directly execute 'finally' clauses.
398 #if defined(FEATURE_PAL) && !defined(LEGACY_BACKEND)
399   #define FEATURE_EH_FUNCLETS      1
400 #else  // FEATURE_PAL && !LEGACY_BACKEND
401   #define FEATURE_EH_FUNCLETS      0
402 #endif // FEATURE_PAL && !LEGACY_BACKEND
403   #define FEATURE_EH_CALLFINALLY_THUNKS 0  // Generate call-to-finally code in "thunks" in the enclosing EH region,
404                                            // protected by "cloned finally" clauses.
405 #ifndef LEGACY_BACKEND
406   #define FEATURE_STACK_FP_X87     0
407 #else // LEGACY_BACKEND
408   #define FEATURE_STACK_FP_X87     1       // Use flat register file model    
409 #endif // LEGACY_BACKEND
410   #define FEATURE_X87_DOUBLES      0       // FP tree temps always use x87 doubles (when 1) or can be double or float
411                                            // (when 0).
412   #define ETW_EBP_FRAMED           1       // if 1 we cannot use EBP as a scratch register and must create EBP based
413                                            // frames for most methods
414   #define CSE_CONSTS               1       // Enable if we want to CSE constants
415
416 #ifndef LEGACY_BACKEND
417   // The following defines are useful for iterating a regNumber
418   #define REG_FIRST                REG_EAX
419   #define REG_INT_FIRST            REG_EAX
420   #define REG_INT_LAST             REG_EDI
421   #define REG_INT_COUNT            (REG_INT_LAST - REG_INT_FIRST + 1)
422   #define REG_NEXT(reg)           ((regNumber)((unsigned)(reg) + 1))
423   #define REG_PREV(reg)           ((regNumber)((unsigned)(reg) - 1))
424
425   #define REG_FP_FIRST             REG_XMM0
426   #define REG_FP_LAST              REG_XMM7
427   #define FIRST_FP_ARGREG          REG_XMM0
428   #define LAST_FP_ARGREG           REG_XMM3
429   #define REG_FLTARG_0             REG_XMM0
430   #define REG_FLTARG_1             REG_XMM1
431   #define REG_FLTARG_2             REG_XMM2
432   #define REG_FLTARG_3             REG_XMM3
433
434   #define RBM_FLTARG_0             RBM_XMM0
435   #define RBM_FLTARG_1             RBM_XMM1
436   #define RBM_FLTARG_2             RBM_XMM2
437   #define RBM_FLTARG_3             RBM_XMM3
438
439   #define RBM_FLTARG_REGS         (RBM_FLTARG_0|RBM_FLTARG_1|RBM_FLTARG_2|RBM_FLTARG_3)
440
441   #define RBM_ALLFLOAT            (RBM_XMM0 | RBM_XMM1 | RBM_XMM2 | RBM_XMM3 | RBM_XMM4 | RBM_XMM5 | RBM_XMM6 | RBM_XMM7)
442   #define RBM_ALLDOUBLE            RBM_ALLFLOAT
443
444   // TODO-CQ: Currently we are following the x86 ABI for SSE2 registers.
445   // This should be reconsidered.
446   #define RBM_FLT_CALLEE_SAVED     RBM_NONE
447   #define RBM_FLT_CALLEE_TRASH     RBM_ALLFLOAT
448   #define REG_VAR_ORDER_FLT        REG_XMM0, REG_XMM1, REG_XMM2, REG_XMM3, REG_XMM4, REG_XMM5, REG_XMM6, REG_XMM7
449
450   #define REG_FLT_CALLEE_SAVED_FIRST   REG_XMM6
451   #define REG_FLT_CALLEE_SAVED_LAST    REG_XMM7
452
453   #define XMM_REGSIZE_BYTES        16      // XMM register size in bytes
454   #define YMM_REGSIZE_BYTES        32      // YMM register size in bytes
455
456   #define REGNUM_BITS              6       // number of bits in a REG_*
457   #define TINY_REGNUM_BITS         6       // number used in a tiny instrdesc (same)
458
459 #else // LEGACY_BACKEND
460   #define FEATURE_FP_REGALLOC      0       // Enabled if RegAlloc is used to enregister Floating Point LclVars      
461
462   #define FP_STK_SIZE              8
463   #define RBM_ALLFLOAT            (RBM_FPV0 | RBM_FPV1 | RBM_FPV2 | RBM_FPV3 | RBM_FPV4 | RBM_FPV5 | RBM_FPV6)
464   #define REG_FP_FIRST             REG_FPV0
465   #define REG_FP_LAST              REG_FPV7
466   #define FIRST_FP_ARGREG          REG_NA
467   #define LAST_FP_ARGREG           REG_NA
468
469
470   #define REGNUM_BITS              3       // number of bits in a REG_*
471   #define TINY_REGNUM_BITS         3       
472   #define REGMASK_BITS             8       // number of bits in a REGNUM_MASK
473
474   #define RBM_FLTARG_REGS          0
475   #define RBM_FLT_CALLEE_SAVED     0
476   #define RBM_FLT_CALLEE_TRASH     0
477
478 #endif // LEGACY_BACKEND
479
480   #define REGSIZE_BYTES            4       // number of bytes in one register
481   #define MIN_ARG_AREA_FOR_CALL    0       // Minimum required outgoing argument space for a call.
482
483   #define CODE_ALIGN               1       // code alignment requirement
484 #if !defined(UNIX_X86_ABI)
485   #define STACK_ALIGN              4       // stack alignment requirement
486   #define STACK_ALIGN_SHIFT        2       // Shift-right amount to convert stack size in bytes to size in DWORD_PTRs
487   #define STACK_ALIGN_SHIFT_ALL    2       // Shift-right amount to convert stack size in bytes to size in STACK_ALIGN units
488 #else
489   #define STACK_ALIGN              16      // stack alignment requirement
490   #define STACK_ALIGN_SHIFT        4       // Shift-right amount to convert stack size in bytes to size in DWORD_PTRs
491   #define STACK_ALIGN_SHIFT_ALL    4       // Shift-right amount to convert stack size in bytes to size in STACK_ALIGN units
492 #endif // !UNIX_X86_ABI
493
494   #define RBM_INT_CALLEE_SAVED    (RBM_EBX|RBM_ESI|RBM_EDI)
495   #define RBM_INT_CALLEE_TRASH    (RBM_EAX|RBM_ECX|RBM_EDX)
496
497   #define RBM_CALLEE_SAVED        (RBM_INT_CALLEE_SAVED | RBM_FLT_CALLEE_SAVED)
498   #define RBM_CALLEE_TRASH        (RBM_INT_CALLEE_TRASH | RBM_FLT_CALLEE_TRASH)
499
500   #define RBM_ALLINT              (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH)
501
502   #define REG_VAR_ORDER            REG_EAX,REG_EDX,REG_ECX,REG_ESI,REG_EDI,REG_EBX
503   #define MAX_VAR_ORDER_SIZE       6
504   #define REG_TMP_ORDER            REG_EAX,REG_EDX,REG_ECX,REG_EBX,REG_ESI,REG_EDI
505   #define RBM_TMP_ORDER            RBM_EAX,RBM_EDX,RBM_ECX,RBM_EBX,RBM_ESI,RBM_EDI
506   #define REG_TMP_ORDER_COUNT      6
507
508   #define REG_PREDICT_ORDER        REG_EAX,REG_EDX,REG_ECX,REG_EBX,REG_ESI,REG_EDI
509
510   // The order here is fixed: it must agree with an order assumed in eetwain...
511   #define REG_CALLEE_SAVED_ORDER   REG_EDI,REG_ESI,REG_EBX,REG_EBP
512   #define RBM_CALLEE_SAVED_ORDER   RBM_EDI,RBM_ESI,RBM_EBX,RBM_EBP
513
514   #define CNT_CALLEE_SAVED        (4)
515   #define CNT_CALLEE_TRASH        (3)
516   #define CNT_CALLEE_ENREG        (CNT_CALLEE_SAVED-1)
517
518   #define CNT_CALLEE_SAVED_FLOAT  (0)
519   #define CNT_CALLEE_TRASH_FLOAT  (6)
520
521   #define CALLEE_SAVED_REG_MAXSZ  (CNT_CALLEE_SAVED*REGSIZE_BYTES)  // EBX,ESI,EDI,EBP
522
523   // We reuse the ESP register as a illegal value in the register predictor
524   #define RBM_ILLEGAL              RBM_ESP
525   // We reuse the ESP register as a flag for last use handling in the register predictor
526   #define RBM_LASTUSE              RBM_ESP
527   // We're using the encoding for ESP to indicate a half-long on the frame
528   #define REG_L_STK                REG_ESP
529
530   //  This is the first register in REG_TMP_ORDER
531   #define REG_TMP_0                REG_EAX
532   #define RBM_TMP_0                RBM_EAX
533
534   //  This is the second register in REG_TMP_ORDER
535   #define REG_TMP_1                REG_EDX
536   #define RBM_TMP_1                RBM_EDX
537
538   #define REG_PAIR_TMP             REG_PAIR_EAXEDX
539   #define REG_PAIR_TMP_REVERSE     REG_PAIR_EDXEAX
540   #define RBM_PAIR_TMP             (RBM_EAX|RBM_EDX)
541   #define REG_PAIR_TMP_LO          REG_EAX
542   #define RBM_PAIR_TMP_LO          RBM_EAX
543   #define REG_PAIR_TMP_HI          REG_EDX
544   #define RBM_PAIR_TMP_HI          RBM_EDX
545   #define PREDICT_PAIR_TMP         PREDICT_PAIR_EAXEDX
546   #define PREDICT_PAIR_TMP_LO      PREDICT_REG_EAX
547
548   // Used when calling the 64-bit Variable shift helper
549   #define REG_LNGARG_0             REG_PAIR_EAXEDX
550   #define RBM_LNGARG_0            (RBM_EAX|RBM_EDX)
551   #define PREDICT_PAIR_LNGARG_0    PREDICT_PAIR_EAXEDX
552
553   #define REG_LNGARG_LO             REG_EAX
554   #define RBM_LNGARG_LO             RBM_EAX
555   #define REG_LNGARG_HI             REG_EDX
556   #define RBM_LNGARG_HI             RBM_EDX
557   // register to hold shift amount
558   #define REG_SHIFT                REG_ECX
559   #define RBM_SHIFT                RBM_ECX
560   #define PREDICT_REG_SHIFT        PREDICT_REG_ECX
561   
562   // register to hold shift amount when shifting 64-bit values
563   #define REG_SHIFT_LNG            REG_ECX
564   #define RBM_SHIFT_LNG            RBM_ECX
565   #define PREDICT_REG_SHIFT_LNG    PREDICT_REG_ECX
566   
567   // This is a general scratch register that does not conflict with the argument registers
568   #define REG_SCRATCH              REG_EAX
569   #define RBM_SCRATCH              RBM_EAX
570
571   // Where is the exception object on entry to the handler block?
572   #define REG_EXCEPTION_OBJECT     REG_EAX
573   #define RBM_EXCEPTION_OBJECT     RBM_EAX
574
575   // Only used on ARM for GTF_CALL_M_VIRTSTUB_REL_INDIRECT
576   #define REG_JUMP_THUNK_PARAM     REG_EAX
577   #define RBM_JUMP_THUNK_PARAM     RBM_EAX
578
579 #if NOGC_WRITE_BARRIERS
580   #define REG_WRITE_BARRIER        REG_EDX
581   #define RBM_WRITE_BARRIER        RBM_EDX
582
583   // We don't allow using ebp as a source register. Maybe we should only prevent this for ETW_EBP_FRAMED (but that is always set right now).
584   #define RBM_WRITE_BARRIER_SRC    (RBM_EAX|RBM_ECX|RBM_EBX|RBM_ESI|RBM_EDI)
585
586   #define RBM_CALLEE_TRASH_NOGC    RBM_EDX
587 #endif // NOGC_WRITE_BARRIERS
588
589   // GenericPInvokeCalliHelper unmanaged target parameter
590   #define REG_PINVOKE_TARGET_PARAM REG_EAX
591   #define RBM_PINVOKE_TARGET_PARAM RBM_EAX
592
593   // GenericPInvokeCalliHelper cookie parameter
594   #define REG_PINVOKE_COOKIE_PARAM REG_STK
595
596   // IL stub's secret parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM)
597   #define REG_SECRET_STUB_PARAM    REG_EAX
598   #define RBM_SECRET_STUB_PARAM    RBM_EAX
599
600   // VSD extra parameter
601   #define REG_VIRTUAL_STUB_PARAM   REG_EAX
602   #define RBM_VIRTUAL_STUB_PARAM   RBM_EAX
603   #define PREDICT_REG_VIRTUAL_STUB_PARAM  PREDICT_REG_EAX
604
605   // VSD target address register
606   #define REG_VIRTUAL_STUB_TARGET  REG_EAX
607   #define RBM_VIRTUAL_STUB_TARGET  RBM_EAX
608
609   // Registers used by PInvoke frame setup
610   #define REG_PINVOKE_FRAME        REG_EDI      // EDI is p/invoke "Frame" pointer argument to CORINFO_HELP_INIT_PINVOKE_FRAME helper
611   #define RBM_PINVOKE_FRAME        RBM_EDI
612   #define REG_PINVOKE_TCB          REG_ESI      // ESI is set to Thread Control Block (TCB) on return from
613                                                 // CORINFO_HELP_INIT_PINVOKE_FRAME helper
614   #define RBM_PINVOKE_TCB          RBM_ESI
615   #define REG_PINVOKE_SCRATCH      REG_EAX      // EAX is trashed by CORINFO_HELP_INIT_PINVOKE_FRAME helper
616   #define RBM_PINVOKE_SCRATCH      RBM_EAX
617
618 #ifdef LEGACY_BACKEND
619   #define REG_SPILL_CHOICE         REG_EAX
620   #define RBM_SPILL_CHOICE         RBM_EAX
621 #endif // LEGACY_BACKEND
622
623   // The following defines are useful for iterating a regNumber
624   #define REG_FIRST                REG_EAX
625   #define REG_INT_FIRST            REG_EAX
626   #define REG_INT_LAST             REG_EDI
627   #define REG_INT_COUNT            (REG_INT_LAST - REG_INT_FIRST + 1)
628   #define REG_NEXT(reg)           ((regNumber)((unsigned)(reg) + 1))
629   #define REG_PREV(reg)           ((regNumber)((unsigned)(reg) - 1))
630
631   // genCodeForCall() moves the target address of the tailcall into this register, before pushing it on the stack
632   #define REG_TAILCALL_ADDR        REG_EAX
633
634   // Which register are int and long values returned in ?
635   #define REG_INTRET               REG_EAX
636   #define RBM_INTRET               RBM_EAX
637   #define REG_LNGRET               REG_PAIR_EAXEDX
638   #define RBM_LNGRET              (RBM_EDX|RBM_EAX)
639   #define REG_LNGRET_LO            REG_EAX
640   #define RBM_LNGRET_LO            RBM_EAX
641   #define REG_LNGRET_HI            REG_EDX
642   #define RBM_LNGRET_HI            RBM_EDX
643
644   #define REG_FLOATRET             REG_NA
645   #define RBM_FLOATRET             RBM_NONE
646   #define RBM_DOUBLERET            RBM_NONE
647
648   // The registers trashed by the CORINFO_HELP_STOP_FOR_GC helper
649   #define RBM_STOP_FOR_GC_TRASH    RBM_CALLEE_TRASH
650
651   // The registers trashed by the CORINFO_HELP_INIT_PINVOKE_FRAME helper. On x86, this helper has a custom calling
652   // convention that takes EDI as argument (but doesn't trash it), trashes EAX, and returns ESI.
653   #define RBM_INIT_PINVOKE_FRAME_TRASH  (RBM_PINVOKE_SCRATCH | RBM_PINVOKE_TCB)
654
655   #define REG_FPBASE               REG_EBP
656   #define RBM_FPBASE               RBM_EBP
657   #define STR_FPBASE               "ebp"
658   #define REG_SPBASE               REG_ESP
659   #define RBM_SPBASE               RBM_ESP
660   #define STR_SPBASE               "esp"
661
662   #define FIRST_ARG_STACK_OFFS    (2*REGSIZE_BYTES)   // Caller's saved EBP and return address
663
664   #define MAX_REG_ARG              2
665   #define MAX_FLOAT_REG_ARG        0
666   #define REG_ARG_FIRST            REG_ECX
667   #define REG_ARG_LAST             REG_EDX
668   #define INIT_ARG_STACK_SLOT      0                  // No outgoing reserved stack slots
669
670   #define REG_ARG_0                REG_ECX
671   #define REG_ARG_1                REG_EDX
672
673   SELECTANY const regNumber intArgRegs [] = {REG_ECX, REG_EDX};
674   SELECTANY const regMaskTP intArgMasks[] = {RBM_ECX, RBM_EDX};
675 #if !FEATURE_STACK_FP_X87
676   SELECTANY const regNumber fltArgRegs [] = {REG_XMM0, REG_XMM1, REG_XMM2, REG_XMM3};
677   SELECTANY const regMaskTP fltArgMasks[] = {RBM_XMM0, RBM_XMM1, RBM_XMM2, RBM_XMM3};
678 #endif // FEATURE_STACK_FP_X87
679
680   #define RBM_ARG_0                RBM_ECX
681   #define RBM_ARG_1                RBM_EDX
682
683   #define RBM_ARG_REGS            (RBM_ARG_0|RBM_ARG_1)
684
685   // The registers trashed by profiler enter/leave/tailcall hook
686   // See vm\i386\asmhelpers.asm for more details.
687   #define RBM_PROFILER_ENTER_TRASH     RBM_NONE
688   #define RBM_PROFILER_LEAVE_TRASH     RBM_NONE
689   #define RBM_PROFILER_TAILCALL_TRASH  (RBM_ALLINT & ~RBM_ARG_REGS)
690
691   // What sort of reloc do we use for [disp32] address mode
692   #define IMAGE_REL_BASED_DISP32   IMAGE_REL_BASED_HIGHLOW
693
694   // What sort of reloc to we use for 'moffset' address mode (for 'mov eax, moffset' or 'mov moffset, eax')
695   #define IMAGE_REL_BASED_MOFFSET  IMAGE_REL_BASED_HIGHLOW
696
697   // Pointer-sized string move instructions
698   #define INS_movsp                INS_movsd
699   #define INS_r_movsp              INS_r_movsd
700   #define INS_stosp                INS_stosd
701   #define INS_r_stosp              INS_r_stosd
702
703 #elif defined(_TARGET_AMD64_)
704   // TODO-AMD64-CQ: Fine tune the following xxBlk threshold values:
705  
706   #define CPU_LOAD_STORE_ARCH      0
707   #define CPU_LONG_USES_REGPAIR    0
708   #define CPU_HAS_FP_SUPPORT       1
709   #define ROUND_FLOAT              0       // Do not round intermed float expression results
710   #define CPU_HAS_BYTE_REGS        0
711   #define CPU_USES_BLOCK_MOVE      1 
712
713   #define CPBLK_MOVS_LIMIT         16      // When generating code for CpBlk, this is the buffer size 
714                                            // threshold to stop generating rep movs and switch to the helper call.
715                                            // NOTE: Using rep movs is currently disabled since we found it has bad performance
716                                            //       on pre-Ivy Bridge hardware.
717                                            
718   #define CPBLK_UNROLL_LIMIT       64      // Upper bound to let the code generator to loop unroll CpBlk.
719   #define INITBLK_STOS_LIMIT       64      // When generating code for InitBlk, this is the buffer size 
720                                            // NOTE: Using rep stos is currently disabled since we found it has bad performance
721                                            //       on pre-Ivy Bridge hardware.
722                                            // threshold to stop generating rep movs and switch to the helper call.
723   #define INITBLK_UNROLL_LIMIT     128     // Upper bound to let the code generator to loop unroll InitBlk.
724   #define CPOBJ_NONGC_SLOTS_LIMIT  4       // For CpObj code generation, this is the the threshold of the number 
725                                            // of contiguous non-gc slots that trigger generating rep movsq instead of 
726                                            // sequences of movsq instructions
727
728                                            // The way we're currently disabling rep movs/stos is by setting a limit less than
729                                            // its unrolling counterparts.  When lower takes the decision on which one to make it
730                                            // always asks for the unrolling limit first so you can say the JIT 'favors' unrolling.
731                                            // Setting the limit to something lower than that makes lower to never consider it.
732
733
734 #ifdef FEATURE_SIMD
735   #define ALIGN_SIMD_TYPES         1       // whether SIMD type locals are to be aligned
736 #if defined(UNIX_AMD64_ABI) || !defined(FEATURE_AVX_SUPPORT)
737   #define FEATURE_PARTIAL_SIMD_CALLEE_SAVE 0 // Whether SIMD registers are partially saved at calls
738 #else // !UNIX_AMD64_ABI && !FEATURE_AVX_SUPPORT
739   #define FEATURE_PARTIAL_SIMD_CALLEE_SAVE 1 // Whether SIMD registers are partially saved at calls
740 #endif // !UNIX_AMD64_ABI
741 #endif
742   #define FEATURE_WRITE_BARRIER    1       // Generate the WriteBarrier calls for GC (currently not the x86-style register-customized barriers)
743   #define FEATURE_FIXED_OUT_ARGS   1       // Preallocate the outgoing arg area in the prolog
744   #define FEATURE_STRUCTPROMOTE    1       // JIT Optimization to promote fields of structs into registers
745   #define FEATURE_MULTIREG_STRUCT_PROMOTE  0  // True when we want to promote fields of a multireg struct into registers
746   #define FEATURE_FASTTAILCALL     1       // Tail calls made as epilog+jmp
747   #define FEATURE_TAILCALL_OPT     1       // opportunistic Tail calls (i.e. without ".tail" prefix) made as fast tail calls.
748   #define FEATURE_SET_FLAGS        0       // Set to true to force the JIT to mark the trees with GTF_SET_FLAGS when the flags need to be set
749 #ifdef    UNIX_AMD64_ABI
750   #define FEATURE_MULTIREG_ARGS_OR_RET  1  // Support for passing and/or returning single values in more than one register
751   #define FEATURE_MULTIREG_ARGS         1  // Support for passing a single argument in more than one register  
752   #define FEATURE_MULTIREG_RET          1  // Support for returning a single value in more than one register
753   #define FEATURE_STRUCT_CLASSIFIER     1  // Uses a classifier function to determine if structs are passed/returned in more than one register
754   #define MAX_PASS_MULTIREG_BYTES      32  // Maximum size of a struct that could be passed in more than one register (Max is two SIMD16s)
755   #define MAX_RET_MULTIREG_BYTES       32  // Maximum size of a struct that could be returned in more than one register  (Max is two SIMD16s)
756   #define MAX_ARG_REG_COUNT             2  // Maximum registers used to pass a single argument in multiple registers.
757   #define MAX_RET_REG_COUNT             2  // Maximum registers used to return a value.
758 #else // !UNIX_AMD64_ABI
759   #define WINDOWS_AMD64_ABI                // Uses the Windows ABI for AMD64
760   #define FEATURE_MULTIREG_ARGS_OR_RET  0  // Support for passing and/or returning single values in more than one register
761   #define FEATURE_MULTIREG_ARGS         0  // Support for passing a single argument in more than one register  
762   #define FEATURE_MULTIREG_RET          0  // Support for returning a single value in more than one register
763   #define MAX_PASS_MULTIREG_BYTES       0  // No multireg arguments 
764   #define MAX_RET_MULTIREG_BYTES        0  // No multireg return values 
765   #define MAX_ARG_REG_COUNT             1  // Maximum registers used to pass a single argument (no arguments are passed using multiple registers)
766   #define MAX_RET_REG_COUNT             1  // Maximum registers used to return a value.
767 #endif // !UNIX_AMD64_ABI
768
769 #ifdef FEATURE_USE_ASM_GC_WRITE_BARRIERS
770   #define NOGC_WRITE_BARRIERS      0       // We DO-NOT have specialized WriteBarrier JIT Helpers that DO-NOT trash the RBM_CALLEE_TRASH registers
771 #else
772   #define NOGC_WRITE_BARRIERS      0       // Do not modify this -- modify the definition above.  (If we're not using ASM barriers we definitely don't have NOGC barriers).
773 #endif
774   #define USER_ARGS_COME_LAST      1
775   #define EMIT_TRACK_STACK_DEPTH   1
776   #define TARGET_POINTER_SIZE      8       // equal to sizeof(void*) and the managed pointer size in bytes for this target
777   #define FEATURE_EH               1       // To aid platform bring-up, eliminate exceptional EH clauses (catch, filter, filter-handler, fault) and directly execute 'finally' clauses.
778   #define FEATURE_EH_FUNCLETS      1
779   #define FEATURE_EH_CALLFINALLY_THUNKS 1  // Generate call-to-finally code in "thunks" in the enclosing EH region, protected by "cloned finally" clauses.
780   #define FEATURE_STACK_FP_X87     0 
781 #ifdef    UNIX_AMD64_ABI
782   #define ETW_EBP_FRAMED           1       // if 1 we cannot use EBP as a scratch register and must create EBP based frames for most methods
783 #else // !UNIX_AMD64_ABI
784   #define ETW_EBP_FRAMED           0       // if 1 we cannot use EBP as a scratch register and must create EBP based frames for most methods
785 #endif // !UNIX_AMD64_ABI
786   #define FEATURE_FP_REGALLOC      0       // Enabled if RegAlloc is used to enregister Floating Point LclVars  
787   #define CSE_CONSTS               1       // Enable if we want to CSE constants
788
789   #define RBM_ALLFLOAT            (RBM_XMM0 | RBM_XMM1 | RBM_XMM2 | RBM_XMM3 | RBM_XMM4 | RBM_XMM5 | RBM_XMM6 | RBM_XMM7 | RBM_XMM8 | RBM_XMM9 | RBM_XMM10 | RBM_XMM11 | RBM_XMM12 | RBM_XMM13 | RBM_XMM14 | RBM_XMM15)
790   #define RBM_ALLDOUBLE            RBM_ALLFLOAT
791   #define REG_FP_FIRST             REG_XMM0
792   #define REG_FP_LAST              REG_XMM15
793   #define FIRST_FP_ARGREG          REG_XMM0
794
795 #ifdef    UNIX_AMD64_ABI
796   #define LAST_FP_ARGREG        REG_XMM7
797 #else // !UNIX_AMD64_ABI
798   #define LAST_FP_ARGREG        REG_XMM3
799 #endif // !UNIX_AMD64_ABI
800
801   #define REGNUM_BITS              6       // number of bits in a REG_*
802   #define TINY_REGNUM_BITS         6       // number used in a tiny instrdesc (same)
803   #define REGMASK_BITS             32      // number of bits in a REGNUM_MASK
804   #define REGSIZE_BYTES            8       // number of bytes in one register
805   #define XMM_REGSIZE_BYTES        16      // XMM register size in bytes
806   #define YMM_REGSIZE_BYTES        32      // YMM register size in bytes
807
808   #define CODE_ALIGN               1       // code alignment requirement
809   #define STACK_ALIGN              16      // stack alignment requirement
810   #define STACK_ALIGN_SHIFT        3       // Shift-right amount to convert stack size in bytes to size in pointer sized words
811   #define STACK_ALIGN_SHIFT_ALL    4       // Shift-right amount to convert stack size in bytes to size in STACK_ALIGN units
812
813 #if ETW_EBP_FRAMED
814   #define RBM_ETW_FRAMED_EBP        RBM_NONE
815   #define RBM_ETW_FRAMED_EBP_LIST
816   #define REG_ETW_FRAMED_EBP_LIST
817   #define REG_ETW_FRAMED_EBP_COUNT  0
818 #else // !ETW_EBP_FRAMED
819   #define RBM_ETW_FRAMED_EBP        RBM_EBP
820   #define RBM_ETW_FRAMED_EBP_LIST   RBM_EBP,
821   #define REG_ETW_FRAMED_EBP_LIST   REG_EBP,
822   #define REG_ETW_FRAMED_EBP_COUNT  1
823 #endif // !ETW_EBP_FRAMED
824
825 #ifdef UNIX_AMD64_ABI
826   #define MIN_ARG_AREA_FOR_CALL   0       // Minimum required outgoing argument space for a call.
827
828   #define RBM_INT_CALLEE_SAVED    (RBM_EBX|RBM_ETW_FRAMED_EBP|RBM_R12|RBM_R13|RBM_R14|RBM_R15)
829   #define RBM_INT_CALLEE_TRASH    (RBM_EAX|RBM_RDI|RBM_RSI|RBM_EDX|RBM_ECX|RBM_R8|RBM_R9|RBM_R10|RBM_R11)
830   #define RBM_FLT_CALLEE_SAVED    (0)
831   #define RBM_FLT_CALLEE_TRASH    (RBM_XMM0|RBM_XMM1|RBM_XMM2|RBM_XMM3|RBM_XMM4|RBM_XMM5|RBM_XMM6|RBM_XMM7| \
832                                    RBM_XMM8|RBM_XMM9|RBM_XMM10|RBM_XMM11|RBM_XMM12|RBM_XMM13|RBM_XMM14|RBM_XMM15)
833 #else // !UNIX_AMD64_ABI
834 #define MIN_ARG_AREA_FOR_CALL     (4 * REGSIZE_BYTES)       // Minimum required outgoing argument space for a call.
835
836   #define RBM_INT_CALLEE_SAVED    (RBM_EBX|RBM_ESI|RBM_EDI|RBM_ETW_FRAMED_EBP|RBM_R12|RBM_R13|RBM_R14|RBM_R15)
837   #define RBM_INT_CALLEE_TRASH    (RBM_EAX|RBM_ECX|RBM_EDX|RBM_R8|RBM_R9|RBM_R10|RBM_R11)
838   #define RBM_FLT_CALLEE_SAVED    (RBM_XMM6|RBM_XMM7|RBM_XMM8|RBM_XMM9|RBM_XMM10|RBM_XMM11|RBM_XMM12|RBM_XMM13|RBM_XMM14|RBM_XMM15)
839   #define RBM_FLT_CALLEE_TRASH    (RBM_XMM0|RBM_XMM1|RBM_XMM2|RBM_XMM3|RBM_XMM4|RBM_XMM5)
840 #endif // !UNIX_AMD64_ABI
841   
842   #define REG_FLT_CALLEE_SAVED_FIRST   REG_XMM6
843   #define REG_FLT_CALLEE_SAVED_LAST    REG_XMM15
844
845   #define RBM_CALLEE_TRASH        (RBM_INT_CALLEE_TRASH | RBM_FLT_CALLEE_TRASH)
846   #define RBM_CALLEE_SAVED        (RBM_INT_CALLEE_SAVED | RBM_FLT_CALLEE_SAVED)      
847
848   #define RBM_CALLEE_TRASH_NOGC   RBM_CALLEE_TRASH
849
850   #define RBM_ALLINT              (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH)
851
852 #if 0
853 #define REG_VAR_ORDER            REG_EAX,REG_EDX,REG_ECX,REG_ESI,REG_EDI,REG_EBX,REG_ETW_FRAMED_EBP_LIST \
854                                  REG_R8,REG_R9,REG_R10,REG_R11,REG_R14,REG_R15,REG_R12,REG_R13
855 #else
856   // TEMPORARY ORDER TO AVOID CALLEE-SAVES
857   // TODO-CQ: Review this and set appropriately
858 #ifdef UNIX_AMD64_ABI
859   #define REG_VAR_ORDER          REG_EAX,REG_EDI,REG_ESI, \
860                                  REG_EDX,REG_ECX,REG_R8,REG_R9, \
861                                  REG_R10,REG_R11,REG_EBX,REG_ETW_FRAMED_EBP_LIST \
862                                  REG_R14,REG_R15,REG_R12,REG_R13
863 #else // !UNIX_AMD64_ABI
864   #define REG_VAR_ORDER          REG_EAX,REG_EDX,REG_ECX, \
865                                  REG_R8,REG_R9,REG_R10,REG_R11, \
866                                  REG_ESI,REG_EDI,REG_EBX,REG_ETW_FRAMED_EBP_LIST \
867                                  REG_R14,REG_R15,REG_R12,REG_R13
868 #endif // !UNIX_AMD64_ABI
869 #endif
870
871   #define REG_VAR_ORDER_FLT      REG_XMM0,REG_XMM1,REG_XMM2,REG_XMM3,REG_XMM4,REG_XMM5,REG_XMM6,REG_XMM7,REG_XMM8,REG_XMM9,REG_XMM10,REG_XMM11,REG_XMM12,REG_XMM13,REG_XMM14,REG_XMM15
872
873 #ifdef UNIX_AMD64_ABI
874   #define REG_TMP_ORDER          REG_EAX,REG_EDI,REG_ESI,REG_EDX,REG_ECX,REG_EBX,REG_ETW_FRAMED_EBP_LIST \
875                                  REG_R8,REG_R9,REG_R10,REG_R11,REG_R14,REG_R15,REG_R12,REG_R13
876 #else // !UNIX_AMD64_ABI
877   #define MAX_VAR_ORDER_SIZE     (14 + REG_ETW_FRAMED_EBP_COUNT)
878   #define REG_TMP_ORDER          REG_EAX,REG_EDX,REG_ECX,REG_EBX,REG_ESI,REG_EDI,REG_ETW_FRAMED_EBP_LIST \
879                                  REG_R8,REG_R9,REG_R10,REG_R11,REG_R14,REG_R15,REG_R12,REG_R13
880 #endif // !UNIX_AMD64_ABI
881
882 #ifdef UNIX_AMD64_ABI
883   #define REG_PREDICT_ORDER        REG_EAX,REG_EDI,REG_ESI,REG_EDX,REG_ECX,REG_EBX,REG_ETW_FRAMED_EBP_LIST \
884                                    REG_R8,REG_R9,REG_R10,REG_R11,REG_R14,REG_R15,REG_R12,REG_R13
885   #define CNT_CALLEE_SAVED         (5 + REG_ETW_FRAMED_EBP_COUNT)
886   #define CNT_CALLEE_TRASH         (9)
887   #define CNT_CALLEE_ENREG         (CNT_CALLEE_SAVED)
888
889   #define CNT_CALLEE_SAVED_FLOAT   (0)
890   #define CNT_CALLEE_TRASH_FLOAT   (16)
891
892   #define REG_CALLEE_SAVED_ORDER   REG_EBX,REG_ETW_FRAMED_EBP_LIST REG_R12,REG_R13,REG_R14,REG_R15
893   #define RBM_CALLEE_SAVED_ORDER   RBM_EBX,RBM_ETW_FRAMED_EBP_LIST RBM_R12,RBM_R13,RBM_R14,RBM_R15
894 #else // !UNIX_AMD64_ABI
895   #define REG_TMP_ORDER_COUNT      (14 + REG_ETW_FRAMED_EBP_COUNT)
896   #define REG_PREDICT_ORDER        REG_EAX,REG_EDX,REG_ECX,REG_EBX,REG_ESI,REG_EDI,REG_ETW_FRAMED_EBP_LIST \
897                                    REG_R8,REG_R9,REG_R10,REG_R11,REG_R14,REG_R15,REG_R12,REG_R13
898   #define CNT_CALLEE_SAVED         (7 + REG_ETW_FRAMED_EBP_COUNT)
899   #define CNT_CALLEE_TRASH         (7)
900   #define CNT_CALLEE_ENREG         (CNT_CALLEE_SAVED)
901
902   #define CNT_CALLEE_SAVED_FLOAT   (10)
903   #define CNT_CALLEE_TRASH_FLOAT   (6)
904
905   #define REG_CALLEE_SAVED_ORDER   REG_EBX,REG_ESI,REG_EDI,REG_ETW_FRAMED_EBP_LIST REG_R12,REG_R13,REG_R14,REG_R15
906   #define RBM_CALLEE_SAVED_ORDER   RBM_EBX,RBM_ESI,RBM_EDI,RBM_ETW_FRAMED_EBP_LIST RBM_R12,RBM_R13,RBM_R14,RBM_R15
907 #endif // !UNIX_AMD64_ABI
908
909   #define CALLEE_SAVED_REG_MAXSZ   (CNT_CALLEE_SAVED*REGSIZE_BYTES)
910   #define CALLEE_SAVED_FLOAT_MAXSZ (CNT_CALLEE_SAVED_FLOAT*16)
911
912   // We reuse the ESP register as a illegal value in the register predictor
913   #define RBM_ILLEGAL              RBM_ESP
914   // We reuse the ESP register as a flag for last use handling in the register predictor
915   #define RBM_LASTUSE              RBM_ESP
916   // We're using the encoding for ESP to indicate a half-long on the frame
917   #define REG_L_STK                REG_ESP
918
919   //  This is the first register in REG_TMP_ORDER
920   #define REG_TMP_0                REG_EAX
921   #define RBM_TMP_0                RBM_EAX
922
923   //  This is the second register in REG_TMP_ORDER
924 #ifdef UNIX_AMD64_ABI
925   #define REG_TMP_1                REG_EDI
926   #define RBM_TMP_1                RBM_EDI
927 #else // !UNIX_AMD64_ABI
928   #define REG_TMP_1                REG_EDX
929   #define RBM_TMP_1                RBM_EDX
930 #endif // !UNIX_AMD64_ABI
931   #define REG_PAIR_TMP             REG_PAIR_EAXEDX
932   #define RBM_PAIR_TMP             (RBM_EAX|RBM_EDX)
933   #define REG_PAIR_TMP_LO          REG_EAX
934   #define RBM_PAIR_TMP_LO          RBM_EAX
935   #define REG_PAIR_TMP_HI          REG_EDX
936   #define RBM_PAIR_TMP_HI          RBM_EDX
937   #define PREDICT_PAIR_TMP         PREDICT_PAIR_RAXRDX
938   #define PREDICT_PAIR_TMP_LO      PREDICT_REG_EAX
939   
940   // register to hold shift amount
941   #define REG_SHIFT                REG_ECX
942   #define RBM_SHIFT                RBM_ECX
943   #define PREDICT_REG_SHIFT        PREDICT_REG_ECX
944   
945   // This is a general scratch register that does not conflict with the argument registers
946   #define REG_SCRATCH              REG_EAX
947   #define RBM_SCRATCH              RBM_EAX
948
949 // Where is the exception object on entry to the handler block?
950 #ifdef UNIX_AMD64_ABI
951   #define REG_EXCEPTION_OBJECT     REG_ESI
952   #define RBM_EXCEPTION_OBJECT     RBM_ESI
953 #else // !UNIX_AMD64_ABI
954   #define REG_EXCEPTION_OBJECT     REG_EDX
955   #define RBM_EXCEPTION_OBJECT     RBM_EDX
956 #endif // !UNIX_AMD64_ABI
957
958   #define REG_JUMP_THUNK_PARAM     REG_EAX
959   #define RBM_JUMP_THUNK_PARAM     RBM_EAX
960
961 #if NOGC_WRITE_BARRIERS
962   #define REG_WRITE_BARRIER        REG_EDX
963   #define RBM_WRITE_BARRIER        RBM_EDX
964 #endif
965
966   // Register to be used for emitting helper calls whose call target is an indir of an
967   // absolute memory address in case of Rel32 overflow i.e. a data address could not be
968   // encoded as PC-relative 32-bit offset.
969   //
970   // Notes:
971   // 1) that RAX is callee trash register that is not used for passing parameter and
972   //    also results in smaller instruction encoding.  
973   // 2) Profiler Leave callback requires the return value to be preserved
974   //    in some form.  We can use custom calling convention for Leave callback.
975   //    For e.g return value could be preserved in rcx so that it is available for
976   //    profiler.
977   #define REG_DEFAULT_HELPER_CALL_TARGET    REG_RAX
978
979   // GenericPInvokeCalliHelper VASigCookie Parameter 
980   #define REG_PINVOKE_COOKIE_PARAM          REG_R11
981   #define RBM_PINVOKE_COOKIE_PARAM          RBM_R11
982   #define PREDICT_REG_PINVOKE_COOKIE_PARAM  PREDICT_REG_R11
983
984   // GenericPInvokeCalliHelper unmanaged target Parameter 
985   #define REG_PINVOKE_TARGET_PARAM          REG_R10
986   #define RBM_PINVOKE_TARGET_PARAM          RBM_R10
987   #define PREDICT_REG_PINVOKE_TARGET_PARAM  PREDICT_REG_R10
988
989   // IL stub's secret MethodDesc parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM)
990   #define REG_SECRET_STUB_PARAM    REG_R10
991   #define RBM_SECRET_STUB_PARAM    RBM_R10
992
993   // VSD extra parameter (slot address)
994   #define REG_VIRTUAL_STUB_PARAM   REG_R11
995   #define RBM_VIRTUAL_STUB_PARAM   RBM_R11
996   #define PREDICT_REG_VIRTUAL_STUB_PARAM  PREDICT_REG_R11
997
998   // Registers used by PInvoke frame setup
999   #define REG_PINVOKE_FRAME        REG_EDI
1000   #define RBM_PINVOKE_FRAME        RBM_EDI
1001   #define REG_PINVOKE_TCB          REG_EAX
1002   #define RBM_PINVOKE_TCB          RBM_EAX
1003   #define REG_PINVOKE_SCRATCH      REG_EAX
1004   #define RBM_PINVOKE_SCRATCH      RBM_EAX
1005
1006   // The following defines are useful for iterating a regNumber
1007   #define REG_FIRST                REG_EAX
1008   #define REG_INT_FIRST            REG_EAX
1009   #define REG_INT_LAST             REG_R15
1010   #define REG_INT_COUNT            (REG_INT_LAST - REG_INT_FIRST + 1)
1011   #define REG_NEXT(reg)           ((regNumber)((unsigned)(reg) + 1))
1012   #define REG_PREV(reg)           ((regNumber)((unsigned)(reg) - 1))
1013
1014   // genCodeForCall() moves the target address of the tailcall into this register, before pushing it on the stack
1015   #define REG_TAILCALL_ADDR        REG_RDX
1016
1017   // Which register are int and long values returned in ?
1018   #define REG_INTRET               REG_EAX
1019   #define RBM_INTRET               RBM_EAX
1020
1021   #define REG_LNGRET               REG_EAX
1022   #define RBM_LNGRET               RBM_EAX
1023
1024 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
1025     #define REG_INTRET_1           REG_RDX
1026     #define RBM_INTRET_1           RBM_RDX
1027
1028     #define REG_LNGRET_1           REG_RDX
1029     #define RBM_LNGRET_1           RBM_RDX
1030 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
1031
1032
1033   #define REG_FLOATRET             REG_XMM0
1034   #define RBM_FLOATRET             RBM_XMM0
1035   #define REG_DOUBLERET            REG_XMM0
1036   #define RBM_DOUBLERET            RBM_XMM0
1037
1038 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
1039 #define REG_FLOATRET_1             REG_XMM1
1040 #define RBM_FLOATRET_1             RBM_XMM1
1041
1042 #define REG_DOUBLERET_1            REG_XMM1
1043 #define RBM_DOUBLERET_1            RBM_XMM1
1044 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
1045
1046   #define REG_FPBASE               REG_EBP
1047   #define RBM_FPBASE               RBM_EBP
1048   #define STR_FPBASE               "rbp"
1049   #define REG_SPBASE               REG_ESP
1050   #define RBM_SPBASE               RBM_ESP
1051   #define STR_SPBASE               "rsp"
1052
1053   #define FIRST_ARG_STACK_OFFS     (REGSIZE_BYTES)   // return address
1054
1055 #ifdef UNIX_AMD64_ABI
1056   #define MAX_REG_ARG              6
1057   #define MAX_FLOAT_REG_ARG        8
1058   #define REG_ARG_FIRST            REG_EDI
1059   #define REG_ARG_LAST             REG_R9
1060   #define INIT_ARG_STACK_SLOT      0                  // No outgoing reserved stack slots
1061
1062   #define REG_ARG_0                REG_EDI
1063   #define REG_ARG_1                REG_ESI
1064   #define REG_ARG_2                REG_EDX
1065   #define REG_ARG_3                REG_ECX
1066   #define REG_ARG_4                REG_R8
1067   #define REG_ARG_5                REG_R9
1068
1069   SELECTANY const regNumber intArgRegs [] = { REG_EDI, REG_ESI, REG_EDX, REG_ECX, REG_R8, REG_R9 };
1070   SELECTANY const regMaskTP intArgMasks[] = { RBM_EDI, RBM_ESI, RBM_EDX, RBM_ECX, RBM_R8, RBM_R9 };
1071   SELECTANY const regNumber fltArgRegs [] = { REG_XMM0, REG_XMM1, REG_XMM2, REG_XMM3, REG_XMM4, REG_XMM5, REG_XMM6, REG_XMM7 };
1072   SELECTANY const regMaskTP fltArgMasks[] = { RBM_XMM0, RBM_XMM1, RBM_XMM2, RBM_XMM3, RBM_XMM4, RBM_XMM5, RBM_XMM6, RBM_XMM7 };
1073
1074   #define RBM_ARG_0                RBM_RDI
1075   #define RBM_ARG_1                RBM_RSI
1076   #define RBM_ARG_2                RBM_EDX
1077   #define RBM_ARG_3                RBM_ECX
1078   #define RBM_ARG_4                RBM_R8
1079   #define RBM_ARG_5                RBM_R9
1080 #else // !UNIX_AMD64_ABI
1081   #define MAX_REG_ARG              4
1082   #define MAX_FLOAT_REG_ARG        4
1083   #define REG_ARG_FIRST            REG_ECX
1084   #define REG_ARG_LAST             REG_R9
1085   #define INIT_ARG_STACK_SLOT      4                  // 4 outgoing reserved stack slots
1086
1087   #define REG_ARG_0                REG_ECX
1088   #define REG_ARG_1                REG_EDX
1089   #define REG_ARG_2                REG_R8
1090   #define REG_ARG_3                REG_R9
1091
1092   SELECTANY const regNumber intArgRegs [] = { REG_ECX, REG_EDX, REG_R8, REG_R9 };
1093   SELECTANY const regMaskTP intArgMasks[] = { RBM_ECX, RBM_EDX, RBM_R8, RBM_R9 };
1094   SELECTANY const regNumber fltArgRegs [] = { REG_XMM0, REG_XMM1, REG_XMM2, REG_XMM3 };
1095   SELECTANY const regMaskTP fltArgMasks[] = { RBM_XMM0, RBM_XMM1, RBM_XMM2, RBM_XMM3 };
1096
1097   #define RBM_ARG_0                RBM_ECX
1098   #define RBM_ARG_1                RBM_EDX
1099   #define RBM_ARG_2                RBM_R8
1100   #define RBM_ARG_3                RBM_R9
1101 #endif // !UNIX_AMD64_ABI
1102
1103   #define REG_FLTARG_0             REG_XMM0
1104   #define REG_FLTARG_1             REG_XMM1
1105   #define REG_FLTARG_2             REG_XMM2
1106   #define REG_FLTARG_3             REG_XMM3
1107
1108   #define RBM_FLTARG_0             RBM_XMM0
1109   #define RBM_FLTARG_1             RBM_XMM1
1110   #define RBM_FLTARG_2             RBM_XMM2
1111   #define RBM_FLTARG_3             RBM_XMM3
1112
1113 #ifdef UNIX_AMD64_ABI
1114   #define REG_FLTARG_4             REG_XMM4
1115   #define REG_FLTARG_5             REG_XMM5
1116   #define REG_FLTARG_6             REG_XMM6
1117   #define REG_FLTARG_7             REG_XMM7
1118
1119   #define RBM_FLTARG_4             RBM_XMM4
1120   #define RBM_FLTARG_5             RBM_XMM5
1121   #define RBM_FLTARG_6             RBM_XMM6
1122   #define RBM_FLTARG_7             RBM_XMM7
1123
1124   #define RBM_ARG_REGS            (RBM_ARG_0|RBM_ARG_1|RBM_ARG_2|RBM_ARG_3|RBM_ARG_4|RBM_ARG_5)
1125   #define RBM_FLTARG_REGS         (RBM_FLTARG_0|RBM_FLTARG_1|RBM_FLTARG_2|RBM_FLTARG_3|RBM_FLTARG_4|RBM_FLTARG_5|RBM_FLTARG_6|RBM_FLTARG_7)
1126 #else // !UNIX_AMD64_ABI
1127   #define RBM_ARG_REGS            (RBM_ARG_0|RBM_ARG_1|RBM_ARG_2|RBM_ARG_3)
1128   #define RBM_FLTARG_REGS         (RBM_FLTARG_0|RBM_FLTARG_1|RBM_FLTARG_2|RBM_FLTARG_3)
1129 #endif // !UNIX_AMD64_ABI
1130
1131   // The registers trashed by profiler enter/leave/tailcall hook
1132   // See vm\amd64\asmhelpers.asm for more details.
1133   #define RBM_PROFILER_ENTER_TRASH     RBM_CALLEE_TRASH
1134   #define RBM_PROFILER_LEAVE_TRASH     (RBM_CALLEE_TRASH & ~(RBM_FLOATRET | RBM_INTRET))
1135   #define RBM_PROFILER_TAILCALL_TRASH  RBM_PROFILER_LEAVE_TRASH
1136
1137   // The registers trashed by the CORINFO_HELP_STOP_FOR_GC helper.
1138 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
1139   // See vm\amd64\unixasmhelpers.S for more details.
1140   //
1141   // On Unix a struct of size >=9 and <=16 bytes in size is returned in two return registers.
1142   // The return registers could be any two from the set { RAX, RDX, XMM0, XMM1 }.
1143   // STOP_FOR_GC helper preserves all the 4 possible return registers.
1144   #define RBM_STOP_FOR_GC_TRASH     (RBM_CALLEE_TRASH & ~(RBM_FLOATRET | RBM_INTRET | RBM_FLOATRET_1 | RBM_INTRET_1))
1145 #else
1146   // See vm\amd64\asmhelpers.asm for more details.
1147   #define RBM_STOP_FOR_GC_TRASH     (RBM_CALLEE_TRASH & ~(RBM_FLOATRET | RBM_INTRET))
1148 #endif
1149
1150   // The registers trashed by the CORINFO_HELP_INIT_PINVOKE_FRAME helper.
1151   #define RBM_INIT_PINVOKE_FRAME_TRASH  RBM_CALLEE_TRASH
1152
1153   // What sort of reloc do we use for [disp32] address mode
1154   #define IMAGE_REL_BASED_DISP32   IMAGE_REL_BASED_REL32
1155
1156   // What sort of reloc to we use for 'moffset' address mode (for 'mov eax, moffset' or 'mov moffset, eax')
1157   #define IMAGE_REL_BASED_MOFFSET  IMAGE_REL_BASED_DIR64
1158
1159   // Pointer-sized string move instructions
1160   #define INS_movsp                INS_movsq
1161   #define INS_r_movsp              INS_r_movsq
1162   #define INS_stosp                INS_stosq
1163   #define INS_r_stosp              INS_r_stosq
1164
1165 #elif defined(_TARGET_ARM_)
1166
1167   // TODO-ARM-CQ: Use shift for division by power of 2
1168   // TODO-ARM-CQ: Check for sdiv/udiv at runtime and generate it if available
1169   #define USE_HELPERS_FOR_INT_DIV  1       // BeagleBoard (ARMv7A) doesn't support SDIV/UDIV
1170   #define CPU_LOAD_STORE_ARCH      1
1171 #ifdef LEGACY_BACKEND
1172   #define CPU_LONG_USES_REGPAIR    1
1173 #else
1174   #define CPU_LONG_USES_REGPAIR    0
1175 #endif
1176   #define CPU_HAS_FP_SUPPORT       1
1177   #define ROUND_FLOAT              0       // Do not round intermed float expression results
1178   #define CPU_HAS_BYTE_REGS        0
1179   #define CPU_USES_BLOCK_MOVE      0
1180   #define FEATURE_WRITE_BARRIER    1       // Generate the proper WriteBarrier calls for GC    
1181   #define FEATURE_FIXED_OUT_ARGS   1       // Preallocate the outgoing arg area in the prolog
1182   #define FEATURE_STRUCTPROMOTE    1       // JIT Optimization to promote fields of structs into registers
1183   #define FEATURE_MULTIREG_STRUCT_PROMOTE  0  // True when we want to promote fields of a multireg struct into registers
1184   #define FEATURE_FASTTAILCALL     0       // Tail calls made as epilog+jmp
1185   #define FEATURE_TAILCALL_OPT     0       // opportunistic Tail calls (i.e. without ".tail" prefix) made as fast tail calls.
1186   #define FEATURE_SET_FLAGS        1       // Set to true to force the JIT to mark the trees with GTF_SET_FLAGS when the flags need to be set
1187   #define FEATURE_MULTIREG_ARGS_OR_RET  1  // Support for passing and/or returning single values in more than one register (including HFA support)
1188   #define FEATURE_MULTIREG_ARGS         1  // Support for passing a single argument in more than one register (including passing HFAs)
1189   #define FEATURE_MULTIREG_RET          1  // Support for returning a single value in more than one register (including HFA returns)
1190   #define FEATURE_STRUCT_CLASSIFIER     0  // Uses a classifier function to determine is structs are passed/returned in more than one register
1191   #define MAX_PASS_MULTIREG_BYTES      32  // Maximum size of a struct that could be passed in more than one register (Max is an HFA of 4 doubles)
1192   #define MAX_RET_MULTIREG_BYTES       32  // Maximum size of a struct that could be returned in more than one register (Max is an HFA of 4 doubles)
1193   #define MAX_ARG_REG_COUNT             4  // Maximum registers used to pass a single argument in multiple registers. (max is 4 floats or doubles using an HFA)
1194   #define MAX_RET_REG_COUNT             4  // Maximum registers used to return a value.
1195
1196 #ifdef FEATURE_USE_ASM_GC_WRITE_BARRIERS
1197   #define NOGC_WRITE_BARRIERS      0       // We DO-NOT have specialized WriteBarrier JIT Helpers that DO-NOT trash the RBM_CALLEE_TRASH registers
1198 #else
1199   #define NOGC_WRITE_BARRIERS      0       // Do not modify this -- modify the definition above.  (If we're not using ASM barriers we definitely don't have NOGC barriers).
1200 #endif
1201   #define USER_ARGS_COME_LAST      1
1202   #define EMIT_TRACK_STACK_DEPTH   1       // This is something of a workaround.  For both ARM and AMD64, the frame size is fixed, so we don't really
1203                                            // need to track stack depth, but this is currently necessary to get GC information reported at call sites.
1204   #define TARGET_POINTER_SIZE      4       // equal to sizeof(void*) and the managed pointer size in bytes for this target
1205   #define FEATURE_EH               1       // To aid platform bring-up, eliminate exceptional EH clauses (catch, filter, filter-handler, fault) and directly execute 'finally' clauses.
1206   #define FEATURE_EH_FUNCLETS      1
1207   #define FEATURE_EH_CALLFINALLY_THUNKS 0  // Generate call-to-finally code in "thunks" in the enclosing EH region, protected by "cloned finally" clauses.
1208   #define FEATURE_STACK_FP_X87     0 
1209   #define ETW_EBP_FRAMED           1       // if 1 we cannot use REG_FP as a scratch register and must setup the frame pointer for most methods
1210   #define FEATURE_FP_REGALLOC      1       // Enabled if RegAlloc is used to enregister Floating Point LclVars  
1211   #define CSE_CONSTS               1       // Enable if we want to CSE constants 
1212
1213   #define REG_FP_FIRST             REG_F0
1214   #define REG_FP_LAST              REG_F31
1215   #define FIRST_FP_ARGREG          REG_F0
1216   #define LAST_FP_ARGREG           REG_F15
1217
1218   #define REGNUM_BITS              6       // number of bits in a REG_*
1219   #define TINY_REGNUM_BITS         4       // number of bits we will use for a tiny instr desc (may not use float)
1220   #define REGMASK_BITS             64      // number of bits in a REGNUM_MASK
1221   #define REGSIZE_BYTES            4       // number of bytes in one register
1222   #define MIN_ARG_AREA_FOR_CALL    0       // Minimum required outgoing argument space for a call.
1223
1224   #define CODE_ALIGN               2       // code alignment requirement
1225   #define STACK_ALIGN              8       // stack alignment requirement
1226   #define STACK_ALIGN_SHIFT        2       // Shift-right amount to convert stack size in bytes to size in DWORD_PTRs
1227
1228   #define RBM_INT_CALLEE_SAVED    (RBM_R4|RBM_R5|RBM_R6|RBM_R7|RBM_R8|RBM_R9|RBM_R10)
1229   #define RBM_INT_CALLEE_TRASH    (RBM_R0|RBM_R1|RBM_R2|RBM_R3|RBM_R12|RBM_LR)
1230   #define RBM_FLT_CALLEE_SAVED    (RBM_F16|RBM_F17|RBM_F18|RBM_F19|RBM_F20|RBM_F21|RBM_F22|RBM_F23|RBM_F24|RBM_F25|RBM_F26|RBM_F27|RBM_F28|RBM_F29|RBM_F30|RBM_F31)
1231   #define RBM_FLT_CALLEE_TRASH    (RBM_F0|RBM_F1|RBM_F2|RBM_F3|RBM_F4|RBM_F5|RBM_F6|RBM_F7|RBM_F8|RBM_F9|RBM_F10|RBM_F11|RBM_F12|RBM_F13|RBM_F14|RBM_F15)
1232
1233   #define RBM_CALLEE_SAVED        (RBM_INT_CALLEE_SAVED | RBM_FLT_CALLEE_SAVED)
1234   #define RBM_CALLEE_TRASH        (RBM_INT_CALLEE_TRASH | RBM_FLT_CALLEE_TRASH)
1235 #ifdef LEGACY_BACKEND
1236   #define RBM_CALLEE_TRASH_NOGC   (RBM_R2|RBM_R3|RBM_LR)
1237 #else
1238   #define RBM_CALLEE_TRASH_NOGC   RBM_CALLEE_TRASH
1239 #endif
1240   #define REG_DEFAULT_HELPER_CALL_TARGET REG_R12
1241
1242   #define RBM_ALLINT              (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH)
1243   #define RBM_ALLFLOAT            (RBM_FLT_CALLEE_SAVED | RBM_FLT_CALLEE_TRASH)
1244   #define RBM_ALLDOUBLE           (RBM_F0|RBM_F2|RBM_F4|RBM_F6|RBM_F8|RBM_F10|RBM_F12|RBM_F14|RBM_F16|RBM_F18|RBM_F20|RBM_F22|RBM_F24|RBM_F26|RBM_F28|RBM_F30)
1245
1246   #define REG_VAR_ORDER            REG_R3,REG_R2,REG_R1,REG_R0,REG_R4,REG_LR,REG_R12,\
1247                                    REG_R5,REG_R6,REG_R7,REG_R8,REG_R9,REG_R10
1248
1249   #define REG_VAR_ORDER_FLT        REG_F8,  REG_F9,  REG_F10, REG_F11, \
1250                                    REG_F12, REG_F13, REG_F14, REG_F15, \
1251                                    REG_F6,  REG_F7,  REG_F4,  REG_F5,  \
1252                                    REG_F2,  REG_F3,  REG_F0,  REG_F1,  \
1253                                    REG_F16, REG_F17, REG_F18, REG_F19, \
1254                                    REG_F20, REG_F21, REG_F22, REG_F23, \
1255                                    REG_F24, REG_F25, REG_F26, REG_F27, \
1256                                    REG_F28, REG_F29, REG_F30, REG_F31,
1257
1258   #define MAX_VAR_ORDER_SIZE       32
1259
1260   #define REG_TMP_ORDER            REG_R3,REG_R2,REG_R1,REG_R0, REG_R4,REG_R5,REG_R6,REG_R7,\
1261                                    REG_LR,REG_R12,              REG_R8,REG_R9,REG_R10
1262   #define REG_TMP_ORDER_COUNT      13
1263
1264   #define REG_FLT_TMP_ORDER        REG_F14, REG_F15, REG_F12, REG_F13, \
1265                                    REG_F10, REG_F11, REG_F8,  REG_F9,  \
1266                                    REG_F6,  REG_F7,  REG_F4,  REG_F5,  \
1267                                    REG_F2,  REG_F3,  REG_F0,  REG_F1,  \
1268                                    REG_F16, REG_F17, REG_F18, REG_F19, \
1269                                    REG_F20, REG_F21, REG_F22, REG_F23, \
1270                                    REG_F24, REG_F25, REG_F26, REG_F27, \
1271                                    REG_F28, REG_F29, REG_F30, REG_F31,
1272
1273   #define REG_FLT_TMP_ORDER_COUNT  32
1274
1275   #define REG_PREDICT_ORDER        REG_LR,REG_R12,REG_R3,REG_R2,REG_R1,REG_R0, \
1276                                    REG_R7,REG_R6,REG_R5,REG_R4,REG_R8,REG_R9,REG_R10
1277
1278   #define RBM_LOW_REGS            (RBM_R0|RBM_R1|RBM_R2|RBM_R3|RBM_R4|RBM_R5|RBM_R6|RBM_R7)
1279   #define RBM_HIGH_REGS           (RBM_R8|RBM_R9|RBM_R10|RBM_R11|RBM_R12|RBM_SP|RBM_LR|RBM_PC)
1280
1281   #define REG_CALLEE_SAVED_ORDER   REG_R4,REG_R5,REG_R6,REG_R7,REG_R8,REG_R9,REG_R10,REG_R11
1282   #define RBM_CALLEE_SAVED_ORDER   RBM_R4,RBM_R5,RBM_R6,RBM_R7,RBM_R8,RBM_R9,RBM_R10,RBM_R11
1283
1284   #define CNT_CALLEE_SAVED        (8)
1285   #define CNT_CALLEE_TRASH        (6)
1286   #define CNT_CALLEE_ENREG        (CNT_CALLEE_SAVED-1)
1287
1288   #define CNT_CALLEE_SAVED_FLOAT  (16)
1289   #define CNT_CALLEE_TRASH_FLOAT  (16)
1290
1291   #define CALLEE_SAVED_REG_MAXSZ    (CNT_CALLEE_SAVED*REGSIZE_BYTES)
1292   #define CALLEE_SAVED_FLOAT_MAXSZ  (CNT_CALLEE_SAVED_FLOAT*sizeof(float))
1293
1294   // We reuse the ESP register as a illegal value in the register predictor
1295   #define RBM_ILLEGAL              RBM_SP
1296   // We reuse the ESP register as a flag for last use handling in the register predictor
1297   #define RBM_LASTUSE              RBM_SP
1298   // We're using the encoding for ESP to indicate a half-long on the frame
1299   #define REG_L_STK                REG_SP
1300
1301   //  This is the first register in REG_TMP_ORDER
1302   #define REG_TMP_0                REG_R3
1303   #define RBM_TMP_0                RBM_R3
1304
1305   //  This is the second register in REG_TMP_ORDER
1306   #define REG_TMP_1                REG_R2
1307   #define RBM_TMP_1                RBM_R2
1308
1309   //  This is the first register pair in REG_TMP_ORDER
1310   #define REG_PAIR_TMP             REG_PAIR_R2R3
1311   #define REG_PAIR_TMP_REVERSE     REG_PAIR_R3R2
1312   #define RBM_PAIR_TMP             (RBM_R2|RBM_R3)
1313   #define REG_PAIR_TMP_LO          REG_R2
1314   #define RBM_PAIR_TMP_LO          RBM_R2
1315   #define REG_PAIR_TMP_HI          REG_R3
1316   #define RBM_PAIR_TMP_HI          RBM_R3
1317   #define PREDICT_PAIR_TMP         PREDICT_PAIR_R2R3
1318   #define PREDICT_PAIR_TMP_LO      PREDICT_REG_R2
1319
1320   // Used when calling the 64-bit Variable shift helper
1321   #define REG_LNGARG_0             REG_PAIR_R0R1
1322   #define RBM_LNGARG_0            (RBM_R0|RBM_R1)
1323   #define PREDICT_PAIR_LNGARG_0    PREDICT_PAIR_R0R1
1324   
1325   // register to hold shift amount; no special register is required on the ARM
1326   #define REG_SHIFT                REG_NA
1327   #define RBM_SHIFT                RBM_ALLINT
1328   #define PREDICT_REG_SHIFT        PREDICT_REG
1329
1330   // register to hold shift amount when shifting 64-bit values (this uses a helper call)
1331   #define REG_SHIFT_LNG            REG_R2            // REG_ARG_2
1332   #define RBM_SHIFT_LNG            RBM_R2            // RBM_ARG_2
1333   #define PREDICT_REG_SHIFT_LNG    PREDICT_REG_R2
1334  
1335   
1336   // This is a general scratch register that does not conflict with the argument registers
1337   #define REG_SCRATCH              REG_LR
1338   #define RBM_SCRATCH              RBM_LR
1339
1340   // This is a general register that can be optionally reserved for other purposes during codegen
1341   #define REG_OPT_RSVD             REG_R10
1342   #define RBM_OPT_RSVD             RBM_R10
1343
1344   // We reserve R9 to store SP on entry for stack unwinding when localloc is used
1345   #define REG_SAVED_LOCALLOC_SP    REG_R9
1346   #define RBM_SAVED_LOCALLOC_SP    RBM_R9
1347
1348   // Where is the exception object on entry to the handler block?
1349   #define REG_EXCEPTION_OBJECT     REG_R0
1350   #define RBM_EXCEPTION_OBJECT     RBM_R0
1351
1352   #define REG_JUMP_THUNK_PARAM     REG_R12
1353   #define RBM_JUMP_THUNK_PARAM     RBM_R12
1354
1355 #if NOGC_WRITE_BARRIERS
1356   #define REG_WRITE_BARRIER        REG_R1
1357   #define RBM_WRITE_BARRIER        RBM_R1
1358 #endif
1359
1360   // GenericPInvokeCalliHelper VASigCookie Parameter 
1361   #define REG_PINVOKE_COOKIE_PARAM          REG_R4
1362   #define RBM_PINVOKE_COOKIE_PARAM          RBM_R4
1363   #define PREDICT_REG_PINVOKE_COOKIE_PARAM  PREDICT_REG_R4
1364
1365   // GenericPInvokeCalliHelper unmanaged target Parameter 
1366   #define REG_PINVOKE_TARGET_PARAM          REG_R12
1367   #define RBM_PINVOKE_TARGET_PARAM          RBM_R12
1368   #define PREDICT_REG_PINVOKE_TARGET_PARAM  PREDICT_REG_R12
1369
1370   // IL stub's secret MethodDesc parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM)
1371   #define REG_SECRET_STUB_PARAM     REG_R12
1372   #define RBM_SECRET_STUB_PARAM     RBM_R12
1373
1374   // VSD extra parameter (slot address)
1375   #define REG_VIRTUAL_STUB_PARAM          REG_R4
1376   #define RBM_VIRTUAL_STUB_PARAM          RBM_R4
1377   #define PREDICT_REG_VIRTUAL_STUB_PARAM  PREDICT_REG_R4
1378
1379   // R2R indirect call. Use the same registers as VSD
1380   #define REG_R2R_INDIRECT_PARAM          REG_R4
1381   #define RBM_R2R_INDIRECT_PARAM          RBM_R4
1382
1383   // Registers used by PInvoke frame setup
1384   #define REG_PINVOKE_FRAME        REG_R4
1385   #define RBM_PINVOKE_FRAME        RBM_R4
1386   #define REG_PINVOKE_TCB          REG_R5
1387   #define RBM_PINVOKE_TCB          RBM_R5
1388   #define REG_PINVOKE_SCRATCH      REG_R6
1389   #define RBM_PINVOKE_SCRATCH      RBM_R6
1390
1391 #ifdef LEGACY_BACKEND
1392   #define REG_SPILL_CHOICE         REG_LR
1393   #define RBM_SPILL_CHOICE         RBM_LR
1394   #define REG_SPILL_CHOICE_FLT     REG_F14
1395   #define RBM_SPILL_CHOICE_FLT    (RBM_F14|RBM_F15)
1396 #endif // LEGACY_BACKEND
1397
1398   // The following defines are useful for iterating a regNumber
1399   #define REG_FIRST                REG_R0
1400   #define REG_INT_FIRST            REG_R0
1401   #define REG_INT_LAST             REG_LR
1402   #define REG_INT_COUNT            (REG_INT_LAST - REG_INT_FIRST + 1)
1403   #define REG_NEXT(reg)           ((regNumber)((unsigned)(reg) + 1))
1404   #define REG_PREV(reg)           ((regNumber)((unsigned)(reg) - 1))
1405
1406   // genCodeForCall() moves the target address of the tailcall into this register, before pushing it on the stack
1407   #define REG_TAILCALL_ADDR        REG_R1
1408
1409   // The following registers are used in emitting Enter/Leave/Tailcall profiler callbacks
1410   #define REG_PROFILER_ENTER_ARG           REG_R0
1411   #define RBM_PROFILER_ENTER_ARG           RBM_R0
1412   #define REG_PROFILER_RET_SCRATCH         REG_R2
1413   #define RBM_PROFILER_RET_SCRATCH         RBM_R2
1414   #define RBM_PROFILER_RET_USED            (RBM_R0 | RBM_R1 | RBM_R2)
1415   #define REG_PROFILER_JMP_ARG             REG_R0
1416   #define RBM_PROFILER_JMP_USED            RBM_R0
1417   #define RBM_PROFILER_TAIL_USED           (RBM_R0 | RBM_R12 | RBM_LR)
1418   
1419
1420   // Which register are int and long values returned in ?
1421   #define REG_INTRET               REG_R0
1422   #define RBM_INTRET               RBM_R0
1423   #define REG_LNGRET               REG_PAIR_R0R1
1424   #define RBM_LNGRET              (RBM_R1|RBM_R0)
1425   #define REG_LNGRET_LO            REG_R0
1426   #define REG_LNGRET_HI            REG_R1
1427   #define RBM_LNGRET_LO            RBM_R0
1428   #define RBM_LNGRET_HI            RBM_R1
1429
1430   #define REG_FLOATRET             REG_F0
1431   #define RBM_FLOATRET             RBM_F0
1432   #define RBM_DOUBLERET           (RBM_F0|RBM_F1)
1433
1434   // The registers trashed by the CORINFO_HELP_STOP_FOR_GC helper
1435   // See vm\arm\amshelpers.asm for more details.
1436   #define RBM_STOP_FOR_GC_TRASH     (RBM_CALLEE_TRASH & ~(RBM_FLOATRET | RBM_INTRET))
1437
1438   // The registers trashed by the CORINFO_HELP_INIT_PINVOKE_FRAME helper.
1439   #define RBM_INIT_PINVOKE_FRAME_TRASH (RBM_CALLEE_TRASH | RBM_PINVOKE_TCB | RBM_PINVOKE_SCRATCH)
1440
1441   #define REG_FPBASE               REG_R11
1442   #define RBM_FPBASE               RBM_R11
1443   #define STR_FPBASE               "r11"
1444   #define REG_SPBASE               REG_SP
1445   #define RBM_SPBASE               RBM_SP
1446   #define STR_SPBASE               "sp"
1447
1448   #define FIRST_ARG_STACK_OFFS    (2*REGSIZE_BYTES)   // Caller's saved FP and return address
1449
1450   #define MAX_REG_ARG              4
1451   #define MAX_FLOAT_REG_ARG        16
1452   #define MAX_HFA_RET_SLOTS        8
1453
1454   #define REG_ARG_FIRST            REG_R0
1455   #define REG_ARG_LAST             REG_R3
1456   #define REG_ARG_FP_FIRST         REG_F0
1457   #define REG_ARG_FP_LAST          REG_F7
1458   #define INIT_ARG_STACK_SLOT      0                  // No outgoing reserved stack slots
1459
1460   #define REG_ARG_0                REG_R0
1461   #define REG_ARG_1                REG_R1
1462   #define REG_ARG_2                REG_R2
1463   #define REG_ARG_3                REG_R3
1464
1465   SELECTANY const regNumber intArgRegs [] = {REG_R0, REG_R1, REG_R2, REG_R3};
1466   SELECTANY const regMaskTP intArgMasks[] = {RBM_R0, RBM_R1, RBM_R2, RBM_R3};
1467
1468   #define RBM_ARG_0                RBM_R0
1469   #define RBM_ARG_1                RBM_R1
1470   #define RBM_ARG_2                RBM_R2
1471   #define RBM_ARG_3                RBM_R3
1472
1473   #define RBM_ARG_REGS            (RBM_ARG_0|RBM_ARG_1|RBM_ARG_2|RBM_ARG_3)
1474   #define RBM_FLTARG_REGS         (RBM_F0|RBM_F1|RBM_F2|RBM_F3|RBM_F4|RBM_F5|RBM_F6|RBM_F7|RBM_F8|RBM_F9|RBM_F10|RBM_F11|RBM_F12|RBM_F13|RBM_F14|RBM_F15)
1475   #define RBM_DBL_REGS            RBM_ALLDOUBLE
1476
1477   SELECTANY const regNumber fltArgRegs [] = {REG_F0, REG_F1, REG_F2, REG_F3, REG_F4, REG_F5, REG_F6, REG_F7, REG_F8, REG_F9, REG_F10, REG_F11, REG_F12, REG_F13, REG_F14, REG_F15 };
1478   SELECTANY const regMaskTP fltArgMasks[] = {RBM_F0, RBM_F1, RBM_F2, RBM_F3, RBM_F4, RBM_F5, RBM_F6, RBM_F7, RBM_F8, RBM_F9, RBM_F10, RBM_F11, RBM_F12, RBM_F13, RBM_F14, RBM_F15 };
1479
1480   #define LBL_DIST_SMALL_MAX_NEG  (0)
1481   #define LBL_DIST_SMALL_MAX_POS  (+1020)
1482   #define LBL_DIST_MED_MAX_NEG    (-4095)
1483   #define LBL_DIST_MED_MAX_POS    (+4096)
1484
1485   #define JMP_DIST_SMALL_MAX_NEG  (-2048)
1486   #define JMP_DIST_SMALL_MAX_POS  (+2046)
1487
1488   #define CALL_DIST_MAX_NEG (-16777216)
1489   #define CALL_DIST_MAX_POS (+16777214)
1490
1491   #define JCC_DIST_SMALL_MAX_NEG  (-256)
1492   #define JCC_DIST_SMALL_MAX_POS  (+254)
1493
1494   #define JCC_DIST_MEDIUM_MAX_NEG (-1048576)
1495   #define JCC_DIST_MEDIUM_MAX_POS (+1048574)
1496
1497   #define LBL_SIZE_SMALL          (2)
1498
1499   #define JMP_SIZE_SMALL          (2)
1500   #define JMP_SIZE_LARGE          (4)
1501
1502   #define JCC_SIZE_SMALL          (2)
1503   #define JCC_SIZE_MEDIUM         (4)
1504   #define JCC_SIZE_LARGE          (6)
1505
1506 #elif defined(_TARGET_ARM64_)
1507
1508   #define CPU_LOAD_STORE_ARCH      1
1509   #define CPU_LONG_USES_REGPAIR    0
1510   #define CPU_HAS_FP_SUPPORT       1
1511   #define ROUND_FLOAT              0       // Do not round intermed float expression results
1512   #define CPU_HAS_BYTE_REGS        0
1513   #define CPU_USES_BLOCK_MOVE      0
1514
1515   #define CPBLK_UNROLL_LIMIT       64      // Upper bound to let the code generator to loop unroll CpBlk.
1516   #define INITBLK_UNROLL_LIMIT     64      // Upper bound to let the code generator to loop unroll InitBlk.
1517
1518   #define FEATURE_WRITE_BARRIER    1       // Generate the proper WriteBarrier calls for GC    
1519   #define FEATURE_FIXED_OUT_ARGS   1       // Preallocate the outgoing arg area in the prolog
1520   #define FEATURE_STRUCTPROMOTE    1       // JIT Optimization to promote fields of structs into registers
1521   #define FEATURE_MULTIREG_STRUCT_PROMOTE 1  // True when we want to promote fields of a multireg struct into registers
1522   #define FEATURE_FASTTAILCALL     1       // Tail calls made as epilog+jmp
1523   #define FEATURE_TAILCALL_OPT     1       // opportunistic Tail calls (i.e. without ".tail" prefix) made as fast tail calls.
1524   #define FEATURE_SET_FLAGS        1       // Set to true to force the JIT to mark the trees with GTF_SET_FLAGS when the flags need to be set
1525   #define FEATURE_MULTIREG_ARGS_OR_RET  1  // Support for passing and/or returning single values in more than one register  
1526   #define FEATURE_MULTIREG_ARGS         1  // Support for passing a single argument in more than one register  
1527   #define FEATURE_MULTIREG_RET          1  // Support for returning a single value in more than one register  
1528   #define FEATURE_STRUCT_CLASSIFIER     0  // Uses a classifier function to determine is structs are passed/returned in more than one register
1529   #define MAX_PASS_MULTIREG_BYTES      32  // Maximum size of a struct that could be passed in more than one register (max is 4 doubles using an HFA)
1530   #define MAX_RET_MULTIREG_BYTES       32  // Maximum size of a struct that could be returned in more than one register (Max is an HFA of 4 doubles)
1531   #define MAX_ARG_REG_COUNT             4  // Maximum registers used to pass a single argument in multiple registers. (max is 4 floats or doubles using an HFA)
1532   #define MAX_RET_REG_COUNT             4  // Maximum registers used to return a value.
1533
1534 #ifdef FEATURE_USE_ASM_GC_WRITE_BARRIERS
1535   #define NOGC_WRITE_BARRIERS      1       // We have specialized WriteBarrier JIT Helpers that DO-NOT trash the RBM_CALLEE_TRASH registers
1536 #else
1537   #define NOGC_WRITE_BARRIERS      0       // Do not modify this -- modify the definition above.  (If we're not using ASM barriers we definitely don't have NOGC barriers).
1538 #endif
1539   #define USER_ARGS_COME_LAST      1
1540   #define EMIT_TRACK_STACK_DEPTH   1       // This is something of a workaround.  For both ARM and AMD64, the frame size is fixed, so we don't really
1541                                            // need to track stack depth, but this is currently necessary to get GC information reported at call sites.
1542   #define TARGET_POINTER_SIZE      8       // equal to sizeof(void*) and the managed pointer size in bytes for this target
1543   #define FEATURE_EH               1       // To aid platform bring-up, eliminate exceptional EH clauses (catch, filter, filter-handler, fault) and directly execute 'finally' clauses.
1544   #define FEATURE_EH_FUNCLETS      1
1545   #define FEATURE_EH_CALLFINALLY_THUNKS 1  // Generate call-to-finally code in "thunks" in the enclosing EH region, protected by "cloned finally" clauses.
1546   #define FEATURE_STACK_FP_X87     0 
1547   #define ETW_EBP_FRAMED           1       // if 1 we cannot use REG_FP as a scratch register and must setup the frame pointer for most methods
1548   #define FEATURE_FP_REGALLOC      0       // Enabled if RegAlloc is used to enregister Floating Point LclVars  
1549   #define CSE_CONSTS               1       // Enable if we want to CSE constants 
1550
1551   #define REG_FP_FIRST             REG_V0
1552   #define REG_FP_LAST              REG_V31
1553   #define FIRST_FP_ARGREG          REG_V0
1554   #define LAST_FP_ARGREG           REG_V15
1555
1556   #define REGNUM_BITS              6       // number of bits in a REG_*
1557   #define TINY_REGNUM_BITS         5       // number of bits we will use for a tiny instr desc (may not use float)
1558   #define REGMASK_BITS             64      // number of bits in a REGNUM_MASK
1559   #define REGSIZE_BYTES            8       // number of bytes in one general purpose register
1560   #define FP_REGSIZE_BYTES         16      // number of bytes in one FP/SIMD register
1561   #define FPSAVE_REGSIZE_BYTES     8       // number of bytes in one FP/SIMD register that are saved/restored, for callee-saved registers
1562
1563   #define MIN_ARG_AREA_FOR_CALL    0       // Minimum required outgoing argument space for a call.
1564
1565   #define CODE_ALIGN               4       // code alignment requirement
1566   #define STACK_ALIGN              16      // stack alignment requirement
1567   #define STACK_ALIGN_SHIFT        3       // Shift-right amount to convert stack size in bytes to size in DWORD_PTRs
1568
1569   #define RBM_INT_CALLEE_SAVED    (RBM_R19|RBM_R20|RBM_R21|RBM_R22|RBM_R23|RBM_R24|RBM_R25|RBM_R26|RBM_R27|RBM_R28)
1570   #define RBM_INT_CALLEE_TRASH    (RBM_R0|RBM_R1|RBM_R2|RBM_R3|RBM_R4|RBM_R5|RBM_R6|RBM_R7|RBM_R8|RBM_R9|RBM_R10|RBM_R11|RBM_R12|RBM_R13|RBM_R14|RBM_R15|RBM_IP0|RBM_IP1|RBM_LR)
1571   #define RBM_FLT_CALLEE_SAVED    (RBM_V8|RBM_V9|RBM_V10|RBM_V11|RBM_V12|RBM_V13|RBM_V14|RBM_V15)
1572   #define RBM_FLT_CALLEE_TRASH    (RBM_V0|RBM_V1|RBM_V2|RBM_V3|RBM_V4|RBM_V5|RBM_V6|RBM_V7|RBM_V16|RBM_V17|RBM_V18|RBM_V19|RBM_V20|RBM_V21|RBM_V22|RBM_V23|RBM_V24|RBM_V25|RBM_V26|RBM_V27|RBM_V28|RBM_V29|RBM_V30|RBM_V31)
1573
1574   #define RBM_CALLEE_SAVED        (RBM_INT_CALLEE_SAVED | RBM_FLT_CALLEE_SAVED)
1575   #define RBM_CALLEE_TRASH        (RBM_INT_CALLEE_TRASH | RBM_FLT_CALLEE_TRASH)
1576   #define RBM_CALLEE_TRASH_NOGC   (RBM_R12|RBM_R13|RBM_R14|RBM_R15|RBM_IP1)
1577   #define REG_DEFAULT_HELPER_CALL_TARGET REG_R12
1578
1579   #define RBM_ALLINT              (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH)
1580   #define RBM_ALLFLOAT            (RBM_FLT_CALLEE_SAVED | RBM_FLT_CALLEE_TRASH)
1581   #define RBM_ALLDOUBLE            RBM_ALLFLOAT
1582
1583   #define REG_VAR_ORDER            REG_R9,REG_R10,REG_R11,REG_R12,REG_R13,REG_R14,REG_R15,\
1584                                    REG_R8,REG_R7,REG_R6,REG_R5,REG_R4,REG_R3,REG_R2,REG_R1,REG_R0,\
1585                                    REG_R19,REG_R20,REG_R21,REG_R22,REG_R23,REG_R24,REG_R25,REG_R26,REG_R27,REG_R28,\
1586
1587   #define REG_VAR_ORDER_FLT        REG_V16, REG_V17, REG_V18, REG_V19, \
1588                                    REG_V20, REG_V21, REG_V22, REG_V23, \
1589                                    REG_V24, REG_V25, REG_V26, REG_V27, \
1590                                    REG_V28, REG_V29, REG_V30, REG_V31, \
1591                                    REG_V7,  REG_V6,  REG_V5,  REG_V4,  \
1592                                    REG_V8,  REG_V9,  REG_V10, REG_V11, \
1593                                    REG_V12, REG_V13, REG_V14, REG_V16, \
1594                                    REG_V3,  REG_V2, REG_V1,  REG_V0 
1595
1596   #define REG_CALLEE_SAVED_ORDER   REG_R19,REG_R20,REG_R21,REG_R22,REG_R23,REG_R24,REG_R25,REG_R26,REG_R27,REG_R28
1597   #define RBM_CALLEE_SAVED_ORDER   RBM_R19,RBM_R20,RBM_R21,RBM_R22,RBM_R23,RBM_R24,RBM_R25,RBM_R26,RBM_R27,RBM_R28
1598
1599   #define CNT_CALLEE_SAVED        (11)
1600   #define CNT_CALLEE_TRASH        (17)
1601   #define CNT_CALLEE_ENREG        (CNT_CALLEE_SAVED-1)
1602
1603   #define CNT_CALLEE_SAVED_FLOAT  (8)
1604   #define CNT_CALLEE_TRASH_FLOAT  (24)
1605
1606   #define CALLEE_SAVED_REG_MAXSZ    (CNT_CALLEE_SAVED * REGSIZE_BYTES)
1607   #define CALLEE_SAVED_FLOAT_MAXSZ  (CNT_CALLEE_SAVED_FLOAT * FPSAVE_REGSIZE_BYTES)
1608
1609   // TODO-ARM64-Cleanup: Remove this
1610   #define REG_L_STK                REG_ZR
1611
1612   //  This is the first register in REG_TMP_ORDER
1613   #define REG_TMP_0                REG_R9
1614   #define RBM_TMP_0                RBM_R9
1615
1616   //  This is the second register in REG_TMP_ORDER
1617   #define REG_TMP_1                REG_R10
1618   #define RBM_TMP_1                RBM_R10
1619
1620   // register to hold shift amount; no special register is required on ARM64.
1621   #define REG_SHIFT                REG_NA
1622   #define RBM_SHIFT                RBM_ALLINT
1623   #define PREDICT_REG_SHIFT        PREDICT_REG
1624
1625   // This is a general scratch register that does not conflict with the argument registers
1626   #define REG_SCRATCH              REG_R9
1627   #define RBM_SCRATCH              RBM_R9
1628
1629   // This is a general register that can be optionally reserved for other purposes during codegen
1630   #define REG_OPT_RSVD             REG_IP1
1631   #define RBM_OPT_RSVD             RBM_IP1
1632
1633   // Where is the exception object on entry to the handler block?
1634   #define REG_EXCEPTION_OBJECT     REG_R0
1635   #define RBM_EXCEPTION_OBJECT     RBM_R0
1636
1637   #define REG_JUMP_THUNK_PARAM     REG_R12
1638   #define RBM_JUMP_THUNK_PARAM     RBM_R12
1639
1640 #if NOGC_WRITE_BARRIERS
1641   #define REG_WRITE_BARRIER_SRC_BYREF    REG_R13
1642   #define RBM_WRITE_BARRIER_SRC_BYREF    RBM_R13
1643
1644   #define REG_WRITE_BARRIER_DST_BYREF    REG_R14
1645   #define RBM_WRITE_BARRIER_DST_BYREF    RBM_R14
1646
1647   #define REG_WRITE_BARRIER              REG_R15
1648   #define RBM_WRITE_BARRIER              RBM_R15
1649 #endif
1650
1651   // GenericPInvokeCalliHelper VASigCookie Parameter 
1652   #define REG_PINVOKE_COOKIE_PARAM          REG_R15
1653   #define RBM_PINVOKE_COOKIE_PARAM          RBM_R15
1654   #define PREDICT_REG_PINVOKE_COOKIE_PARAM  PREDICT_REG_R15
1655
1656   // GenericPInvokeCalliHelper unmanaged target Parameter 
1657   #define REG_PINVOKE_TARGET_PARAM          REG_R14
1658   #define RBM_PINVOKE_TARGET_PARAM          RBM_R14
1659   #define PREDICT_REG_PINVOKE_TARGET_PARAM  PREDICT_REG_R14
1660
1661   // IL stub's secret MethodDesc parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM)
1662   #define REG_SECRET_STUB_PARAM     REG_R12
1663   #define RBM_SECRET_STUB_PARAM     RBM_R12
1664
1665   // VSD extra parameter (slot address)
1666   #define REG_VIRTUAL_STUB_PARAM          REG_R11
1667   #define RBM_VIRTUAL_STUB_PARAM          RBM_R11
1668   #define PREDICT_REG_VIRTUAL_STUB_PARAM  PREDICT_REG_R11
1669
1670   // R2R indirect call. Use the same registers as VSD
1671   #define REG_R2R_INDIRECT_PARAM          REG_R11
1672   #define RBM_R2R_INDIRECT_PARAM          RBM_R11
1673
1674   // Registers used by PInvoke frame setup
1675   #define REG_PINVOKE_FRAME        REG_R9
1676   #define RBM_PINVOKE_FRAME        RBM_R9
1677   #define REG_PINVOKE_TCB          REG_R10
1678   #define RBM_PINVOKE_TCB          RBM_R10
1679   #define REG_PINVOKE_SCRATCH      REG_R10
1680   #define RBM_PINVOKE_SCRATCH      RBM_R10
1681
1682   // The following defines are useful for iterating a regNumber
1683   #define REG_FIRST                REG_R0
1684   #define REG_INT_FIRST            REG_R0
1685   #define REG_INT_LAST             REG_ZR
1686   #define REG_INT_COUNT            (REG_INT_LAST - REG_INT_FIRST + 1)
1687   #define REG_NEXT(reg)           ((regNumber)((unsigned)(reg) + 1))
1688   #define REG_PREV(reg)           ((regNumber)((unsigned)(reg) - 1))
1689
1690   // genCodeForCall() moves the target address of the tailcall into this register, before pushing it on the stack
1691   #define REG_TAILCALL_ADDR        REG_R9
1692
1693   // The following registers are used in emitting Enter/Leave/Tailcall profiler callbacks
1694   #define REG_PROFILER_ENTER_ARG           REG_R0
1695   #define RBM_PROFILER_ENTER_ARG           RBM_R0
1696   #define REG_PROFILER_RET_SCRATCH         REG_R2
1697   #define RBM_PROFILER_RET_SCRATCH         RBM_R2
1698   #define RBM_PROFILER_RET_USED            (RBM_R0 | RBM_R1 | RBM_R2)
1699   #define REG_PROFILER_JMP_ARG             REG_R0
1700   #define RBM_PROFILER_JMP_USED            RBM_R0
1701   #define RBM_PROFILER_TAIL_USED           (RBM_R0 | RBM_R12 | RBM_LR)
1702   
1703
1704   // Which register are int and long values returned in ?
1705   #define REG_INTRET               REG_R0
1706   #define RBM_INTRET               RBM_R0
1707   #define REG_LNGRET               REG_R0
1708   #define RBM_LNGRET               RBM_R0
1709   // second return register for 16-byte structs
1710   #define REG_INTRET_1             REG_R1 
1711   #define RBM_INTRET_1             RBM_R1
1712
1713   #define REG_FLOATRET             REG_V0
1714   #define RBM_FLOATRET             RBM_V0
1715   #define RBM_DOUBLERET            RBM_V0
1716
1717   // The registers trashed by the CORINFO_HELP_STOP_FOR_GC helper
1718   #define RBM_STOP_FOR_GC_TRASH    RBM_CALLEE_TRASH
1719
1720   // The registers trashed by the CORINFO_HELP_INIT_PINVOKE_FRAME helper.
1721   #define RBM_INIT_PINVOKE_FRAME_TRASH  RBM_CALLEE_TRASH
1722
1723   #define REG_FPBASE               REG_FP
1724   #define RBM_FPBASE               RBM_FP
1725   #define STR_FPBASE               "fp"
1726   #define REG_SPBASE               REG_SP
1727   #define RBM_SPBASE               RBM_ZR     // reuse the RBM for REG_ZR
1728   #define STR_SPBASE               "sp"
1729
1730   #define FIRST_ARG_STACK_OFFS    (2*REGSIZE_BYTES)   // Caller's saved FP and return address
1731
1732   // On ARM64 the calling convention defines REG_R8 (x8) as an additional argument register
1733   // It isn't allocated for the normal user arguments, so it isn't counted by MAX_REG_ARG
1734   // whether we use this register to pass the RetBuff is controlled by the function hasFixedRetBuffReg()
1735   // it is consider to be the next integer argnum, which is 8 
1736   //
1737   #define REG_ARG_RET_BUFF         REG_R8
1738   #define RBM_ARG_RET_BUFF         RBM_R8
1739   #define RET_BUFF_ARGNUM          8
1740
1741   #define MAX_REG_ARG              8
1742   #define MAX_FLOAT_REG_ARG        8
1743
1744   #define REG_ARG_FIRST            REG_R0
1745   #define REG_ARG_LAST             REG_R7
1746   #define REG_ARG_FP_FIRST         REG_V0
1747   #define REG_ARG_FP_LAST          REG_V7
1748   #define INIT_ARG_STACK_SLOT      0                  // No outgoing reserved stack slots
1749
1750   #define REG_ARG_0                REG_R0
1751   #define REG_ARG_1                REG_R1
1752   #define REG_ARG_2                REG_R2
1753   #define REG_ARG_3                REG_R3
1754   #define REG_ARG_4                REG_R4
1755   #define REG_ARG_5                REG_R5
1756   #define REG_ARG_6                REG_R6
1757   #define REG_ARG_7                REG_R7
1758
1759   SELECTANY const regNumber intArgRegs [] = {REG_R0, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, REG_R6, REG_R7};
1760   SELECTANY const regMaskTP intArgMasks[] = {RBM_R0, RBM_R1, RBM_R2, RBM_R3, RBM_R4, RBM_R5, RBM_R6, RBM_R7};
1761
1762   #define RBM_ARG_0                RBM_R0
1763   #define RBM_ARG_1                RBM_R1
1764   #define RBM_ARG_2                RBM_R2
1765   #define RBM_ARG_3                RBM_R3
1766   #define RBM_ARG_4                RBM_R4
1767   #define RBM_ARG_5                RBM_R5
1768   #define RBM_ARG_6                RBM_R6
1769   #define RBM_ARG_7                RBM_R7
1770
1771   #define REG_FLTARG_0             REG_V0
1772   #define REG_FLTARG_1             REG_V1
1773   #define REG_FLTARG_2             REG_V2
1774   #define REG_FLTARG_3             REG_V3
1775   #define REG_FLTARG_4             REG_V4
1776   #define REG_FLTARG_5             REG_V5
1777   #define REG_FLTARG_6             REG_V6
1778   #define REG_FLTARG_7             REG_V7
1779
1780   #define RBM_FLTARG_0             RBM_V0
1781   #define RBM_FLTARG_1             RBM_V1
1782   #define RBM_FLTARG_2             RBM_V2
1783   #define RBM_FLTARG_3             RBM_V3
1784   #define RBM_FLTARG_4             RBM_V4
1785   #define RBM_FLTARG_5             RBM_V5
1786   #define RBM_FLTARG_6             RBM_V6
1787   #define RBM_FLTARG_7             RBM_V7
1788
1789   #define RBM_ARG_REGS            (RBM_ARG_0|RBM_ARG_1|RBM_ARG_2|RBM_ARG_3|RBM_ARG_4|RBM_ARG_5|RBM_ARG_6|RBM_ARG_7)
1790   #define RBM_FLTARG_REGS         (RBM_FLTARG_0|RBM_FLTARG_1|RBM_FLTARG_2|RBM_FLTARG_3|RBM_FLTARG_4|RBM_FLTARG_5|RBM_FLTARG_6|RBM_FLTARG_7)
1791
1792   SELECTANY const regNumber fltArgRegs [] = {REG_V0, REG_V1, REG_V2, REG_V3, REG_V4, REG_V5, REG_V6, REG_V7 };
1793   SELECTANY const regMaskTP fltArgMasks[] = {RBM_V0, RBM_V1, RBM_V2, RBM_V3, RBM_V4, RBM_V5, RBM_V6, RBM_V7 };
1794
1795   #define LBL_DIST_SMALL_MAX_NEG  (-1048576)
1796   #define LBL_DIST_SMALL_MAX_POS  (+1048575)
1797
1798   #define LBL_SIZE_SMALL          (4)
1799   #define LBL_SIZE_LARGE          (8)
1800
1801   #define JCC_DIST_SMALL_MAX_NEG  (-1048576)
1802   #define JCC_DIST_SMALL_MAX_POS  (+1048575)
1803
1804   #define JCC_SIZE_SMALL          (4)
1805   #define JCC_SIZE_LARGE          (8)
1806
1807   #define LDC_DIST_SMALL_MAX_NEG  (-1048576)
1808   #define LDC_DIST_SMALL_MAX_POS  (+1048575)
1809
1810   #define LDC_SIZE_SMALL          (4)
1811   #define LDC_SIZE_LARGE          (8)
1812
1813   #define JMP_SIZE_SMALL          (4)
1814
1815 #else
1816   #error Unsupported or unset target architecture
1817 #endif
1818
1819 #ifdef _TARGET_XARCH_
1820
1821   #define JMP_DIST_SMALL_MAX_NEG  (-128)
1822   #define JMP_DIST_SMALL_MAX_POS  (+127)
1823
1824   #define JCC_DIST_SMALL_MAX_NEG  (-128)
1825   #define JCC_DIST_SMALL_MAX_POS  (+127)
1826
1827   #define JMP_SIZE_SMALL          (2)
1828   #define JMP_SIZE_LARGE          (5)
1829
1830   #define JCC_SIZE_SMALL          (2)
1831   #define JCC_SIZE_LARGE          (6)
1832
1833   #define PUSH_INST_SIZE          (5)
1834   #define CALL_INST_SIZE          (5)
1835
1836 #endif // _TARGET_XARCH_
1837
1838 C_ASSERT(REG_FIRST == 0);
1839 C_ASSERT(REG_INT_FIRST < REG_INT_LAST);
1840 C_ASSERT(REG_FP_FIRST  < REG_FP_LAST);
1841
1842 // Opportunistic tail call feature converts non-tail prefixed calls into 
1843 // tail calls where possible. It requires fast tail calling mechanism for
1844 // performance. Otherwise, we are better off not converting non-tail prefixed
1845 // calls into tail calls.
1846 C_ASSERT((FEATURE_TAILCALL_OPT == 0) || (FEATURE_FASTTAILCALL == 1));
1847
1848 /*****************************************************************************/
1849
1850 #define BITS_PER_BYTE              8 
1851 #define REGNUM_MASK              ((1 << REGNUM_BITS) - 1)     // a n-bit mask use to encode multiple REGNUMs into a unsigned int
1852 #define RBM_ALL(type) (varTypeIsFloating(type) ? RBM_ALLFLOAT : RBM_ALLINT)
1853
1854 /*****************************************************************************/
1855
1856 #if CPU_HAS_BYTE_REGS
1857   #define RBM_BYTE_REGS           (RBM_EAX|RBM_ECX|RBM_EDX|RBM_EBX)
1858   #define RBM_NON_BYTE_REGS       (RBM_ESI|RBM_EDI)
1859   // We reuse the ESP register as a flag for byteable registers in lvPrefReg
1860   #define RBM_BYTE_REG_FLAG        RBM_ESP
1861 #else
1862   #define RBM_BYTE_REGS            RBM_ALLINT
1863   #define RBM_NON_BYTE_REGS        RBM_NONE
1864   #define RBM_BYTE_REG_FLAG        RBM_NONE
1865 #endif
1866 // clang-format on
1867
1868 /*****************************************************************************/
1869 class Target
1870 {
1871 public:
1872     static const char* g_tgtCPUName;
1873     static const char* g_tgtPlatformName;
1874
1875     enum ArgOrder
1876     {
1877         ARG_ORDER_R2L,
1878         ARG_ORDER_L2R
1879     };
1880     static const enum ArgOrder g_tgtArgOrder;
1881
1882 #if NOGC_WRITE_BARRIERS
1883     static regMaskTP exclude_WriteBarrierReg(regMaskTP mask)
1884     {
1885         unsigned result = (mask & ~RBM_WRITE_BARRIER);
1886         if (result)
1887             return result;
1888         else
1889             return RBM_ALLINT & ~RBM_WRITE_BARRIER;
1890     }
1891 #endif // NOGC_WRITE_BARRIERS
1892 };
1893
1894 #if defined(DEBUG) || defined(LATE_DISASM)
1895 const char* getRegName(unsigned reg, bool isFloat = false); // this is for gcencode.cpp and disasm.cpp that don't use
1896                                                             // the regNumber type
1897 const char* getRegName(regNumber reg, bool isFloat = false);
1898 #endif // defined(DEBUG) || defined(LATE_DISASM)
1899
1900 #ifdef DEBUG
1901 const char* getRegNameFloat(regNumber reg, var_types type);
1902 extern void dspRegMask(regMaskTP regMask, size_t minSiz = 0);
1903 #endif
1904
1905 #if CPU_HAS_BYTE_REGS
1906 inline BOOL isByteReg(regNumber reg)
1907 {
1908     return (reg <= REG_EBX);
1909 }
1910 #else
1911 inline BOOL isByteReg(regNumber reg)
1912 {
1913     return true;
1914 }
1915 #endif
1916
1917 #ifdef LEGACY_BACKEND
1918 extern const regNumber raRegTmpOrder[REG_TMP_ORDER_COUNT];
1919 extern const regNumber rpRegTmpOrder[REG_TMP_ORDER_COUNT];
1920 #if FEATURE_FP_REGALLOC
1921 extern const regNumber raRegFltTmpOrder[REG_FLT_TMP_ORDER_COUNT];
1922 #endif
1923 #endif // LEGACY_BACKEND
1924
1925 inline regMaskTP genRegMask(regNumber reg);
1926 inline regMaskTP genRegMaskFloat(regNumber reg, var_types type = TYP_DOUBLE);
1927
1928 /*****************************************************************************
1929  * Return true if the register number is valid
1930  */
1931 inline bool genIsValidReg(regNumber reg)
1932 {
1933     /* It's safest to perform an unsigned comparison in case reg is negative */
1934     return ((unsigned)reg < (unsigned)REG_COUNT);
1935 }
1936
1937 /*****************************************************************************
1938  * Return true if the register is a valid integer register
1939  */
1940 inline bool genIsValidIntReg(regNumber reg)
1941 {
1942     return reg >= REG_INT_FIRST && reg <= REG_INT_LAST;
1943 }
1944
1945 /*****************************************************************************
1946  * Return true if the register is a valid floating point register
1947  */
1948 inline bool genIsValidFloatReg(regNumber reg)
1949 {
1950     return reg >= REG_FP_FIRST && reg <= REG_FP_LAST;
1951 }
1952
1953 #if defined(LEGACY_BACKEND) && defined(_TARGET_ARM_)
1954
1955 /*****************************************************************************
1956  * Return true if the register is a valid floating point double register
1957  */
1958 inline bool genIsValidDoubleReg(regNumber reg)
1959 {
1960     return genIsValidFloatReg(reg) && (((reg - REG_FP_FIRST) & 0x1) == 0);
1961 }
1962
1963 #endif // defined(LEGACY_BACKEND) && defined(_TARGET_ARM_)
1964
1965 //-------------------------------------------------------------------------------------------
1966 // hasFixedRetBuffReg:
1967 //     Returns true if our target architecture uses a fixed return buffer register
1968 //
1969 inline bool hasFixedRetBuffReg()
1970 {
1971 #ifdef _TARGET_ARM64_
1972     return true;
1973 #else
1974     return false;
1975 #endif
1976 }
1977
1978 //-------------------------------------------------------------------------------------------
1979 // theFixedRetBuffReg:
1980 //     Returns the regNumber to use for the fixed return buffer
1981 //
1982 inline regNumber theFixedRetBuffReg()
1983 {
1984     assert(hasFixedRetBuffReg()); // This predicate should be checked before calling this method
1985 #ifdef _TARGET_ARM64_
1986     return REG_ARG_RET_BUFF;
1987 #else
1988     return REG_NA;
1989 #endif
1990 }
1991
1992 //-------------------------------------------------------------------------------------------
1993 // theFixedRetBuffMask:
1994 //     Returns the regNumber to use for the fixed return buffer
1995 //
1996 inline regMaskTP theFixedRetBuffMask()
1997 {
1998     assert(hasFixedRetBuffReg()); // This predicate should be checked before calling this method
1999 #ifdef _TARGET_ARM64_
2000     return RBM_ARG_RET_BUFF;
2001 #else
2002     return 0;
2003 #endif
2004 }
2005
2006 //-------------------------------------------------------------------------------------------
2007 // theFixedRetBuffArgNum:
2008 //     Returns the argNum to use for the fixed return buffer
2009 //
2010 inline unsigned theFixedRetBuffArgNum()
2011 {
2012     assert(hasFixedRetBuffReg()); // This predicate should be checked before calling this method
2013 #ifdef _TARGET_ARM64_
2014     return RET_BUFF_ARGNUM;
2015 #else
2016     return BAD_VAR_NUM;
2017 #endif
2018 }
2019
2020 //-------------------------------------------------------------------------------------------
2021 // fullIntArgRegMask:
2022 //     Returns the full mask of all possible integer registers
2023 //     Note this includes the fixed return buffer register on Arm64
2024 //
2025 inline regMaskTP fullIntArgRegMask()
2026 {
2027     if (hasFixedRetBuffReg())
2028     {
2029         return RBM_ARG_REGS | theFixedRetBuffMask();
2030     }
2031     else
2032     {
2033         return RBM_ARG_REGS;
2034     }
2035 }
2036
2037 //-------------------------------------------------------------------------------------------
2038 // isValidIntArgReg:
2039 //     Returns true if the register is a valid integer argument register
2040 //     Note this method also returns true on Arm64 when 'reg' is the RetBuff register
2041 //
2042 inline bool isValidIntArgReg(regNumber reg)
2043 {
2044     return (genRegMask(reg) & fullIntArgRegMask()) != 0;
2045 }
2046
2047 //-------------------------------------------------------------------------------------------
2048 // genRegArgNext:
2049 //     Given a register that is an integer or floating point argument register
2050 //     returns the next argument register
2051 //
2052 regNumber genRegArgNext(regNumber argReg);
2053
2054 //-------------------------------------------------------------------------------------------
2055 // isValidFloatArgReg:
2056 //     Returns true if the register is a valid floating-point argument register
2057 //
2058 inline bool isValidFloatArgReg(regNumber reg)
2059 {
2060     if (reg == REG_NA)
2061     {
2062         return false;
2063     }
2064     else
2065     {
2066         return (reg >= FIRST_FP_ARGREG) && (reg <= LAST_FP_ARGREG);
2067     }
2068 }
2069
2070 /*****************************************************************************
2071  *
2072  *  Can the register hold the argument type?
2073  */
2074
2075 #ifdef _TARGET_ARM_
2076 inline bool floatRegCanHoldType(regNumber reg, var_types type)
2077 {
2078     assert(genIsValidFloatReg(reg));
2079     if (type == TYP_DOUBLE)
2080     {
2081         return ((reg - REG_F0) % 2) == 0;
2082     }
2083     else
2084     {
2085         // Can be TYP_STRUCT for HFA. It's not clear that's correct; what about
2086         // HFA of double? We wouldn't be asserting the right alignment, and
2087         // callers like genRegMaskFloat() wouldn't be generating the right mask.
2088
2089         assert((type == TYP_FLOAT) || (type == TYP_STRUCT));
2090         return true;
2091     }
2092 }
2093 #else
2094 // AMD64: xmm registers can hold any float type
2095 // x86: FP stack can hold any float type
2096 // ARM64: Floating-point/SIMD registers can hold any type.
2097 inline bool floatRegCanHoldType(regNumber reg, var_types type)
2098 {
2099     return true;
2100 }
2101 #endif
2102
2103 /*****************************************************************************
2104  *
2105  *  Map a register number to a register mask.
2106  */
2107
2108 extern const regMaskSmall regMasks[REG_COUNT];
2109
2110 inline regMaskTP genRegMask(regNumber reg)
2111 {
2112     assert((unsigned)reg < ArrLen(regMasks));
2113 #ifdef _TARGET_AMD64_
2114     // shift is faster than a L1 hit on modern x86
2115     // (L1 latency on sandy bridge is 4 cycles for [base] and 5 for [base + index*c] )
2116     // the reason this is AMD-only is because the x86 BE will try to get reg masks for REG_STK
2117     // and the result needs to be zero.
2118     regMaskTP result = 1 << reg;
2119     assert(result == regMasks[reg]);
2120     return result;
2121 #else
2122     return regMasks[reg];
2123 #endif
2124 }
2125
2126 /*****************************************************************************
2127  *
2128  *  Map a register number to a floating-point register mask.
2129  */
2130
2131 #if defined(_TARGET_X86_) && defined(LEGACY_BACKEND)
2132 extern const regMaskSmall regFPMasks[REG_FPCOUNT];
2133 #endif // defined(_TARGET_X86_) && defined(LEGACY_BACKEND)
2134
2135 inline regMaskTP genRegMaskFloat(regNumber reg, var_types type /* = TYP_DOUBLE */)
2136 {
2137 #if defined(_TARGET_X86_) && defined(LEGACY_BACKEND)
2138     assert(reg >= REG_FPV0 && reg < REG_FPCOUNT);
2139     assert((unsigned)reg < ArrLen(regFPMasks));
2140     return regFPMasks[reg];
2141 #elif defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) || defined(_TARGET_X86_)
2142     assert(genIsValidFloatReg(reg));
2143     assert((unsigned)reg < ArrLen(regMasks));
2144     return regMasks[reg];
2145 #elif defined _TARGET_ARM_
2146     assert(floatRegCanHoldType(reg, type));
2147     assert(reg >= REG_F0 && reg <= REG_F31);
2148
2149     if (type == TYP_DOUBLE)
2150     {
2151         return regMasks[reg] | regMasks[reg + 1];
2152     }
2153     else
2154     {
2155         return regMasks[reg];
2156     }
2157 #else
2158 #error Unsupported or unset target architecture
2159 #endif
2160 }
2161
2162 //------------------------------------------------------------------------
2163 // genRegMask: Given a register, and its type, generate the appropriate regMask
2164 //
2165 // Arguments:
2166 //    regNum   - the register of interest
2167 //    type     - the type of regNum (i.e. the type it is being used as)
2168 //
2169 // Return Value:
2170 //    This will usually return the same value as genRegMask(regNum), but
2171 //    on architectures where multiple registers are used for certain types
2172 //    (e.g. TYP_DOUBLE on ARM), it will return a regMask that includes
2173 //    all the registers.
2174 //    Registers that are used in pairs, but separately named (e.g. TYP_LONG
2175 //    on ARM) will return just the regMask for the given register.
2176 //
2177 // Assumptions:
2178 //    For registers that are used in pairs, the caller will be handling
2179 //    each member of the pair separately.
2180 //
2181 inline regMaskTP genRegMask(regNumber regNum, var_types type)
2182 {
2183 #ifndef _TARGET_ARM_
2184     return genRegMask(regNum);
2185 #else
2186     regMaskTP regMask = RBM_NONE;
2187
2188     if (varTypeIsFloating(type))
2189     {
2190         regMask = genRegMaskFloat(regNum, type);
2191     }
2192     else
2193     {
2194         regMask = genRegMask(regNum);
2195     }
2196     return regMask;
2197 #endif
2198 }
2199
2200 /*****************************************************************************
2201  *
2202  *  These arrays list the callee-saved register numbers (and bitmaps, respectively) for
2203  *  the current architecture.
2204  */
2205 extern const regNumber raRegCalleeSaveOrder[CNT_CALLEE_SAVED];
2206 extern const regMaskTP raRbmCalleeSaveOrder[CNT_CALLEE_SAVED];
2207
2208 // This method takes a "compact" bitset of the callee-saved registers, and "expands" it to a full register mask.
2209 regMaskSmall genRegMaskFromCalleeSavedMask(unsigned short);
2210
2211 /*****************************************************************************
2212  *
2213  *  Returns the register that holds the low  32 bits of the long value given
2214  *  by the register pair 'regPair'.
2215  */
2216 inline regNumber genRegPairLo(regPairNo regPair)
2217 {
2218     assert(regPair >= REG_PAIR_FIRST && regPair <= REG_PAIR_LAST);
2219
2220     return (regNumber)((regPair - REG_PAIR_FIRST) & REG_PAIR_NMASK);
2221 }
2222
2223 /*****************************************************************************
2224  *
2225  *  Returns the register that holds the high 32 bits of the long value given
2226  *  by the register pair 'regPair'.
2227  */
2228 inline regNumber genRegPairHi(regPairNo regPair)
2229 {
2230     assert(regPair >= REG_PAIR_FIRST && regPair <= REG_PAIR_LAST);
2231
2232     return (regNumber)(((regPair - REG_PAIR_FIRST) >> REG_PAIR_NBITS) & REG_PAIR_NMASK);
2233 }
2234
2235 /*****************************************************************************
2236  *
2237  *  Returns whether regPair is a combination of two "real" registers
2238  *  or whether it contains a pseudo register.
2239  *
2240  *  In debug it also asserts that reg1 and reg2 are not the same.
2241  */
2242 bool genIsProperRegPair(regPairNo regPair);
2243
2244 /*****************************************************************************
2245  *
2246  *  Returns the register pair number that corresponds to the given two regs.
2247  */
2248 inline regPairNo gen2regs2pair(regNumber regLo, regNumber regHi)
2249 {
2250     assert(regLo != regHi || regLo == REG_STK);
2251     assert(genIsValidReg(regLo) && genIsValidReg(regHi));
2252     assert(regLo != REG_L_STK && regHi != REG_L_STK);
2253
2254     regPairNo regPair = (regPairNo)(regLo + (regHi << REG_PAIR_NBITS) + REG_PAIR_FIRST);
2255
2256     assert(regLo == genRegPairLo(regPair));
2257     assert(regHi == genRegPairHi(regPair));
2258
2259     return regPair;
2260 }
2261
2262 /*****************************************************************************/
2263 inline regMaskTP genRegPairMask(regPairNo regPair)
2264 {
2265     assert(regPair >= REG_PAIR_FIRST && regPair <= REG_PAIR_LAST);
2266
2267     return genRegMask(genRegPairLo(regPair)) | genRegMask(genRegPairHi(regPair));
2268 }
2269
2270 /*****************************************************************************
2271  *
2272  *  Assumes that "reg" is of the given "type". Return the next unused reg number after "reg"
2273  *  of this type, else REG_NA if there are no more.
2274  */
2275
2276 inline regNumber regNextOfType(regNumber reg, var_types type)
2277 {
2278     regNumber regReturn;
2279
2280 #ifdef _TARGET_ARM_
2281     if (type == TYP_DOUBLE)
2282     {
2283         // Skip odd FP registers for double-precision types
2284         assert(floatRegCanHoldType(reg, type));
2285         regReturn = regNumber(reg + 2);
2286     }
2287     else
2288     {
2289         regReturn = REG_NEXT(reg);
2290     }
2291 #else // _TARGET_ARM_
2292     regReturn = REG_NEXT(reg);
2293 #endif
2294
2295     if (varTypeIsFloating(type))
2296     {
2297         if (regReturn > REG_FP_LAST)
2298         {
2299             regReturn = REG_NA;
2300         }
2301     }
2302     else
2303     {
2304         if (regReturn > REG_INT_LAST)
2305         {
2306             regReturn = REG_NA;
2307         }
2308     }
2309
2310     return regReturn;
2311 }
2312
2313 /*****************************************************************************
2314  *
2315  *  Type checks
2316  */
2317
2318 inline bool isRegPairType(int /* s/b "var_types" */ type)
2319 {
2320 #if !CPU_LONG_USES_REGPAIR
2321     return false;
2322 #else
2323 #ifdef _TARGET_64BIT_
2324     return false;
2325 #elif CPU_HAS_FP_SUPPORT
2326     return type == TYP_LONG;
2327 #else
2328     return type == TYP_LONG || type == TYP_DOUBLE;
2329 #endif
2330 #endif // CPU_LONG_USES_REGPAIR
2331 }
2332
2333 inline bool isFloatRegType(int /* s/b "var_types" */ type)
2334 {
2335 #if CPU_HAS_FP_SUPPORT
2336     return type == TYP_DOUBLE || type == TYP_FLOAT;
2337 #else
2338     return false;
2339 #endif
2340 }
2341
2342 // If the WINDOWS_AMD64_ABI is defined make sure that _TARGET_AMD64_ is also defined.
2343 #if defined(WINDOWS_AMD64_ABI)
2344 #if !defined(_TARGET_AMD64_)
2345 #error When WINDOWS_AMD64_ABI is defined you must define _TARGET_AMD64_ defined as well.
2346 #endif
2347 #endif
2348
2349 /*****************************************************************************/
2350 // Some sanity checks on some of the register masks
2351 // Stack pointer is never part of RBM_ALLINT
2352 C_ASSERT((RBM_ALLINT & RBM_SPBASE) == RBM_NONE);
2353 C_ASSERT((RBM_INT_CALLEE_SAVED & RBM_SPBASE) == RBM_NONE);
2354
2355 #if ETW_EBP_FRAMED
2356 // Frame pointer isn't either if we're supporting ETW frame chaining
2357 C_ASSERT((RBM_ALLINT & RBM_FPBASE) == RBM_NONE);
2358 C_ASSERT((RBM_INT_CALLEE_SAVED & RBM_FPBASE) == RBM_NONE);
2359 #endif
2360 /*****************************************************************************/
2361
2362 /*****************************************************************************/
2363 #endif // _TARGET_H_
2364 /*****************************************************************************/