555ea37c3a32adb46714287399f7ee8cf1429fee
[cacao.git] / src / vm / jit / x86_64 / md.c
1 /* src/vm/jit/x86_64/md.c - machine dependent x86_64 Linux functions
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Christian Thalinger
28
29    Changes: Edwin Steiner
30
31    $Id: md.c 4623 2006-03-16 00:05:18Z edwin $
32
33 */
34
35
36 #define _GNU_SOURCE
37
38 #include "config.h"
39
40 #include <stdlib.h>
41 #include <ucontext.h>
42
43 #include "vm/jit/x86_64/md-abi.h"
44
45 #include "vm/exceptions.h"
46 #include "vm/signallocal.h"
47 #include "vm/jit/asmpart.h"
48 #include "vm/jit/stacktrace.h"
49 #include "vm/options.h" /* XXX debug */
50 #include "vm/jit/disass.h" /* XXX debug */
51
52
53 /* md_init *********************************************************************
54
55    Do some machine dependent initialization.
56
57 *******************************************************************************/
58
59 void md_init(void)
60 {
61         /* nothing to do */
62 }
63
64
65 /* md_signal_handler_sigsegv ***************************************************
66
67    NullPointerException signal handler for hardware null pointer
68    check.
69
70 *******************************************************************************/
71
72 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
73 {
74         ucontext_t  *_uc;
75         mcontext_t  *_mc;
76         u1          *sp;
77         u1          *ra;
78         u1          *xpc;
79
80         _uc = (ucontext_t *) _p;
81         _mc = &_uc->uc_mcontext;
82
83         /* ATTENTION: don't use CACAO internal REG_* defines as they are          */
84         /* different to the ones in <ucontext.h>                                  */
85
86         sp  = (u1 *) _mc->gregs[REG_RSP];
87         xpc = (u1 *) _mc->gregs[REG_RIP];
88         ra  = xpc;                          /* return address is equal to xpc     */
89
90         _mc->gregs[REG_RAX] =
91                 (ptrint) stacktrace_hardware_nullpointerexception(NULL, sp, ra, xpc);
92
93         _mc->gregs[REG_R10] = (ptrint) xpc;                      /* REG_ITMP2_XPC */
94         _mc->gregs[REG_RIP] = (ptrint) asm_handle_exception;
95 }
96
97
98 /* md_signal_handler_sigfpe ****************************************************
99
100    ArithmeticException signal handler for hardware divide by zero
101    check.
102
103 *******************************************************************************/
104
105 void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
106 {
107         ucontext_t  *_uc;
108         mcontext_t  *_mc;
109         u1          *sp;
110         u1          *ra;
111         u1          *xpc;
112
113         _uc = (ucontext_t *) _p;
114         _mc = &_uc->uc_mcontext;
115
116         /* ATTENTION: don't use CACAO internal REG_* defines as they are          */
117         /* different to the ones in <ucontext.h>                                  */
118
119         sp  = (u1 *) _mc->gregs[REG_RSP];
120         xpc = (u1 *) _mc->gregs[REG_RIP];
121         ra  = xpc;                          /* return address is equal to xpc     */
122
123         _mc->gregs[REG_RAX] =
124                 (ptrint) stacktrace_hardware_arithmeticexception(NULL, sp, ra, xpc);
125
126         _mc->gregs[REG_R10] = (ptrint) xpc;                      /* REG_ITMP2_XPC */
127         _mc->gregs[REG_RIP] = (ptrint) asm_handle_exception;
128 }
129
130
131 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
132 void thread_restartcriticalsection(ucontext_t *uc)
133 {
134         void *critical;
135
136         critical = thread_checkcritical((void *) uc->uc_mcontext.gregs[REG_RIP]);
137
138         if (critical)
139                 uc->uc_mcontext.gregs[REG_RIP] = (ptrint) critical;
140 }
141 #endif
142
143
144 /* md_stacktrace_get_returnaddress *********************************************
145
146    Returns the return address of the current stackframe, specified by
147    the passed stack pointer and the stack frame size.
148
149 *******************************************************************************/
150
151 u1 *md_stacktrace_get_returnaddress(u1 *sp, u4 framesize)
152 {
153         u1 *ra;
154
155         /* on x86_64 the return address is above the current stack frame */
156
157         ra = *((u1 **) (sp + framesize));
158
159         return ra;
160 }
161
162
163 /* md_codegen_findmethod *******************************************************
164
165    On this architecture just a wrapper function to codegen_findmethod.
166
167 *******************************************************************************/
168
169 u1 *md_codegen_findmethod(u1 *ra)
170 {
171         u1 *pv;
172
173         /* the the start address of the function which contains this
174        address from the method table */
175
176         pv = codegen_findmethod(ra);
177
178         return pv;
179 }
180
181
182 /* md_patch_replacement_point **************************************************
183
184    Patch the given replacement point.
185
186 *******************************************************************************/
187
188 void md_patch_replacement_point(rplpoint *rp)
189 {
190     u8 mcode;
191
192         /* XXX this is probably unsafe! */
193
194         /* save the current machine code */
195         mcode = *(u8*)rp->pc;
196
197         /* write spinning instruction */
198         *(u2*)(rp->pc) = 0xebfe;
199
200         /* write 5th byte */
201         rp->pc[4] = (rp->mcode >> 32);
202
203         /* write first word */
204     *(u4*)(rp->pc) = (u4) rp->mcode;
205
206         /* store saved mcode */
207         rp->mcode = mcode;
208         
209         {
210                 u1* u1ptr = rp->pc;
211                 DISASSINSTR(u1ptr);
212                 fflush(stdout);
213         }
214                         
215     /* XXX if required asm_cacheflush(rp->pc,8); */
216 }
217
218 /*
219  * These are local overrides for various environment variables in Emacs.
220  * Please do not remove this and leave it at the end of the file, where
221  * Emacs will automagically detect them.
222  * ---------------------------------------------------------------------
223  * Local variables:
224  * mode: c
225  * indent-tabs-mode: t
226  * c-basic-offset: 4
227  * tab-width: 4
228  * End:
229  * vim:noexpandtab:sw=4:ts=4:
230  */