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