* src/vm/jit/x86_64/md.c (md_cacheflush): New method.
[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 4637 2006-03-16 15:36:49Z twisti $
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_cacheflush ***************************************************************
183
184    Calls the system's function to flush the instruction and data
185    cache.
186
187 *******************************************************************************/
188
189 void md_cacheflush(u1 *addr, s4 nbytes)
190 {
191         /* do nothing */
192 }
193
194
195 /* md_patch_replacement_point **************************************************
196
197    Patch the given replacement point.
198
199 *******************************************************************************/
200
201 void md_patch_replacement_point(rplpoint *rp)
202 {
203     u8 mcode;
204
205         /* XXX this is probably unsafe! */
206
207         /* save the current machine code */
208         mcode = *(u8*)rp->pc;
209
210         /* write spinning instruction */
211         *(u2*)(rp->pc) = 0xebfe;
212
213         /* write 5th byte */
214         rp->pc[4] = (rp->mcode >> 32);
215
216         /* write first word */
217     *(u4*)(rp->pc) = (u4) rp->mcode;
218
219         /* store saved mcode */
220         rp->mcode = mcode;
221         
222         {
223                 u1* u1ptr = rp->pc;
224                 DISASSINSTR(u1ptr);
225                 fflush(stdout);
226         }
227                         
228     /* XXX if required asm_cacheflush(rp->pc,8); */
229 }
230
231 /*
232  * These are local overrides for various environment variables in Emacs.
233  * Please do not remove this and leave it at the end of the file, where
234  * Emacs will automagically detect them.
235  * ---------------------------------------------------------------------
236  * Local variables:
237  * mode: c
238  * indent-tabs-mode: t
239  * c-basic-offset: 4
240  * tab-width: 4
241  * End:
242  * vim:noexpandtab:sw=4:ts=4:
243  */