Merge from subtype.
[cacao.git] / src / vm / jit / i386 / solaris / md-os.c
1 /* src/vm/jit/i386/solaris/md-os.c - machine dependent i386 Solaris functions
2
3    Copyright (C) 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <stdint.h>
29 #include <ucontext.h>
30
31 #include "vm/types.h"
32
33 #include "vm/jit/i386/codegen.h"
34 #include "vm/jit/i386/md.h"
35
36 #include "threads/thread.hpp"
37
38 #include "vm/jit/builtin.hpp"
39 #include "vm/signallocal.h"
40
41 #include "vm/jit/asmpart.h"
42 #include "vm/jit/executionstate.h"
43 #include "vm/jit/stacktrace.hpp"
44 #include "vm/jit/trap.h"
45
46
47 /* md_signal_handler_sigsegv ***************************************************
48
49    Signal handler for hardware exceptions.
50
51 *******************************************************************************/
52
53 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
54 {
55         ucontext_t     *_uc;
56         mcontext_t     *_mc;
57         u1             *pv;
58         u1             *sp;
59         u1             *ra;
60         u1             *xpc;
61         u1              opc;
62         u1              mod;
63         u1              rm;
64         s4              d;
65         s4              disp;
66         ptrint          val;
67         s4              type;
68         void           *p;
69
70         _uc = (ucontext_t *) _p;
71         _mc = &_uc->uc_mcontext;
72
73         pv  = NULL;                 /* is resolved during stackframeinfo creation */
74         sp  = (u1 *) _mc->gregs[ESP];
75         xpc = (u1 *) _mc->gregs[EIP];
76         ra  = xpc;                              /* return address is equal to XPC */
77
78         /* get exception-throwing instruction */
79
80         opc = M_ALD_MEM_GET_OPC(xpc);
81         mod = M_ALD_MEM_GET_MOD(xpc);
82         rm  = M_ALD_MEM_GET_RM(xpc);
83
84         /* for values see emit_mov_mem_reg and emit_mem */
85
86         if ((opc == 0x8b) && (mod == 0) && (rm == 5)) {
87                 /* this was a hardware-exception */
88
89                 d    = M_ALD_MEM_GET_REG(xpc);
90                 disp = M_ALD_MEM_GET_DISP(xpc);
91
92                 /* we use the exception type as load displacement */
93
94                 type = disp;
95
96                 /* ATTENTION: The _mc->gregs layout is completely crazy!  The
97                    registers are reversed starting with number 4 for REG_EDI
98                    (see /usr/include/sys/ucontext.h).  We have to convert that
99                    here. */
100
101                 val = _mc->gregs[EAX - d];
102
103                 if (type == TRAP_COMPILER) {
104                         /* The PV from the compiler stub is equal to the XPC. */
105
106                         pv = xpc;
107
108                         /* We use a framesize of zero here because the call pushed
109                            the return addres onto the stack. */
110
111                         ra = md_stacktrace_get_returnaddress(sp, 0);
112
113                         /* Skip the RA on the stack. */
114
115                         sp = sp + 1 * SIZEOF_VOID_P;
116
117                         /* The XPC is the RA minus 2, because the RA points to the
118                            instruction after the call. */
119
120                         xpc = ra - 2;
121                 }
122         }
123         else {
124                 /* this was a normal NPE */
125
126                 type = TRAP_NullPointerException;
127                 val  = 0;
128         }
129
130         /* Handle the trap. */
131
132         p = trap_handle(type, val, pv, sp, ra, xpc, _p);
133
134         /* Set registers. */
135
136         if (type == TRAP_COMPILER) {
137                 if (p == NULL) {
138                         _mc->gregs[ESP] = (uintptr_t) sp;    /* Remove RA from stack. */
139                 }
140         }
141 }
142
143
144 /* md_signal_handler_sigfpe ****************************************************
145
146    ArithmeticException signal handler for hardware divide by zero
147    check.
148
149 *******************************************************************************/
150
151 void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
152 {
153         ucontext_t *_uc;
154         mcontext_t *_mc;
155         u1         *pv;
156         u1         *sp;
157         u1         *ra;
158         u1         *xpc;
159         s4          type;
160         ptrint      val;
161
162         _uc = (ucontext_t *) _p;
163         _mc = &_uc->uc_mcontext;
164
165         pv  = NULL;                 /* is resolved during stackframeinfo creation */
166         sp  = (u1 *) _mc->gregs[ESP];
167         xpc = (u1 *) _mc->gregs[EIP];
168         ra  = xpc;                          /* return address is equal to xpc     */
169
170         /* This is an ArithmeticException. */
171
172         type = TRAP_ArithmeticException;
173         val  = 0;
174
175         /* Handle the trap. */
176
177         trap_handle(type, val, pv, sp, ra, xpc, _p);
178 }
179
180
181 /* md_signal_handler_sigill ****************************************************
182
183    Signal handler for hardware patcher traps (ud2).
184
185 *******************************************************************************/
186
187 void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
188 {
189         ucontext_t *_uc;
190         mcontext_t *_mc;
191         u1         *pv;
192         u1         *sp;
193         u1         *ra;
194         u1         *xpc;
195         s4          type;
196         ptrint      val;
197
198         _uc = (ucontext_t *) _p;
199         _mc = &_uc->uc_mcontext;
200
201         pv  = NULL;                 /* is resolved during stackframeinfo creation */
202         sp  = (u1 *) _mc->gregs[ESP];
203         xpc = (u1 *) _mc->gregs[EIP];
204         ra  = xpc;                            /* return address is equal to xpc   */
205
206         type = TRAP_PATCHER;
207         val  = 0;
208
209         /* Handle the trap. */
210
211         trap_handle(type, val, pv, sp, ra, xpc, _p);
212 }
213
214
215 /* md_signal_handler_sigusr1 ***************************************************
216
217    Signal handler for suspending threads.
218
219 *******************************************************************************/
220
221 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
222 void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
223 {
224         ucontext_t *_uc;
225         mcontext_t *_mc;
226         u1         *pc;
227         u1         *sp;
228
229         _uc = (ucontext_t *) _p;
230         _mc = &_uc->uc_mcontext;
231
232         /* get the PC and SP for this thread */
233         pc = (u1 *) _mc->gregs[EIP];
234         sp = (u1 *) _mc->gregs[ESP];
235
236         /* now suspend the current thread */
237         threads_suspend_ack(pc, sp);
238 }
239 #endif
240
241
242 /* md_signal_handler_sigusr2 ***************************************************
243
244    Signal handler for profiling sampling.
245
246 *******************************************************************************/
247
248 #if defined(ENABLE_THREADS)
249 void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
250 {
251         threadobject *t;
252         ucontext_t   *_uc;
253         mcontext_t   *_mc;
254         u1           *pc;
255
256         t = THREADOBJECT;
257
258         _uc = (ucontext_t *) _p;
259         _mc = &_uc->uc_mcontext;
260
261         pc = (u1 *) _mc->gregs[EIP];
262
263         t->pc = pc;
264 }
265 #endif
266
267
268 /* md_executionstate_read ******************************************************
269
270    Read the given context into an executionstate for Replacement.
271
272 *******************************************************************************/
273
274 void md_executionstate_read(executionstate_t *es, void *context)
275 {
276         ucontext_t *_uc;
277         mcontext_t *_mc;
278         s4          i;
279
280         _uc = (ucontext_t *) context;
281         _mc = &_uc->uc_mcontext;
282
283         /* read special registers */
284         es->pc = (u1 *) _mc->gregs[EIP];
285         es->sp = (u1 *) _mc->gregs[ESP];
286         es->pv = NULL;                   /* pv must be looked up via AVL tree */
287
288         /* read integer registers */
289         for (i = 0; i < INT_REG_CNT; i++)
290                 es->intregs[i] = _mc->gregs[EAX - i];
291
292         /* read float registers */
293         for (i = 0; i < FLT_REG_CNT; i++)
294                 es->fltregs[i] = 0xdeadbeefdeadbeefULL;
295 }
296
297
298 /* md_executionstate_write *****************************************************
299
300    Write the given executionstate back to the context for Replacement.
301
302 *******************************************************************************/
303
304 void md_executionstate_write(executionstate_t *es, void *context)
305 {
306         ucontext_t *_uc;
307         mcontext_t *_mc;
308         s4          i;
309
310         _uc = (ucontext_t *) context;
311         _mc = &_uc->uc_mcontext;
312
313         /* write integer registers */
314         for (i = 0; i < INT_REG_CNT; i++)
315                 _mc->gregs[EAX - i] = es->intregs[i];
316
317         /* write special registers */
318         _mc->gregs[EIP] = (ptrint) es->pc;
319         _mc->gregs[ESP] = (ptrint) es->sp;
320 }
321
322
323 /*
324  * These are local overrides for various environment variables in Emacs.
325  * Please do not remove this and leave it at the end of the file, where
326  * Emacs will automagically detect them.
327  * ---------------------------------------------------------------------
328  * Local variables:
329  * mode: c
330  * indent-tabs-mode: t
331  * c-basic-offset: 4
332  * tab-width: 4
333  * End:
334  */