2008-07-08 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / mini-amd64.h
1 #ifndef __MONO_MINI_AMD64_H__
2 #define __MONO_MINI_AMD64_H__
3
4 #include <mono/arch/amd64/amd64-codegen.h>
5 #include <glib.h>
6
7 #ifdef PLATFORM_WIN32
8 #include <windows.h>
9 /* use SIG* defines if possible */
10 #ifdef HAVE_SIGNAL_H
11 #include <signal.h>
12 #endif
13
14 /* sigcontext surrogate */
15 struct sigcontext {
16         guint64 eax;
17         guint64 ebx;
18         guint64 ecx;
19         guint64 edx;
20         guint64 ebp;
21         guint64 esp;
22     guint64 esi;
23         guint64 edi;
24         guint64 eip;
25 };
26
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);
31
32 #ifndef SIGFPE
33 #define SIGFPE 4
34 #endif
35
36 #ifndef SIGILL
37 #define SIGILL 8
38 #endif
39
40 #ifndef SIGSEGV
41 #define SIGSEGV 11
42 #endif
43
44 LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep);
45
46 #endif /* PLATFORM_WIN32 */
47
48 #ifdef sun    // Solaris x86
49 #  undef SIGSEGV_ON_ALTSTACK
50 #  define MONO_ARCH_NOMAP32BIT
51
52 struct sigcontext {
53         unsigned short gs, __gsh;
54         unsigned short fs, __fsh;
55         unsigned short es, __esh;
56         unsigned short ds, __dsh;
57         unsigned long edi;
58         unsigned long esi;
59         unsigned long ebp;
60         unsigned long esp;
61         unsigned long ebx;
62         unsigned long edx;
63         unsigned long ecx;
64         unsigned long eax;
65         unsigned long trapno;
66         unsigned long err;
67         unsigned long eip;
68         unsigned short cs, __csh;
69         unsigned long eflags;
70         unsigned long esp_at_signal;
71         unsigned short ss, __ssh;
72         unsigned long fpstate[95];
73       unsigned long filler[5];
74 };
75 #endif  // sun, Solaris x86
76
77 #define MONO_ARCH_SIGNAL_STACK_SIZE (16 * 1024)
78
79 #define MONO_ARCH_CPU_SPEC amd64_desc
80
81 #define MONO_MAX_IREGS 16
82
83 #define MONO_MAX_FREGS AMD64_XMM_NREG
84
85 /* xmm15 is reserved for use by some opcodes */
86 #define MONO_ARCH_CALLEE_FREGS 0xef
87 #define MONO_ARCH_CALLEE_SAVED_FREGS 0
88
89 #define MONO_ARCH_CALLEE_REGS AMD64_CALLEE_REGS
90 #define MONO_ARCH_CALLEE_SAVED_REGS AMD64_CALLEE_SAVED_REGS
91
92 #define MONO_ARCH_USE_FPSTACK FALSE
93 #define MONO_ARCH_FPSTACK_SIZE 0
94
95 #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))))))
96
97 /* RDX is clobbered by the opcode implementation before accessing sreg2 */
98 #define MONO_ARCH_INST_SREG2_MASK(ins) (((ins [MONO_INST_CLOB] == 'a') || (ins [MONO_INST_CLOB] == 'd')) ? (1 << AMD64_RDX) : 0)
99
100 #define MONO_ARCH_INST_IS_REGPAIR(desc) FALSE
101 #define MONO_ARCH_INST_REGPAIR_REG2(desc,hreg1) (-1)
102
103 #define MONO_ARCH_FRAME_ALIGNMENT 16
104
105 /* fixme: align to 16byte instead of 32byte (we align to 32byte to get 
106  * reproduceable results for benchmarks */
107 #define MONO_ARCH_CODE_ALIGNMENT 32
108
109 #define MONO_ARCH_BASEREG X86_EBP
110 #define MONO_ARCH_RETREG1 X86_EAX
111 #define MONO_ARCH_RETREG2 X86_EDX
112
113 #define MONO_ARCH_AOT_PLT_OFFSET_REG AMD64_RAX
114
115 #define MONO_ARCH_ENCODE_LREG(r1,r2) (r1 | (r2<<3))
116
117 #define inst_dreg_low dreg&7 
118 #define inst_dreg_high dreg>>3
119 #define inst_sreg1_low sreg1&7 
120 #define inst_sreg1_high sreg1>>3
121 #define inst_sreg2_low sreg2&7 
122 #define inst_sreg2_high sreg2>>3
123
124 struct MonoLMF {
125         /* 
126          * If the lowest bit is set to 1, then this LMF has the rip field set. Otherwise,
127          * the rip field is not set, and the rsp field points to the stack location where
128          * the caller ip is saved.
129          */
130         gpointer    previous_lmf;
131         gpointer    lmf_addr;
132         /* This is only set in trampoline LMF frames */
133         MonoMethod *method;
134         guint64     rip;
135         guint64     rbx;
136         guint64     rbp;
137         guint64     rsp;
138         guint64     r12;
139         guint64     r13;
140         guint64     r14;
141         guint64     r15;
142 #ifdef PLATFORM_WIN32
143         guint64     rdi;
144         guint64     rsi;
145 #endif
146 };
147
148 typedef struct MonoCompileArch {
149         gint32 lmf_offset;
150         gint32 localloc_offset;
151         gint32 reg_save_area_offset;
152         gint32 stack_alloc_size;
153         gboolean omit_fp, omit_fp_computed;
154         gpointer cinfo;
155         gint32 async_point_count;
156         gpointer vret_addr_loc;
157 } MonoCompileArch;
158
159 typedef struct {
160         guint64 rax;
161         guint64 rbx;
162         guint64 rcx;
163         guint64 rdx;
164         guint64 rbp;
165         guint64 rsp;
166     guint64 rsi;
167         guint64 rdi;
168         guint64 rip;
169         guint64 r12;
170         guint64 r13;
171         guint64 r14;
172         guint64 r15;
173 } MonoContext;
174
175 #define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->rip = (guint64)(ip); } while (0); 
176 #define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->rbp = (guint64)(bp); } while (0); 
177 #define MONO_CONTEXT_SET_SP(ctx,esp) do { (ctx)->rsp = (guint64)(esp); } while (0); 
178
179 #define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->rip))
180 #define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->rbp))
181 #define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->rsp))
182
183 #define MONO_ARCH_INIT_TOP_LMF_ENTRY(lmf)
184
185 #ifdef _MSC_VER
186
187 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx, start_func) do { \
188     guint64 stackptr; \
189         mono_arch_flush_register_windows (); \
190         stackptr = ((guint64)_AddressOfReturnAddress () - sizeof (void*));\
191         MONO_CONTEXT_SET_IP ((ctx), (start_func)); \
192         MONO_CONTEXT_SET_BP ((ctx), stackptr); \
193         MONO_CONTEXT_SET_SP ((ctx), stackptr); \
194 } while (0)
195
196 #else
197
198 /* 
199  * __builtin_frame_address () is broken on some older gcc versions in the presence of
200  * frame pointer elimination, see bug #82095.
201  */
202 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx,start_func) do {        \
203         int tmp; \
204         guint64 stackptr = (guint64)&tmp; \
205                 mono_arch_flush_register_windows ();    \
206                 MONO_CONTEXT_SET_IP ((ctx), (start_func));      \
207                 MONO_CONTEXT_SET_BP ((ctx), stackptr);  \
208                 MONO_CONTEXT_SET_SP ((ctx), stackptr);  \
209         } while (0)
210
211 #endif
212
213 /*
214  * some icalls like mono_array_new_va needs to be called using a different 
215  * calling convention.
216  */
217 #define MONO_ARCH_VARARG_ICALLS 1
218
219 #ifndef PLATFORM_WIN32
220
221 #define MONO_ARCH_USE_SIGACTION 1
222
223 #ifdef HAVE_WORKING_SIGALTSTACK
224
225 #define MONO_ARCH_SIGSEGV_ON_ALTSTACK
226
227 #endif
228
229 #endif /* PLATFORM_WIN32 */
230
231 #ifdef __FreeBSD__
232
233 #define REG_RAX 7
234 #define REG_RCX 4
235 #define REG_RDX 3
236 #define REG_RBX 8
237 #define REG_RSP 23
238 #define REG_RBP 9
239 #define REG_RSI 2
240 #define REG_RDI 1
241 #define REG_R8  5
242 #define REG_R9  6
243 #define REG_R10 10
244 #define REG_R11 11
245 #define REG_R12 12
246 #define REG_R13 13
247 #define REG_R14 14
248 #define REG_R15 15
249 #define REG_RIP 20
250
251 /* 
252  * FreeBSD does not have MAP_32BIT, so code allocated by the code manager might not have a
253  * 32 bit address.
254  */
255 #define MONO_ARCH_NOMAP32BIT
256
257 #endif /* __FreeBSD__ */
258
259 #define MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
260 #define MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
261
262 #define MONO_ARCH_EMULATE_CONV_R8_UN    1
263 #define MONO_ARCH_EMULATE_FREM 1
264 #define MONO_ARCH_HAVE_IS_INT_OVERFLOW 1
265
266 #define MONO_ARCH_ENABLE_EMIT_STATE_OPT 1
267 #define MONO_ARCH_ENABLE_REGALLOC_IN_EH_BLOCKS 1
268 #define MONO_ARCH_ENABLE_MONO_LMF_VAR 1
269 #define MONO_ARCH_HAVE_INVALIDATE_METHOD 1
270 #define MONO_ARCH_HAVE_THROW_CORLIB_EXCEPTION 1
271 #define MONO_ARCH_HAVE_CREATE_TRAMPOLINE_FROM_TOKEN 1
272 #define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE 1
273 #define MONO_ARCH_HAVE_ATOMIC_ADD 1
274 #define MONO_ARCH_HAVE_ATOMIC_EXCHANGE 1
275 #define MONO_ARCH_HAVE_ATOMIC_CAS_IMM 1
276 #define MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES 1
277 #define MONO_ARCH_HAVE_IMT 1
278 #define MONO_ARCH_HAVE_TLS_GET 1
279 #define MONO_ARCH_IMT_REG AMD64_R11
280 #define MONO_ARCH_VTABLE_REG AMD64_R11
281 /*
282  * We use r10 for the rgctx register rather than r11 because r11 is
283  * used by the trampoline as a scratch register and hence might be
284  * clobbered across method call boundaries.
285  */
286 #define MONO_ARCH_RGCTX_REG AMD64_R10
287 #define MONO_ARCH_COMMON_VTABLE_TRAMPOLINE 1
288 #define MONO_ARCH_HAVE_NOTIFY_PENDING_EXC 1
289 #define MONO_ARCH_ENABLE_NORMALIZE_OPCODES 1
290
291 #define MONO_ARCH_AOT_SUPPORTED 1
292
293 void 
294 mono_amd64_patch (unsigned char* code, gpointer target) MONO_INTERNAL;
295
296 void
297 mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4,
298                                                         guint64 dummy5, guint64 dummy6,
299                                                         MonoObject *exc, guint64 rip, guint64 rsp,
300                                                         guint64 rbx, guint64 rbp, guint64 r12, guint64 r13, 
301                                                         guint64 r14, guint64 r15, guint64 rdi, guint64 rsi, 
302                                                         guint64 rax, guint64 rcx, guint64 rdx,
303                                                         guint64 rethrow);
304
305 typedef struct {
306         guint8 *address;
307         guint8 saved_byte;
308 } MonoBreakpointInfo;
309
310 extern MonoBreakpointInfo mono_breakpoint_info [MONO_BREAKPOINT_ARRAY_SIZE];
311
312 #endif /* __MONO_MINI_AMD64_H__ */  
313