1 #ifndef __MONO_MINI_AMD64_H__
2 #define __MONO_MINI_AMD64_H__
4 #include <mono/arch/amd64/amd64-codegen.h>
5 #include <mono/utils/mono-sigcontext.h>
10 /* use SIG* defines if possible */
16 /* sigcontext surrogate */
29 typedef void (* MonoW32ExceptionHandler) (int _dummy, EXCEPTION_RECORD *info, void *context);
30 void win32_seh_init(void);
31 void win32_seh_cleanup(void);
32 void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler);
46 LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep);
48 #endif /* HOST_WIN32 */
50 #ifdef sun // Solaris x86
51 # undef SIGSEGV_ON_ALTSTACK
52 # define MONO_ARCH_NOMAP32BIT
55 unsigned short gs, __gsh;
56 unsigned short fs, __fsh;
57 unsigned short es, __esh;
58 unsigned short ds, __dsh;
70 unsigned short cs, __csh;
72 unsigned long esp_at_signal;
73 unsigned short ss, __ssh;
74 unsigned long fpstate[95];
75 unsigned long filler[5];
77 #endif // sun, Solaris x86
79 #define MONO_ARCH_SUPPORT_SIMD_INTRINSICS 1
82 #define MONO_ARCH_SIMD_INTRINSICS 1
83 #define MONO_ARCH_NEED_SIMD_BANK 1
84 #define MONO_ARCH_USE_SHARED_FP_SIMD_BANK 1
89 #define MONO_ARCH_SIGNAL_STACK_SIZE (16 * 1024)
91 #define MONO_ARCH_HAVE_RESTORE_STACK_SUPPORT 1
93 #define MONO_ARCH_CPU_SPEC amd64_desc
95 #define MONO_MAX_IREGS 16
97 #define MONO_MAX_FREGS AMD64_XMM_NREG
99 #define MONO_ARCH_FP_RETURN_REG AMD64_XMM0
101 /* xmm15 is reserved for use by some opcodes */
102 #define MONO_ARCH_CALLEE_FREGS 0x7fff
103 #define MONO_ARCH_CALLEE_SAVED_FREGS 0
105 #define MONO_MAX_XREGS MONO_MAX_FREGS
107 #define MONO_ARCH_CALLEE_XREGS 0x7fff
108 #define MONO_ARCH_CALLEE_SAVED_XREGS 0
111 #define MONO_ARCH_CALLEE_REGS AMD64_CALLEE_REGS
112 #define MONO_ARCH_CALLEE_SAVED_REGS AMD64_CALLEE_SAVED_REGS
114 #define MONO_ARCH_USE_FPSTACK FALSE
115 #define MONO_ARCH_FPSTACK_SIZE 0
117 #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))))))
119 /* RDX is clobbered by the opcode implementation before accessing sreg2 */
120 #define MONO_ARCH_INST_SREG2_MASK(ins) (((ins [MONO_INST_CLOB] == 'a') || (ins [MONO_INST_CLOB] == 'd')) ? (1 << AMD64_RDX) : 0)
122 #define MONO_ARCH_INST_IS_REGPAIR(desc) FALSE
123 #define MONO_ARCH_INST_REGPAIR_REG2(desc,hreg1) (-1)
125 #define MONO_ARCH_FRAME_ALIGNMENT 16
127 /* fixme: align to 16byte instead of 32byte (we align to 32byte to get
128 * reproduceable results for benchmarks */
129 #define MONO_ARCH_CODE_ALIGNMENT 32
131 #define MONO_ARCH_RETREG1 X86_EAX
132 #define MONO_ARCH_RETREG2 X86_EDX
134 /*This is the max size of the locals area of a given frame. I think 1MB is a safe default for now*/
135 #define MONO_ARCH_MAX_FRAME_SIZE 0x100000
139 * If the lowest bit is set to 1, then this LMF has the rip field set. Otherwise,
140 * the rip field is not set, and the rsp field points to the stack location where
141 * the caller ip is saved.
142 * If the second lowest bit is set to 1, then this is a MonoLMFExt structure, and
143 * the other fields are not valid.
145 gpointer previous_lmf;
147 /* This is only set in trampoline LMF frames */
163 typedef struct MonoCompileArch {
165 gint32 localloc_offset;
166 gint32 reg_save_area_offset;
167 gint32 stack_alloc_size;
168 gboolean omit_fp, omit_fp_computed, no_pushes;
170 gint32 async_point_count;
171 gpointer vret_addr_loc;
175 gpointer ss_trigger_page_var;
194 #define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->rip = (guint64)(ip); } while (0);
195 #define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->rbp = (guint64)(bp); } while (0);
196 #define MONO_CONTEXT_SET_SP(ctx,esp) do { (ctx)->rsp = (guint64)(esp); } while (0);
198 #define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->rip))
199 #define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->rbp))
200 #define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->rsp))
202 #define MONO_CONTEXT_SET_LLVM_EXC_REG(ctx, exc) do { (ctx)->rax = (gsize)exc; } while (0)
204 #define MONO_ARCH_INIT_TOP_LMF_ENTRY(lmf)
208 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx, start_func) do { \
210 mono_arch_flush_register_windows (); \
211 stackptr = ((guint64)_AddressOfReturnAddress () - sizeof (void*));\
212 MONO_CONTEXT_SET_IP ((ctx), (start_func)); \
213 MONO_CONTEXT_SET_BP ((ctx), stackptr); \
214 MONO_CONTEXT_SET_SP ((ctx), stackptr); \
220 * __builtin_frame_address () is broken on some older gcc versions in the presence of
221 * frame pointer elimination, see bug #82095.
223 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx,start_func) do { \
225 guint64 stackptr = (guint64)&tmp; \
226 mono_arch_flush_register_windows (); \
227 MONO_CONTEXT_SET_IP ((ctx), (start_func)); \
228 MONO_CONTEXT_SET_BP ((ctx), stackptr); \
229 MONO_CONTEXT_SET_SP ((ctx), stackptr); \
235 * This structure is an extension of MonoLMF and contains extra information.
239 gboolean debugger_invoke;
240 MonoContext ctx; /* if debugger_invoke is TRUE */
244 * some icalls like mono_array_new_va needs to be called using a different
245 * calling convention.
247 #define MONO_ARCH_VARARG_ICALLS 1
251 #define MONO_ARCH_USE_SIGACTION 1
253 #ifdef HAVE_WORKING_SIGALTSTACK
255 #define MONO_ARCH_SIGSEGV_ON_ALTSTACK
259 #endif /* HOST_WIN32 */
261 #if defined (__NetBSD__)
281 #define MONO_ARCH_NOMAP32BIT
283 #elif defined (__OpenBSD__)
285 #define MONO_ARCH_NOMAP32BIT
287 #elif defined (__FreeBSD__)
308 * FreeBSD does not have MAP_32BIT, so code allocated by the code manager might not have a
311 #define MONO_ARCH_NOMAP32BIT
313 #endif /* __FreeBSD__ */
316 #define MONO_AMD64_ARG_REG1 AMD64_RCX
317 #define MONO_AMD64_ARG_REG2 AMD64_RDX
319 #define MONO_AMD64_ARG_REG1 AMD64_RDI
320 #define MONO_AMD64_ARG_REG2 AMD64_RSI
323 #define MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
324 #define MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
326 #define MONO_ARCH_EMULATE_CONV_R8_UN 1
327 #define MONO_ARCH_EMULATE_FREM 1
328 #define MONO_ARCH_HAVE_IS_INT_OVERFLOW 1
330 #define MONO_ARCH_ENABLE_REGALLOC_IN_EH_BLOCKS 1
331 #define MONO_ARCH_ENABLE_MONO_LMF_VAR 1
332 #define MONO_ARCH_HAVE_INVALIDATE_METHOD 1
333 #define MONO_ARCH_HAVE_THROW_CORLIB_EXCEPTION 1
334 #define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE 1
335 #define MONO_ARCH_HAVE_ATOMIC_ADD 1
336 #define MONO_ARCH_HAVE_ATOMIC_EXCHANGE 1
337 #define MONO_ARCH_HAVE_ATOMIC_CAS 1
338 #define MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES 1
339 #define MONO_ARCH_HAVE_IMT 1
340 #define MONO_ARCH_HAVE_TLS_GET 1
341 #define MONO_ARCH_IMT_REG AMD64_R11
342 #define MONO_ARCH_VTABLE_REG MONO_AMD64_ARG_REG1
344 * We use r10 for the rgctx register rather than r11 because r11 is
345 * used by the trampoline as a scratch register and hence might be
346 * clobbered across method call boundaries.
348 #define MONO_ARCH_RGCTX_REG AMD64_R10
349 #define MONO_ARCH_HAVE_CMOV_OPS 1
350 #define MONO_ARCH_HAVE_NOTIFY_PENDING_EXC 1
351 #define MONO_ARCH_HAVE_EXCEPTIONS_INIT 1
352 #define MONO_ARCH_ENABLE_GLOBAL_RA 1
353 #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
354 #define MONO_ARCH_HAVE_LIVERANGE_OPS 1
355 #define MONO_ARCH_HAVE_XP_UNWIND 1
356 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1
357 #if !defined(HOST_WIN32) && !defined(HAVE_MOVING_COLLECTOR)
358 #define MONO_ARCH_MONITOR_OBJECT_REG MONO_AMD64_ARG_REG1
360 #define MONO_ARCH_HAVE_STATIC_RGCTX_TRAMPOLINE 1
362 #define MONO_ARCH_AOT_SUPPORTED 1
364 #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
366 #define DISABLE_DEBUGGER_AGENT 1
368 #define MONO_ARCH_HAVE_FIND_JIT_INFO_EXT 1
370 #if !defined(HOST_WIN32) || defined(__sun)
371 #define MONO_ARCH_ENABLE_MONITOR_IL_FASTPATH 1
374 #define MONO_ARCH_SUPPORT_TASKLETS 1
377 #define MONO_AMD64_NO_PUSHES 1
380 #define MONO_ARCH_GSHARED_SUPPORTED 1
381 #define MONO_ARCH_DYN_CALL_SUPPORTED 1
382 #define MONO_ARCH_DYN_CALL_PARAM_AREA 0
384 #define MONO_ARCH_HAVE_LLVM_IMT_TRAMPOLINE 1
385 #define MONO_ARCH_LLVM_SUPPORTED 1
387 #define MONO_ARCH_USE_OP_TAIL_CALL(caller_sig, callee_sig) mono_metadata_signature_equal ((caller_sig), (callee_sig))
389 /* Used for optimization, not complete */
390 #define MONO_ARCH_IS_OP_MEMBASE(opcode) ((opcode) == OP_X86_PUSH_MEMBASE)
392 #define MONO_ARCH_EMIT_BOUNDS_CHECK(cfg, array_reg, offset, index_reg) do { \
394 MONO_INST_NEW ((cfg), inst, OP_AMD64_ICOMPARE_MEMBASE_REG); \
395 inst->inst_basereg = array_reg; \
396 inst->inst_offset = offset; \
397 inst->sreg2 = index_reg; \
398 MONO_ADD_INS ((cfg)->cbb, inst); \
399 MONO_EMIT_NEW_COND_EXC (cfg, LE_UN, "IndexOutOfRangeException"); \
403 mono_amd64_patch (unsigned char* code, gpointer target) MONO_INTERNAL;
406 mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4,
407 guint64 dummy5, guint64 dummy6,
408 MonoObject *exc, guint64 rip, guint64 rsp,
409 guint64 rbx, guint64 rbp, guint64 r12, guint64 r13,
410 guint64 r14, guint64 r15, guint64 rdi, guint64 rsi,
411 guint64 rax, guint64 rcx, guint64 rdx,
415 mono_amd64_get_original_ip (void) MONO_INTERNAL;
418 mono_amd64_emit_tls_get (guint8* code, int dreg, int tls_offset) MONO_INTERNAL;
423 } MonoBreakpointInfo;
425 extern MonoBreakpointInfo mono_breakpoint_info [MONO_BREAKPOINT_ARRAY_SIZE];
429 void mono_arch_unwindinfo_add_push_nonvol (gpointer* monoui, gpointer codebegin, gpointer nextip, guchar reg );
430 void mono_arch_unwindinfo_add_set_fpreg (gpointer* monoui, gpointer codebegin, gpointer nextip, guchar reg );
431 void mono_arch_unwindinfo_add_alloc_stack (gpointer* monoui, gpointer codebegin, gpointer nextip, guint size );
432 guint mono_arch_unwindinfo_get_size (gpointer monoui);
433 void mono_arch_unwindinfo_install_unwind_info (gpointer* monoui, gpointer code, guint code_size);
435 #define MONO_ARCH_HAVE_UNWIND_TABLE 1
438 #endif /* __MONO_MINI_AMD64_H__ */