Sync may31 release/8.0-tizen (#510)
[platform/upstream/dotnet/runtime.git] / src / coreclr / jit / targetriscv64.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 #pragma once
4
5 #if !defined(TARGET_RISCV64)
6 #error The file should not be included for this platform.
7 #endif
8
9 // clang-format off
10   #define CPU_LOAD_STORE_ARCH      1
11   #define CPU_HAS_FP_SUPPORT       1
12   #define ROUND_FLOAT              0       // Do not round intermed float expression results
13   #define CPU_HAS_BYTE_REGS        0
14
15
16 #ifdef FEATURE_SIMD
17 #pragma error("SIMD Unimplemented yet RISCV64")
18 #endif // FEATURE_SIMD
19
20   #define FEATURE_FIXED_OUT_ARGS   1       // Preallocate the outgoing arg area in the prolog
21   #define FEATURE_STRUCTPROMOTE    1       // JIT Optimization to promote fields of structs into registers
22   #define FEATURE_MULTIREG_STRUCT_PROMOTE 1  // True when we want to promote fields of a multireg struct into registers
23   #define FEATURE_FASTTAILCALL     1       // Tail calls made as epilog+jmp
24   #define FEATURE_TAILCALL_OPT     1       // opportunistic Tail calls (i.e. without ".tail" prefix) made as fast tail calls.
25   #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
26   #define FEATURE_IMPLICIT_BYREFS       1  // Support for struct parameters passed via pointers to shadow copies
27   #define FEATURE_MULTIREG_ARGS_OR_RET  1  // Support for passing and/or returning single values in more than one register
28   #define FEATURE_MULTIREG_ARGS         1  // Support for passing a single argument in more than one register
29   #define FEATURE_MULTIREG_RET          1  // Support for returning a single value in more than one register
30   #define FEATURE_STRUCT_CLASSIFIER     0  // Uses a classifier function to determine is structs are passed/returned in more than one register
31   #define MAX_PASS_SINGLEREG_BYTES     8  // Maximum size of a struct passed in a single register (8-byte vector).
32   #define MAX_PASS_MULTIREG_BYTES      16  // Maximum size of a struct that could be passed in more than one register
33   #define MAX_RET_MULTIREG_BYTES       16  // Maximum size of a struct that could be returned in more than one register (Max is an HFA or 2 doubles)
34   #define MAX_ARG_REG_COUNT             2  // Maximum registers used to pass a single argument in multiple registers.
35   #define MAX_RET_REG_COUNT             2  // Maximum registers used to return a value.
36   #define MAX_MULTIREG_COUNT            2  // Maximum number of registers defined by a single instruction (including calls).
37                                            // This is also the maximum number of registers for a MultiReg node.
38
39   #define NOGC_WRITE_BARRIERS      1       // We have specialized WriteBarrier JIT Helpers that DO-NOT trash the RBM_CALLEE_TRASH registers
40   #define USER_ARGS_COME_LAST      1
41   #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
42                                            // need to track stack depth, but this is currently necessary to get GC information reported at call sites.
43   #define TARGET_POINTER_SIZE      8       // equal to sizeof(void*) and the managed pointer size in bytes for this target
44   #define FEATURE_EH               1       // To aid platform bring-up, eliminate exceptional EH clauses (catch, filter, filter-handler, fault) and directly execute 'finally' clauses.
45   #define FEATURE_EH_CALLFINALLY_THUNKS 1  // Generate call-to-finally code in "thunks" in the enclosing EH region, protected by "cloned finally" clauses.
46   #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
47   #define CSE_CONSTS               1       // Enable if we want to CSE constants
48
49   #define REG_FP_FIRST             REG_F0
50   #define REG_FP_LAST              REG_F31
51   #define FIRST_FP_ARGREG          REG_F10
52   #define LAST_FP_ARGREG           REG_F17
53
54   #define REGNUM_BITS              6       // number of bits in a REG_*
55   #define REGSIZE_BYTES            8       // number of bytes in one general purpose register
56   #define FP_REGSIZE_BYTES         8      // number of bytes in one FP/SIMD register
57   #define FPSAVE_REGSIZE_BYTES     8       // number of bytes in one FP/SIMD register that are saved/restored, for callee-saved registers
58
59   #define MIN_ARG_AREA_FOR_CALL    0       // Minimum required outgoing argument space for a call.
60
61   #define CODE_ALIGN               4       // code alignment requirement
62   #define STACK_ALIGN              16      // stack alignment requirement
63
64   #define RBM_INT_CALLEE_SAVED    (RBM_S1|RBM_S2|RBM_S3|RBM_S4|RBM_S5|RBM_S6|RBM_S7|RBM_S8|RBM_S9|RBM_S10|RBM_S11)
65   #define RBM_INT_CALLEE_TRASH    (RBM_A0|RBM_A1|RBM_A2|RBM_A3|RBM_A4|RBM_A5|RBM_A6|RBM_A7|RBM_T0|RBM_T1|RBM_T2|RBM_T3|RBM_T4|RBM_T5|RBM_T6)
66   #define RBM_FLT_CALLEE_SAVED    (RBM_F8|RBM_F9|RBM_F18|RBM_F19|RBM_F20|RBM_F21|RBM_F22|RBM_F23|RBM_F24|RBM_F25|RBM_F26|RBM_F27)
67   #define RBM_FLT_CALLEE_TRASH    (RBM_F10|RBM_F11|RBM_F12|RBM_F13|RBM_F14|RBM_F15|RBM_F16|RBM_F17)
68
69   #define RBM_CALLEE_SAVED        (RBM_INT_CALLEE_SAVED | RBM_FLT_CALLEE_SAVED)
70   #define RBM_CALLEE_TRASH        (RBM_INT_CALLEE_TRASH | RBM_FLT_CALLEE_TRASH)
71
72   #define REG_DEFAULT_HELPER_CALL_TARGET REG_T2
73   #define RBM_DEFAULT_HELPER_CALL_TARGET RBM_T2
74
75   #define RBM_ALLINT              (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH)
76   #define RBM_ALLFLOAT            (RBM_FLT_CALLEE_SAVED | RBM_FLT_CALLEE_TRASH)
77   #define RBM_ALLDOUBLE            RBM_ALLFLOAT
78
79   // REG_VAR_ORDER is: (CALLEE_TRASH & ~CALLEE_TRASH_NOGC), CALLEE_TRASH_NOGC, CALLEE_SAVED
80   #define REG_VAR_ORDER            REG_A0,REG_A1,REG_A2,REG_A3,REG_A4,REG_A5,REG_A6,REG_A7, \
81                                    REG_T0,REG_T1,REG_T2,REG_T3,REG_T4,REG_T5,REG_T6, \
82                                    REG_CALLEE_SAVED_ORDER
83
84   #define REG_VAR_ORDER_FLT        REG_F12,REG_F13,REG_F14,REG_F15,REG_F16,REG_F17,REG_F18,REG_F19, \
85                                    REG_F2,REG_F3,REG_F4,REG_F5,REG_F6,REG_F7,REG_F8,REG_F9,REG_F10, \
86                                    REG_F20,REG_F21,REG_F22,REG_F23, \
87                                    REG_F24,REG_F25,REG_F26,REG_F27,REG_F28,REG_F29,REG_F30,REG_F31, \
88                                    REG_F1,REG_F0
89
90   #define REG_CALLEE_SAVED_ORDER   REG_S1,REG_S2,REG_S3,REG_S4,REG_S5,REG_S6,REG_S7,REG_S8,REG_S9,REG_S10,REG_S11
91   #define RBM_CALLEE_SAVED_ORDER   RBM_S1,RBM_S2,RBM_S3,RBM_S4,RBM_S5,RBM_S6,RBM_S7,RBM_S8,RBM_S9,RBM_S10,RBM_S11
92
93   #define CNT_CALLEE_SAVED        (11)
94   #define CNT_CALLEE_TRASH        (15)
95   #define CNT_CALLEE_ENREG        (CNT_CALLEE_SAVED-1)
96
97   #define CNT_CALLEE_SAVED_FLOAT  (12)
98   #define CNT_CALLEE_TRASH_FLOAT  (20)
99
100   #define CALLEE_SAVED_REG_MAXSZ    (CNT_CALLEE_SAVED * REGSIZE_BYTES)
101   #define CALLEE_SAVED_FLOAT_MAXSZ  (CNT_CALLEE_SAVED_FLOAT * FPSAVE_REGSIZE_BYTES)
102
103   #define REG_TMP_0                REG_T0
104
105   // Temporary registers used for the GS cookie check.
106   #define REG_GSCOOKIE_TMP_0       REG_T0
107   #define REG_GSCOOKIE_TMP_1       REG_T1
108
109   // register to hold shift amount; no special register is required on ARM64.
110   #define REG_SHIFT                REG_NA
111   #define RBM_SHIFT                RBM_ALLINT
112
113   // This is a general scratch register that does not conflict with the argument registers
114   #define REG_SCRATCH              REG_T0
115
116   // This is a float scratch register that does not conflict with the argument registers
117   #define REG_SCRATCH_FLT          REG_F28
118
119   // This is a general register that can be optionally reserved for other purposes during codegen
120   #define REG_OPT_RSVD             REG_T6
121   #define RBM_OPT_RSVD             RBM_T6
122
123   // Where is the exception object on entry to the handler block?
124   #define REG_EXCEPTION_OBJECT     REG_A0
125   #define RBM_EXCEPTION_OBJECT     RBM_A0
126
127   #define REG_JUMP_THUNK_PARAM     REG_T2
128   #define RBM_JUMP_THUNK_PARAM     RBM_T2
129
130   #define REG_WRITE_BARRIER_DST          REG_T3
131   #define RBM_WRITE_BARRIER_DST          RBM_T3
132
133   #define REG_WRITE_BARRIER_SRC          REG_T4
134   #define RBM_WRITE_BARRIER_SRC          RBM_T4
135
136   #define REG_WRITE_BARRIER_DST_BYREF    REG_T3
137   #define RBM_WRITE_BARRIER_DST_BYREF    RBM_T3
138
139   #define REG_WRITE_BARRIER_SRC_BYREF    REG_T5
140   #define RBM_WRITE_BARRIER_SRC_BYREF    RBM_T5
141
142   #define RBM_CALLEE_TRASH_NOGC          (RBM_T0|RBM_T1|RBM_T2|RBM_T3|RBM_T4|RBM_T5|RBM_T6|RBM_DEFAULT_HELPER_CALL_TARGET)
143
144   // Registers killed by CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF.
145   #define RBM_CALLEE_TRASH_WRITEBARRIER         (RBM_WRITE_BARRIER_DST|RBM_CALLEE_TRASH_NOGC)
146
147   // Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF.
148   #define RBM_CALLEE_GCTRASH_WRITEBARRIER       RBM_CALLEE_TRASH_NOGC
149
150   // Registers killed by CORINFO_HELP_ASSIGN_BYREF.
151   #define RBM_CALLEE_TRASH_WRITEBARRIER_BYREF   (RBM_WRITE_BARRIER_DST_BYREF | RBM_WRITE_BARRIER_SRC_BYREF | RBM_CALLEE_TRASH_NOGC)
152
153   // Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_BYREF.
154   // Note that x13 and x14 are still valid byref pointers after this helper call, despite their value being changed.
155   #define RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF RBM_CALLEE_TRASH_NOGC
156
157   // GenericPInvokeCalliHelper VASigCookie Parameter
158   #define REG_PINVOKE_COOKIE_PARAM          REG_T3
159   #define RBM_PINVOKE_COOKIE_PARAM          RBM_T3
160
161   // GenericPInvokeCalliHelper unmanaged target Parameter
162   #define REG_PINVOKE_TARGET_PARAM          REG_T2
163   #define RBM_PINVOKE_TARGET_PARAM          RBM_T2
164
165   // IL stub's secret MethodDesc parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM)
166   #define REG_SECRET_STUB_PARAM     REG_T2
167   #define RBM_SECRET_STUB_PARAM     RBM_T2
168
169   // R2R indirect call. Use the same registers as VSD
170   #define REG_R2R_INDIRECT_PARAM          REG_T5
171   #define RBM_R2R_INDIRECT_PARAM          RBM_T5
172
173   // JMP Indirect call register
174   #define REG_INDIRECT_CALL_TARGET_REG    REG_T5
175
176   // Registers used by PInvoke frame setup
177   #define REG_PINVOKE_FRAME        REG_T0
178   #define RBM_PINVOKE_FRAME        RBM_T0
179   #define REG_PINVOKE_TCB          REG_T1
180   #define RBM_PINVOKE_TCB          RBM_T1
181   #define REG_PINVOKE_SCRATCH      REG_T1
182   #define RBM_PINVOKE_SCRATCH      RBM_T1
183
184   // The following defines are useful for iterating a regNumber
185   #define REG_FIRST                REG_R0
186   #define REG_INT_FIRST            REG_R0
187   #define REG_INT_LAST             REG_T6
188   #define REG_INT_COUNT            (REG_INT_LAST - REG_INT_FIRST + 1)
189   #define REG_NEXT(reg)           ((regNumber)((unsigned)(reg) + 1))
190   #define REG_PREV(reg)           ((regNumber)((unsigned)(reg) - 1))
191
192   // The following registers are used in emitting Enter/Leave/Tailcall profiler callbacks
193   #define REG_PROFILER_ENTER_ARG_FUNC_ID    REG_T0
194   #define RBM_PROFILER_ENTER_ARG_FUNC_ID    RBM_T0
195   #define REG_PROFILER_ENTER_ARG_CALLER_SP  REG_T1
196   #define RBM_PROFILER_ENTER_ARG_CALLER_SP  RBM_T1
197   #define REG_PROFILER_LEAVE_ARG_FUNC_ID    REG_PROFILER_ENTER_ARG_FUNC_ID
198   #define RBM_PROFILER_LEAVE_ARG_FUNC_ID    RBM_PROFILER_ENTER_ARG_FUNC_ID
199   #define REG_PROFILER_LEAVE_ARG_CALLER_SP  REG_PROFILER_ENTER_ARG_CALLER_SP
200   #define RBM_PROFILER_LEAVE_ARG_CALLER_SP  RBM_PROFILER_ENTER_ARG_CALLER_SP
201
202   // The registers trashed by profiler enter/leave/tailcall hook
203   #define RBM_PROFILER_ENTER_TRASH     (RBM_CALLEE_TRASH & ~(RBM_ARG_REGS|RBM_FLTARG_REGS|RBM_FP))
204   #define RBM_PROFILER_LEAVE_TRASH     RBM_PROFILER_ENTER_TRASH
205   #define RBM_PROFILER_TAILCALL_TRASH  RBM_PROFILER_LEAVE_TRASH
206
207   // Which register are int and long values returned in ?
208   #define REG_INTRET               REG_A0
209   #define RBM_INTRET               RBM_A0
210   #define REG_LNGRET               REG_A0
211   #define RBM_LNGRET               RBM_A0
212   // second return register for 16-byte structs
213   #define REG_INTRET_1             REG_A1
214   #define RBM_INTRET_1             RBM_A1
215
216   #define REG_FLOATRET             REG_F10
217   #define RBM_FLOATRET             RBM_F10
218   #define RBM_DOUBLERET            RBM_F10
219   #define REG_FLOATRET_1           REG_F11
220   #define RBM_FLOATRET_1           RBM_F11
221   #define RBM_DOUBLERET_1          RBM_F11
222
223   // The registers trashed by the CORINFO_HELP_STOP_FOR_GC helper
224   #define RBM_STOP_FOR_GC_TRASH    RBM_CALLEE_TRASH
225
226   // The registers trashed by the CORINFO_HELP_INIT_PINVOKE_FRAME helper.
227   #define RBM_INIT_PINVOKE_FRAME_TRASH  RBM_CALLEE_TRASH
228
229   #define RBM_VALIDATE_INDIRECT_CALL_TRASH (RBM_INT_CALLEE_TRASH & ~(RBM_A0 | RBM_A1 | RBM_A2 | RBM_A3 | RBM_A4 | RBM_A5 | RBM_A6 | RBM_A7 | RBM_T3))
230   #define REG_VALIDATE_INDIRECT_CALL_ADDR REG_T3
231   #define REG_DISPATCH_INDIRECT_CALL_ADDR REG_T0
232
233   #define REG_FPBASE               REG_FP
234   #define RBM_FPBASE               RBM_FP
235   #define STR_FPBASE               "fp"
236   #define REG_SPBASE               REG_SP
237   #define RBM_SPBASE               RBM_SP     // reuse the RBM for REG_ZR
238   #define STR_SPBASE               "sp"
239
240   #define FIRST_ARG_STACK_OFFS    (2*REGSIZE_BYTES)   // Caller's saved FP and return address
241
242   #define MAX_REG_ARG              8
243   #define MAX_FLOAT_REG_ARG        8
244
245   #define REG_ARG_FIRST            REG_A0
246   #define REG_ARG_LAST             REG_A7
247   #define REG_ARG_FP_FIRST         REG_F10
248   #define REG_ARG_FP_LAST          REG_F17
249   #define INIT_ARG_STACK_SLOT      0                  // No outgoing reserved stack slots
250
251   #define REG_ARG_0                REG_A0
252   #define REG_ARG_1                REG_A1
253   #define REG_ARG_2                REG_A2
254   #define REG_ARG_3                REG_A3
255   #define REG_ARG_4                REG_A4
256   #define REG_ARG_5                REG_A5
257   #define REG_ARG_6                REG_A6
258   #define REG_ARG_7                REG_A7
259
260   extern const regNumber intArgRegs [MAX_REG_ARG];
261   extern const regMaskTP intArgMasks[MAX_REG_ARG];
262
263   #define RBM_ARG_0                RBM_A0
264   #define RBM_ARG_1                RBM_A1
265   #define RBM_ARG_2                RBM_A2
266   #define RBM_ARG_3                RBM_A3
267   #define RBM_ARG_4                RBM_A4
268   #define RBM_ARG_5                RBM_A5
269   #define RBM_ARG_6                RBM_A6
270   #define RBM_ARG_7                RBM_A7
271
272   #define REG_FLTARG_0             REG_F10
273   #define REG_FLTARG_1             REG_F11
274   #define REG_FLTARG_2             REG_F12
275   #define REG_FLTARG_3             REG_F13
276   #define REG_FLTARG_4             REG_F14
277   #define REG_FLTARG_5             REG_F15
278   #define REG_FLTARG_6             REG_F16
279   #define REG_FLTARG_7             REG_F17
280
281   #define RBM_FLTARG_0             RBM_F10
282   #define RBM_FLTARG_1             RBM_F11
283   #define RBM_FLTARG_2             RBM_F12
284   #define RBM_FLTARG_3             RBM_F13
285   #define RBM_FLTARG_4             RBM_F14
286   #define RBM_FLTARG_5             RBM_F15
287   #define RBM_FLTARG_6             RBM_F16
288   #define RBM_FLTARG_7             RBM_F17
289
290   #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)
291   #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)
292
293   extern const regNumber fltArgRegs [MAX_FLOAT_REG_ARG];
294   extern const regMaskTP fltArgMasks[MAX_FLOAT_REG_ARG];
295
296   #define B_DIST_SMALL_MAX_NEG  (-4096)
297   #define B_DIST_SMALL_MAX_POS  (+4095)
298
299   // The number of bytes from the end the last probed page that must also be probed, to allow for some
300   // small SP adjustments without probes. If zero, then the stack pointer can point to the last byte/word
301   // on the stack guard page, and must be touched before any further "SUB SP".
302   #define STACK_PROBE_BOUNDARY_THRESHOLD_BYTES 0
303
304 // clang-format on