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