1 #ifndef __MONO_MINI_AMD64_H__
2 #define __MONO_MINI_AMD64_H__
4 #include <mono/arch/amd64/amd64-codegen.h>
9 /* use SIG* defines if possible */
14 /* sigcontext surrogate */
27 typedef void (* MonoW32ExceptionHandler) (int);
28 void win32_seh_init(void);
29 void win32_seh_cleanup(void);
30 void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler);
44 LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep);
46 #endif /* PLATFORM_WIN32 */
48 #ifdef sun // Solaris x86
49 # undef SIGSEGV_ON_ALTSTACK
50 # define MONO_ARCH_NOMAP32BIT
53 unsigned short gs, __gsh;
54 unsigned short fs, __fsh;
55 unsigned short es, __esh;
56 unsigned short ds, __dsh;
68 unsigned short cs, __csh;
70 unsigned long esp_at_signal;
71 unsigned short ss, __ssh;
72 unsigned long fpstate[95];
73 unsigned long filler[5];
75 #endif // sun, Solaris x86
77 #define MONO_ARCH_SIGNAL_STACK_SIZE (16 * 1024)
79 #define MONO_ARCH_HAVE_RESTORE_STACK_SUPPORT 1
81 #define MONO_ARCH_CPU_SPEC amd64_desc
83 #define MONO_MAX_IREGS 16
85 #define MONO_MAX_FREGS AMD64_XMM_NREG
87 #define MONO_ARCH_FP_RETURN_REG AMD64_XMM0
89 /* xmm15 is reserved for use by some opcodes */
90 #define MONO_ARCH_CALLEE_FREGS 0xef
91 #define MONO_ARCH_CALLEE_SAVED_FREGS 0
93 #define MONO_ARCH_CALLEE_REGS AMD64_CALLEE_REGS
94 #define MONO_ARCH_CALLEE_SAVED_REGS AMD64_CALLEE_SAVED_REGS
96 #define MONO_ARCH_USE_FPSTACK FALSE
97 #define MONO_ARCH_FPSTACK_SIZE 0
99 #define MONO_ARCH_INST_FIXED_REG(desc) ((desc == '\0') ? -1 : ((desc == 'i' ? -1 : ((desc == 'a') ? AMD64_RAX : ((desc == 's') ? AMD64_RCX : ((desc == 'd') ? AMD64_RDX : -1))))))
101 /* RDX is clobbered by the opcode implementation before accessing sreg2 */
102 #define MONO_ARCH_INST_SREG2_MASK(ins) (((ins [MONO_INST_CLOB] == 'a') || (ins [MONO_INST_CLOB] == 'd')) ? (1 << AMD64_RDX) : 0)
104 #define MONO_ARCH_INST_IS_REGPAIR(desc) FALSE
105 #define MONO_ARCH_INST_REGPAIR_REG2(desc,hreg1) (-1)
107 #define MONO_ARCH_FRAME_ALIGNMENT 16
109 /* fixme: align to 16byte instead of 32byte (we align to 32byte to get
110 * reproduceable results for benchmarks */
111 #define MONO_ARCH_CODE_ALIGNMENT 32
113 #define MONO_ARCH_RETREG1 X86_EAX
114 #define MONO_ARCH_RETREG2 X86_EDX
118 * If the lowest bit is set to 1, then this LMF has the rip field set. Otherwise,
119 * the rip field is not set, and the rsp field points to the stack location where
120 * the caller ip is saved.
122 gpointer previous_lmf;
124 /* This is only set in trampoline LMF frames */
134 #ifdef PLATFORM_WIN32
140 typedef struct MonoCompileArch {
142 gint32 localloc_offset;
143 gint32 reg_save_area_offset;
144 gint32 stack_alloc_size;
145 gboolean omit_fp, omit_fp_computed;
147 gint32 async_point_count;
148 gpointer vret_addr_loc;
149 #ifdef PLATFORM_WIN32
170 #define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->rip = (guint64)(ip); } while (0);
171 #define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->rbp = (guint64)(bp); } while (0);
172 #define MONO_CONTEXT_SET_SP(ctx,esp) do { (ctx)->rsp = (guint64)(esp); } while (0);
174 #define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->rip))
175 #define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->rbp))
176 #define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->rsp))
178 #define MONO_ARCH_INIT_TOP_LMF_ENTRY(lmf)
182 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx, start_func) do { \
184 mono_arch_flush_register_windows (); \
185 stackptr = ((guint64)_AddressOfReturnAddress () - sizeof (void*));\
186 MONO_CONTEXT_SET_IP ((ctx), (start_func)); \
187 MONO_CONTEXT_SET_BP ((ctx), stackptr); \
188 MONO_CONTEXT_SET_SP ((ctx), stackptr); \
194 * __builtin_frame_address () is broken on some older gcc versions in the presence of
195 * frame pointer elimination, see bug #82095.
197 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx,start_func) do { \
199 guint64 stackptr = (guint64)&tmp; \
200 mono_arch_flush_register_windows (); \
201 MONO_CONTEXT_SET_IP ((ctx), (start_func)); \
202 MONO_CONTEXT_SET_BP ((ctx), stackptr); \
203 MONO_CONTEXT_SET_SP ((ctx), stackptr); \
209 * some icalls like mono_array_new_va needs to be called using a different
210 * calling convention.
212 #define MONO_ARCH_VARARG_ICALLS 1
214 #ifndef PLATFORM_WIN32
216 #define MONO_ARCH_USE_SIGACTION 1
218 #ifdef HAVE_WORKING_SIGALTSTACK
220 #define MONO_ARCH_SIGSEGV_ON_ALTSTACK
224 #endif /* PLATFORM_WIN32 */
226 #if defined (__NetBSD__)
246 #define MONO_ARCH_NOMAP32BIT
248 #elif defined (__FreeBSD__)
269 * FreeBSD does not have MAP_32BIT, so code allocated by the code manager might not have a
272 #define MONO_ARCH_NOMAP32BIT
274 #endif /* __FreeBSD__ */
276 #ifdef PLATFORM_WIN32
277 #define MONO_AMD64_ARG_REG1 AMD64_RCX
278 #define MONO_AMD64_ARG_REG2 AMD64_RDX
280 #define MONO_AMD64_ARG_REG1 AMD64_RDI
281 #define MONO_AMD64_ARG_REG2 AMD64_RSI
284 #define MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
285 #define MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
287 #define MONO_ARCH_EMULATE_CONV_R8_UN 1
288 #define MONO_ARCH_EMULATE_FREM 1
289 #define MONO_ARCH_HAVE_IS_INT_OVERFLOW 1
291 #define MONO_ARCH_ENABLE_EMIT_STATE_OPT 1
292 #define MONO_ARCH_ENABLE_REGALLOC_IN_EH_BLOCKS 1
293 #define MONO_ARCH_ENABLE_MONO_LMF_VAR 1
294 #define MONO_ARCH_HAVE_INVALIDATE_METHOD 1
295 #define MONO_ARCH_HAVE_THROW_CORLIB_EXCEPTION 1
296 #define MONO_ARCH_HAVE_CREATE_TRAMPOLINE_FROM_TOKEN 1
297 #define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE 1
298 #define MONO_ARCH_HAVE_ATOMIC_ADD 1
299 #define MONO_ARCH_HAVE_ATOMIC_EXCHANGE 1
300 #define MONO_ARCH_HAVE_ATOMIC_CAS_IMM 1
301 #define MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES 1
302 #define MONO_ARCH_HAVE_IMT 1
303 #define MONO_ARCH_HAVE_TLS_GET 1
304 #define MONO_ARCH_IMT_REG AMD64_R11
305 #define MONO_ARCH_VTABLE_REG MONO_AMD64_ARG_REG1
307 * We use r10 for the rgctx register rather than r11 because r11 is
308 * used by the trampoline as a scratch register and hence might be
309 * clobbered across method call boundaries.
311 #define MONO_ARCH_RGCTX_REG AMD64_R10
312 #define MONO_ARCH_COMMON_VTABLE_TRAMPOLINE 1
313 #define MONO_ARCH_HAVE_CMOV_OPS 1
314 #define MONO_ARCH_HAVE_NOTIFY_PENDING_EXC 1
315 #define MONO_ARCH_ENABLE_NORMALIZE_OPCODES 1
316 #define MONO_ARCH_ENABLE_GLOBAL_RA 1
317 #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
318 #if !defined(PLATFORM_WIN32) && !defined(HAVE_MOVING_COLLECTOR)
319 #define MONO_ARCH_MONITOR_OBJECT_REG AMD64_RDI
322 #define MONO_ARCH_AOT_SUPPORTED 1
324 #if !defined(PLATFORM_WIN32) || defined(__sun)
325 #define MONO_ARCH_ENABLE_MONITOR_IL_FASTPATH 1
328 /* Used for optimization, not complete */
329 #define MONO_ARCH_IS_OP_MEMBASE(opcode) ((opcode) == OP_X86_PUSH_MEMBASE)
331 #define MONO_ARCH_EMIT_BOUNDS_CHECK(cfg, array_reg, offset, index_reg) do { \
333 MONO_INST_NEW ((cfg), inst, OP_AMD64_ICOMPARE_MEMBASE_REG); \
334 inst->inst_basereg = array_reg; \
335 inst->inst_offset = offset; \
336 inst->sreg2 = index_reg; \
337 MONO_ADD_INS ((cfg)->cbb, inst); \
338 MONO_EMIT_NEW_COND_EXC (cfg, LE_UN, "IndexOutOfRangeException"); \
342 mono_amd64_patch (unsigned char* code, gpointer target) MONO_INTERNAL;
345 mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4,
346 guint64 dummy5, guint64 dummy6,
347 MonoObject *exc, guint64 rip, guint64 rsp,
348 guint64 rbx, guint64 rbp, guint64 r12, guint64 r13,
349 guint64 r14, guint64 r15, guint64 rdi, guint64 rsi,
350 guint64 rax, guint64 rcx, guint64 rdx,
354 mono_amd64_emit_tls_get (guint8* code, int dreg, int tls_offset) MONO_INTERNAL;
359 } MonoBreakpointInfo;
361 extern MonoBreakpointInfo mono_breakpoint_info [MONO_BREAKPOINT_ARRAY_SIZE];
363 #ifdef PLATFORM_WIN32
365 void mono_arch_unwindinfo_add_push_nonvol (gpointer* monoui, gpointer codebegin, gpointer nextip, guchar reg );
366 void mono_arch_unwindinfo_add_set_fpreg (gpointer* monoui, gpointer codebegin, gpointer nextip, guchar reg );
367 void mono_arch_unwindinfo_add_alloc_stack (gpointer* monoui, gpointer codebegin, gpointer nextip, guint size );
368 guint mono_arch_unwindinfo_get_size (gpointer monoui);
369 void mono_arch_unwindinfo_install_unwind_info (gpointer* monoui, gpointer code, guint code_size);
371 #define MONO_ARCH_HAVE_UNWIND_TABLE 1
374 #endif /* __MONO_MINI_AMD64_H__ */