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