[runtime] Transition the trampoline code to use memory managers for memory allocation...
[mono-project.git] / mono / mini / mini-arm64.h
blob4074aa8b43f2c8ab6a7b4616d655e098c32d7562
1 /**
2 * \file
4 * Copyright 2013 Xamarin Inc
6 * Based on mini-arm.h:
8 * Copyright 2011 Xamarin Inc
9 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12 #ifndef __MONO_MINI_ARM64_H__
13 #define __MONO_MINI_ARM64_H__
15 #include <mono/arch/arm64/arm64-codegen.h>
16 #include <mono/mini/mini-arm64-gsharedvt.h>
18 #define MONO_ARCH_CPU_SPEC mono_arm64_cpu_desc
20 #define MONO_MAX_IREGS 32
21 #define MONO_MAX_FREGS 32
22 #define MONO_MAX_XREGS 32
24 #if !defined(DISABLE_SIMD) && defined(ENABLE_NETCORE)
25 #define MONO_ARCH_SIMD_INTRINSICS 1
26 #endif
28 #define MONO_CONTEXT_SET_LLVM_EXC_REG(ctx, exc) do { (ctx)->regs [0] = (gsize)exc; } while (0)
30 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx,func) do { \
31 MONO_CONTEXT_SET_BP ((ctx), __builtin_frame_address (0)); \
32 MONO_CONTEXT_SET_SP ((ctx), __builtin_frame_address (0)); \
33 MONO_CONTEXT_SET_IP ((ctx), (func)); \
34 } while (0)
36 #define MONO_ARCH_INIT_TOP_LMF_ENTRY(lmf)
38 /* Parameters used by the register allocator */
39 /* r0..r7, r9..r14 (r15 is the imt/rgctx reg) */
40 #define MONO_ARCH_CALLEE_REGS 0xfeff
41 /* r19..r28 */
42 #define MONO_ARCH_CALLEE_SAVED_REGS (0x3ff << 19)
44 /* v16/v17 is reserved for a scratch reg */
45 #define MONO_ARCH_CALLEE_FREGS 0xfffc00ff
46 /* v8..v15 */
47 #define MONO_ARCH_CALLEE_SAVED_FREGS 0xff00
49 #define MONO_ARCH_CALLEE_SAVED_XREGS 0
51 #define MONO_ARCH_CALLEE_XREGS MONO_ARCH_CALLEE_FREGS
53 #define MONO_ARCH_USE_FPSTACK FALSE
55 #define MONO_ARCH_INST_SREG2_MASK(ins) (0)
57 #define MONO_ARCH_INST_FIXED_REG(desc) ((desc) == 'a' ? ARMREG_R0 : -1)
59 #define MONO_ARCH_INST_IS_REGPAIR(desc) (0)
61 #define MONO_ARCH_INST_IS_FLOAT(desc) ((desc) == 'f')
63 #define MONO_ARCH_INST_REGPAIR_REG2(desc,hreg1) (-1)
65 #define MONO_ARCH_USE_FPSTACK FALSE
67 #define MONO_ARCH_FRAME_ALIGNMENT 16
69 #define MONO_ARCH_CODE_ALIGNMENT 32
71 /* callee saved regs + fp + sp */
72 #define MONO_ARCH_LMF_REGS ((0x3ff << 19) | (1 << ARMREG_FP) | (1 << ARMREG_SP))
73 #define MONO_ARCH_NUM_LMF_REGS (10 + 2)
74 #define MONO_ARCH_FIRST_LMF_REG ARMREG_R19
75 #define MONO_ARCH_LMF_REG_FP 10
76 #define MONO_ARCH_LMF_REG_SP 11
78 struct MonoLMF {
79 /*
80 * If the second lowest bit is set to 1, then this is a MonoLMFExt structure, and
81 * the other fields are not valid.
83 gpointer previous_lmf;
84 gpointer lmf_addr;
85 host_mgreg_t pc;
86 host_mgreg_t gregs [MONO_ARCH_NUM_LMF_REGS];
89 /* Structure used by the sequence points in AOTed code */
90 struct SeqPointInfo {
91 gpointer ss_tramp_addr;
92 guint8* bp_addrs [MONO_ZERO_LEN_ARRAY];
95 #define PARAM_REGS 8
96 #define FP_PARAM_REGS 8
98 typedef struct {
99 host_mgreg_t res, res2;
100 guint8 *ret;
101 double fpregs [FP_PARAM_REGS];
102 int n_fpargs, n_fpret, n_stackargs;
103 /* This should come last as the structure is dynamically extended */
104 /* The +1 is for r8 */
105 host_mgreg_t regs [PARAM_REGS + 1];
106 } DynCallArgs;
108 typedef struct {
109 CallInfo *cinfo;
110 int saved_gregs_offset;
111 /* Points to arguments received on the stack */
112 int args_reg;
113 gboolean cond_branch_islands;
114 MonoInst *vret_addr_loc;
115 MonoInst *seq_point_info_var;
116 MonoInst *ss_tramp_var;
117 MonoInst *bp_tramp_var;
118 guint8 *thunks;
119 int thunks_size;
120 } MonoCompileArch;
122 #define MONO_ARCH_EMULATE_FCONV_TO_U4 1
123 #define MONO_ARCH_EMULATE_FCONV_TO_U8 1
124 #ifdef MONO_ARCH_ILP32
125 /* For the watch (starting with series 4), a new ABI is introduced: arm64_32.
126 * We can still use the older AOT compiler to produce bitcode, because it's
127 * "offset compatible". However, since it is targeting arm7k, it makes certain
128 * assumptions that we need to align here. */
129 #define MONO_ARCH_EMULATE_FCONV_TO_I8 1
130 #define MONO_ARCH_EMULATE_LCONV_TO_R8 1
131 #define MONO_ARCH_EMULATE_LCONV_TO_R4 1
132 #define MONO_ARCH_EMULATE_LCONV_TO_R8_UN 1
133 #define MONO_ARCH_EMULATE_DIV 1
134 #define MONO_ARCH_EMULATE_CONV_R8_UN 1
135 #else
136 #define MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS 1
137 #define MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS 1
138 #endif
140 #define MONO_ARCH_EMULATE_FREM 1
141 #define MONO_ARCH_EMULATE_LONG_MUL_OVF_OPTS 1
142 #define MONO_ARCH_NEED_DIV_CHECK 1
143 #define MONO_ARCH_EMULATE_MUL_OVF 1
144 #define MONO_ARCH_HAVE_OP_TAILCALL_MEMBASE 1
145 #define MONO_ARCH_HAVE_OP_TAILCALL_REG 1
146 #define MONO_ARCH_RGCTX_REG ARMREG_R15
147 #define MONO_ARCH_IMT_REG MONO_ARCH_RGCTX_REG
148 #define MONO_ARCH_VTABLE_REG ARMREG_R0
149 #define MONO_ARCH_HAVE_GENERALIZED_IMT_TRAMPOLINE 1
150 #define MONO_ARCH_USE_SIGACTION 1
151 #ifdef HOST_TVOS
152 #define MONO_ARCH_HAS_NO_PROPER_MONOCTX 1
153 #endif
154 #define MONO_ARCH_HAVE_CONTEXT_SET_INT_REG 1
155 #define MONO_ARCH_GSHARED_SUPPORTED 1
156 #define MONO_ARCH_INTERPRETER_SUPPORTED 1
157 #define MONO_ARCH_HAVE_INTERP_ENTRY_TRAMPOLINE 1
158 #define MONO_ARCH_HAVE_INTERP_NATIVE_TO_MANAGED 1
159 #define MONO_ARCH_AOT_SUPPORTED 1
160 #define MONO_ARCH_LLVM_SUPPORTED 1
161 #define MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES 1
162 #define MONO_ARCH_HAVE_EXCEPTIONS_INIT 1
163 #define MONO_ARCH_HAVE_GET_TRAMPOLINES 1
164 #define MONO_ARCH_DYN_CALL_SUPPORTED 1
165 #define MONO_ARCH_DYN_CALL_PARAM_AREA 0
166 #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
167 #define MONO_ARCH_GSHAREDVT_SUPPORTED 1
168 #define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1
169 #define MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK 1
170 #define MONO_ARCH_HAVE_GENERAL_RGCTX_LAZY_FETCH_TRAMPOLINE 1
171 #define MONO_ARCH_HAVE_OBJC_GET_SELECTOR 1
172 #define MONO_ARCH_HAVE_SDB_TRAMPOLINES 1
173 #define MONO_ARCH_HAVE_PATCH_CODE_NEW 1
174 #define MONO_ARCH_HAVE_OP_GENERIC_CLASS_INIT 1
175 #define MONO_ARCH_HAVE_OPCODE_NEEDS_EMULATION 1
176 #define MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS 1
177 #define MONO_ARCH_FLOAT32_SUPPORTED 1
178 #define MONO_ARCH_HAVE_INTERP_PINVOKE_TRAMP 1
179 #define MONO_ARCH_LLVM_TARGET_LAYOUT "e-i64:64-i128:128-n32:64-S128"
180 #ifdef TARGET_OSX
181 #define MONO_ARCH_FORCE_FLOAT32 1
182 #endif
184 // Does the ABI have a volatile non-parameter register, so tailcall
185 // can pass context to generics or interfaces?
186 #define MONO_ARCH_HAVE_VOLATILE_NON_PARAM_REGISTER 1
188 #ifdef TARGET_IOS
190 #define MONO_ARCH_REDZONE_SIZE 128
192 #else
194 #define MONO_ARCH_REDZONE_SIZE 0
196 #endif
198 #if defined(TARGET_IOS) || defined(TARGET_WATCHOS)
199 #define MONO_ARCH_HAVE_UNWIND_BACKTRACE 1
200 #endif
202 /* Relocations */
203 #define MONO_R_ARM64_B 1
204 #define MONO_R_ARM64_BCC 2
205 #define MONO_R_ARM64_IMM 3
206 #define MONO_R_ARM64_BL 4
207 #define MONO_R_ARM64_BL_SHORT 5
208 #define MONO_R_ARM64_CBZ 6
211 typedef enum {
212 ArgInIReg,
213 ArgInFReg,
214 ArgInFRegR4,
215 ArgOnStack,
216 ArgOnStackR8,
217 ArgOnStackR4,
219 * Vtype passed in consecutive int registers.
220 * ainfo->reg is the firs register,
221 * ainfo->nregs is the number of registers,
222 * ainfo->size is the size of the structure.
224 ArgVtypeInIRegs,
225 ArgVtypeByRef,
226 ArgVtypeByRefOnStack,
227 ArgVtypeOnStack,
228 ArgHFA,
229 ArgNone
230 } ArgStorage;
232 typedef struct {
233 ArgStorage storage;
234 int reg;
235 /* ArgOnStack */
236 int offset;
237 /* ArgVtypeInIRegs/ArgHFA */
238 int nregs, size;
239 /* ArgHFA */
240 int esize;
241 /* ArgHFA */
242 /* The offsets of the float values inside the arg */
243 guint16 foffsets [4];
244 /* ArgOnStack */
245 int slot_size;
246 /* hfa */
247 int nfregs_to_skip;
248 gboolean sign;
249 gboolean gsharedvt;
250 gboolean hfa;
251 } ArgInfo;
253 struct CallInfo {
254 int nargs;
255 int gr, fr, stack_usage;
256 gboolean pinvoke, vararg;
257 ArgInfo ret;
258 ArgInfo sig_cookie;
259 ArgInfo args [1];
262 typedef struct {
263 /* General registers + ARMREG_R8 for indirect returns */
264 host_mgreg_t gregs [PARAM_REGS + 1];
265 /* Floating registers */
266 double fregs [FP_PARAM_REGS];
267 /* Stack usage, used for passing params on stack */
268 guint32 stack_size;
269 guint8* stack;
270 } CallContext;
272 guint8* mono_arm_emit_imm64 (guint8 *code, int dreg, gint64 imm);
274 guint8* mono_arm_emit_ldrx (guint8 *code, int rt, int rn, int imm);
276 guint8* mono_arm_emit_destroy_frame (guint8 *code, int stack_offset, guint64 temp_regs);
278 guint8* mono_arm_emit_store_regset (guint8 *code, guint64 regs, int basereg, int offset);
280 guint8* mono_arm_emit_store_regarray (guint8 *code, guint64 regs, int basereg, int offset);
282 guint8* mono_arm_emit_load_regarray (guint8 *code, guint64 regs, int basereg, int offset);
284 /* MonoJumpInfo **ji */
285 guint8* mono_arm_emit_aotconst (gpointer ji, guint8 *code, guint8 *code_start, int dreg, guint32 patch_type, gconstpointer data);
287 void mono_arm_patch (guint8 *code, guint8 *target, int relocation);
289 void mono_arm_throw_exception (gpointer arg, host_mgreg_t pc, host_mgreg_t *int_regs, gdouble *fp_regs, gboolean corlib, gboolean rethrow, gboolean preserve_ips);
291 void mono_arm_gsharedvt_init (void);
293 GSList* mono_arm_get_exception_trampolines (gboolean aot);
295 void mono_arm_resume_unwind (gpointer arg, host_mgreg_t pc, host_mgreg_t *int_regs, gdouble *fp_regs, gboolean corlib, gboolean rethrow);
297 CallInfo* mono_arch_get_call_info (MonoMemPool *mp, MonoMethodSignature *sig);
299 #endif /* __MONO_MINI_ARM64_H__ */