* src/vm/exceptions.c: Moved to .cpp.
[cacao.git] / src / vm / jit / powerpc / darwin / md-os.c
1 /* src/vm/jit/powerpc/darwin/md-os.c - machine dependent PowerPC Darwin functions
2
3    Copyright (C) 1996-2005, 2006, 2007, 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 <assert.h>
29 #include <signal.h>
30 #include <stdint.h>
31 #include <ucontext.h>
32
33 #include "vm/types.h"
34
35 #include "vm/jit/powerpc/codegen.h"
36 #include "vm/jit/powerpc/darwin/md-abi.h"
37
38 #include "threads/thread.hpp"
39
40 #include "vm/builtin.h"
41 #include "vm/global.h"
42 #include "vm/signallocal.h"
43 #include "vm/stringlocal.h"
44
45 #include "vm/jit/asmpart.h"
46
47
48 /* md_signal_handler_sigsegv ***************************************************
49
50    NullPointerException signal handler for hardware null pointer
51    check.
52
53 *******************************************************************************/
54
55 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
56 {
57         ucontext_t         *_uc;
58         mcontext_t          _mc;
59         ppc_thread_state_t *_ss;
60         ptrint             *gregs;
61         u1                 *pv;
62         u1                 *sp;
63         u1                 *ra;
64         u1                 *xpc;
65         u4                  mcode;
66         int                 s1;
67         int16_t             disp;
68         int                 d;
69         intptr_t            addr;
70         intptr_t            val;
71         int                 type;
72         void               *p;
73
74         _uc = (ucontext_t *) _p;
75         _mc = _uc->uc_mcontext;
76         _ss = &_mc->ss;
77
78         /* immitate a gregs array */
79
80         gregs = &_ss->r0;
81
82         /* get register values */
83
84         pv  = (u1 *) _ss->r13;
85         sp  = (u1 *) _ss->r1;
86         ra  = (u1 *) _ss->lr;                        /* this is correct for leafs */
87         xpc = (u1 *) _ss->srr0;
88
89         /* get exception-throwing instruction */
90
91         mcode = *((u4 *) xpc);
92
93         s1   = M_INSTR_OP2_IMM_A(mcode);
94         disp = M_INSTR_OP2_IMM_I(mcode);
95         d    = M_INSTR_OP2_IMM_D(mcode);
96
97         val  = gregs[d];
98
99         /* check for special-load */
100
101         if (s1 == REG_ZERO) {
102                 /* we use the exception type as load displacement */
103
104                 type = disp;
105
106                 if (type == EXCEPTION_HARDWARE_COMPILER) {
107                         /* The XPC is the RA minus 4, because the RA points to the
108                            instruction after the call. */
109
110                         xpc = ra - 4;
111                 }
112         }
113         else {
114                 /* This is a normal NPE: addr must be NULL and the NPE-type
115                    define is 0. */
116
117                 addr = gregs[s1];
118                 type = EXCEPTION_HARDWARE_NULLPOINTER;
119
120                 if (addr != 0)
121                         vm_abort("md_signal_handler_sigsegv: faulting address is not NULL: addr=%p", addr);
122         }
123
124         /* Handle the type. */
125
126         p = signal_handle(type, val, pv, sp, ra, xpc, _p);
127
128         /* Set registers. */
129
130         switch (type) {
131         case EXCEPTION_HARDWARE_COMPILER:
132                 if (p != NULL) {
133                         _ss->r13  = (uintptr_t) p;                              /* REG_PV */
134                         _ss->srr0 = (uintptr_t) p;
135                         break;
136                 }
137
138                 /* Get and set the PV from the parent Java method. */
139
140                 pv = md_codegen_get_pv_from_pc(ra);
141
142                 _ss->r13 = (uintptr_t) pv;
143
144                 /* Get the exception object. */
145
146                 p = builtin_retrieve_exception();
147
148                 assert(p != NULL);
149
150                 /* fall-through */
151
152         case EXCEPTION_HARDWARE_PATCHER:
153                 if (p == NULL)
154                         break;
155
156                 /* fall-through */
157                 
158         default:
159                 _ss->r11  = (uintptr_t) p;
160                 _ss->r12  = (uintptr_t) xpc;
161                 _ss->srr0 = (uintptr_t) asm_handle_exception;
162         }
163 }
164
165
166 /* md_signal_handler_sigtrap ***************************************************
167
168    Signal handler for hardware-traps.
169
170 *******************************************************************************/
171
172 void md_signal_handler_sigtrap(int sig, siginfo_t *siginfo, void *_p)
173 {
174         ucontext_t         *_uc;
175         mcontext_t          _mc;
176         ppc_thread_state_t *_ss;
177         ptrint             *gregs;
178         u1                 *pv;
179         u1                 *sp;
180         u1                 *ra;
181         u1                 *xpc;
182         u4                  mcode;
183         int                 s1;
184         intptr_t            val;
185         int                 type;
186         void               *p;
187
188         _uc = (ucontext_t *) _p;
189         _mc = _uc->uc_mcontext;
190         _ss = &_mc->ss;
191
192         /* immitate a gregs array */
193
194         gregs = &_ss->r0;
195
196         /* get register values */
197
198         pv  = (u1 *) _ss->r13;
199         sp  = (u1 *) _ss->r1;
200         ra  = (u1 *) _ss->lr;                    /* this is correct for leafs */
201         xpc = (u1 *) _ss->srr0;
202
203         /* get exception-throwing instruction */
204
205         mcode = *((u4 *) xpc);
206
207         s1 = M_OP3_GET_A(mcode);
208
209         /* for now we only handle ArrayIndexOutOfBoundsException */
210
211         type = EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS;
212         val  = gregs[s1];
213
214         /* Handle the type. */
215
216         p = signal_handle(type, val, pv, sp, ra, xpc, _p);
217
218         /* set registers */
219
220         _ss->r11  = (intptr_t) p;
221         _ss->r12  = (intptr_t) xpc;
222         _ss->srr0 = (intptr_t) asm_handle_exception;
223 }
224
225
226 /* md_signal_handler_sigusr2 ***************************************************
227
228    Signal handler for profiling sampling.
229
230 *******************************************************************************/
231
232 void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
233 {
234         threadobject       *t;
235         ucontext_t         *_uc;
236         mcontext_t          _mc;
237         ppc_thread_state_t *_ss;
238         u1                 *pc;
239
240         t = THREADOBJECT;
241
242         _uc = (ucontext_t *) _p;
243         _mc = _uc->uc_mcontext;
244         _ss = &_mc->ss;
245
246         pc = (u1 *) _ss->srr0;
247
248         t->pc = pc;
249 }
250
251
252 /*
253  * These are local overrides for various environment variables in Emacs.
254  * Please do not remove this and leave it at the end of the file, where
255  * Emacs will automagically detect them.
256  * ---------------------------------------------------------------------
257  * Local variables:
258  * mode: c
259  * indent-tabs-mode: t
260  * c-basic-offset: 4
261  * tab-width: 4
262  * End:
263  */