* src/vm/jit/stacktrace.c: Moved to .cpp.
[cacao.git] / src / vm / jit / arm / linux / md-os.c
1 /* src/vm/jit/arm/linux/md-os.c - machine dependent ARM Linux 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 <stdint.h>
29
30 #include "vm/types.h"
31
32 #include "vm/jit/disass.h"
33
34 #include "vm/jit/arm/md-abi.h"
35
36 #define ucontext broken_glibc_ucontext
37 #define ucontext_t broken_glibc_ucontext_t
38 #include <ucontext.h>
39 #undef ucontext
40 #undef ucontext_t
41
42 typedef struct ucontext {
43    unsigned long     uc_flags;
44    struct ucontext  *uc_link;
45    stack_t           uc_stack;
46    struct sigcontext uc_mcontext;
47    sigset_t          uc_sigmask;
48 } ucontext_t;
49
50 #define scontext_t struct sigcontext
51
52 #include "threads/thread.h"
53
54 #include "vm/exceptions.h"
55 #include "vm/signallocal.h"
56 #include "vm/stringlocal.h"
57 #include "vm/vm.hpp"
58
59 #include "vm/jit/asmpart.h"
60 #include "vm/jit/executionstate.h"
61 #include "vm/jit/trap.h"
62
63
64 /* md_signal_handler_sigsegv ***************************************************
65
66    Signal handler for hardware exceptions.
67
68 *******************************************************************************/
69
70 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
71 {
72         ucontext_t     *_uc;
73         scontext_t     *_sc;
74         u1             *pv;
75         u1             *sp;
76         u1             *ra;
77         u1             *xpc;
78         u4              mcode;
79         intptr_t        addr;
80         int             type;
81         intptr_t        val;
82         void           *p;
83
84         _uc = (ucontext_t*) _p;
85         _sc = &_uc->uc_mcontext;
86
87         /* ATTENTION: glibc included messed up kernel headers we needed a
88            workaround for the ucontext structure. */
89
90         pv  = (u1 *) _sc->arm_ip;
91         sp  = (u1 *) _sc->arm_sp;
92         ra  = (u1 *) _sc->arm_lr;                    /* this is correct for leafs */
93         xpc = (u1 *) _sc->arm_pc;
94
95         /* get exception-throwing instruction */
96
97         if (xpc == NULL)
98                 vm_abort("md_signal_handler_sigsegv: the program counter is NULL");
99
100         mcode = *((s4 *) xpc);
101
102         /* This is a NullPointerException. */
103
104         addr = *((s4 *) _sc + OFFSET(scontext_t, arm_r0)/4 + ((mcode >> 16) & 0x0f));
105         type = addr;
106         val  = 0;
107
108         /* Handle the trap. */
109
110         p = trap_handle(type, val, pv, sp, ra, xpc, _p);
111
112         /* set registers */
113
114         _sc->arm_r10 = (uintptr_t) p;
115         _sc->arm_fp  = (uintptr_t) xpc;
116         _sc->arm_pc  = (uintptr_t) asm_handle_exception;
117 }
118
119
120 /* md_signal_handler_sigill ****************************************************
121
122    Illegal Instruction signal handler for hardware exception checks.
123
124 *******************************************************************************/
125
126 void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
127 {
128         ucontext_t     *_uc;
129         scontext_t     *_sc;
130         u1             *pv;
131         u1             *sp;
132         u1             *ra;
133         u1             *xpc;
134         u4              mcode;
135         int             type;
136         intptr_t        val;
137         void           *p;
138
139         _uc = (ucontext_t*) _p;
140         _sc = &_uc->uc_mcontext;
141
142         /* ATTENTION: glibc included messed up kernel headers we needed a
143            workaround for the ucontext structure. */
144
145         pv  = (u1 *) _sc->arm_ip;
146         sp  = (u1 *) _sc->arm_sp;
147         ra  = (u1 *) _sc->arm_lr;                    /* this is correct for leafs */
148         xpc = (u1 *) _sc->arm_pc;
149
150         /* get exception-throwing instruction */
151
152         mcode = *((u4 *) xpc);
153
154         /* check for undefined instruction we use */
155
156         if ((mcode & 0x0ff000f0) != 0x07f000f0) {
157                 log_println("md_signal_handler_sigill: unknown illegal instruction: inst=%x", mcode);
158 #if defined(ENABLE_DISASSEMBLER)
159                 DISASSINSTR(xpc);
160 #endif
161                 vm_abort("Aborting...");
162         }
163
164         type = (mcode >> 8) & 0x0fff;
165         val  = *((s4 *) _sc + OFFSET(scontext_t, arm_r0)/4 + (mcode & 0x0f));
166
167         /* Handle the trap. */
168
169         p = trap_handle(type, val, pv, sp, ra, xpc, _p);
170
171         /* set registers if we have an exception, continue execution
172            otherwise (this is needed for patchers to work) */
173
174         if (p != NULL) {
175                 _sc->arm_r10 = (uintptr_t) p;
176                 _sc->arm_fp  = (uintptr_t) xpc;
177                 _sc->arm_pc  = (uintptr_t) asm_handle_exception;
178         }
179 }
180
181
182 /* md_signal_handler_sigusr1 ***************************************************
183
184    Signal handler for suspending threads.
185
186 *******************************************************************************/
187
188 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
189 void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
190 {
191         ucontext_t *_uc;
192         scontext_t *_sc;
193         u1         *pc;
194         u1         *sp;
195
196         _uc = (ucontext_t *) _p;
197         _sc = &_uc->uc_mcontext;
198
199         /* get the PC and SP for this thread */
200         pc = (u1 *) _sc->arm_pc;
201         sp = (u1 *) _sc->arm_sp;
202
203         /* now suspend the current thread */
204         threads_suspend_ack(pc, sp);
205 }
206 #endif
207
208
209 /* md_signal_handler_sigusr2 ***************************************************
210
211    Signal handler for profiling sampling.
212
213 *******************************************************************************/
214
215 #if defined(ENABLE_THREADS)
216 void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
217 {
218         threadobject *thread;
219         ucontext_t   *_uc;
220         scontext_t   *_sc;
221         u1           *pc;
222
223         thread = THREADOBJECT;
224
225         _uc = (ucontext_t*) _p;
226         _sc = &_uc->uc_mcontext;
227
228         pc = (u1 *) _sc->arm_pc;
229
230         thread->pc = pc;
231 }
232 #endif
233
234
235 /**
236  * Read the given context into an executionstate.
237  *
238  * @param es      execution state
239  * @param context machine context
240  */
241 void md_executionstate_read(executionstate_t *es, void *context)
242 {
243         vm_abort("md_executionstate_read: IMPLEMENT ME!");
244
245 #if 0
246         ucontext_t *_uc;
247         mcontext_t *_mc;
248         int         i;
249
250         _uc = (ucontext_t *) context;
251         _mc = &_uc->uc_mcontext;
252
253         /* read special registers */
254         es->pc = (u1 *) _mc->sc_pc;
255         es->sp = (u1 *) _mc->sc_regs[REG_SP];
256         es->pv = (u1 *) _mc->sc_regs[REG_PV];
257         es->ra = (u1 *) _mc->sc_regs[REG_RA];
258
259         /* read integer registers */
260         for (i = 0; i < INT_REG_CNT; i++)
261                 es->intregs[i] = _mc->sc_regs[i];
262
263         /* read float registers */
264         /* Do not use the assignment operator '=', as the type of
265          * the _mc->sc_fpregs[i] can cause invalid conversions. */
266
267         assert(sizeof(_mc->sc_fpregs) == sizeof(es->fltregs));
268         system_memcpy(&es->fltregs, &_mc->sc_fpregs, sizeof(_mc->sc_fpregs));
269 #endif
270 }
271
272
273 /**
274  * Write the given executionstate back to the context.
275  *
276  * @param es      execution state
277  * @param context machine context
278  */
279 void md_executionstate_write(executionstate_t *es, void *context)
280 {
281         vm_abort("md_executionstate_write: IMPLEMENT ME!");
282
283 #if 0
284         ucontext_t *_uc;
285         mcontext_t *_mc;
286         int         i;
287
288         _uc = (ucontext_t *) context;
289         _mc = &_uc->uc_mcontext;
290
291         /* write integer registers */
292         for (i = 0; i < INT_REG_CNT; i++)
293                 _mc->sc_regs[i] = es->intregs[i];
294
295         /* write float registers */
296         /* Do not use the assignment operator '=', as the type of
297          * the _mc->sc_fpregs[i] can cause invalid conversions. */
298
299         assert(sizeof(_mc->sc_fpregs) == sizeof(es->fltregs));
300         system_memcpy(&_mc->sc_fpregs, &es->fltregs, sizeof(_mc->sc_fpregs));
301
302         /* write special registers */
303         _mc->sc_pc           = (ptrint) es->pc;
304         _mc->sc_regs[REG_SP] = (ptrint) es->sp;
305         _mc->sc_regs[REG_PV] = (ptrint) es->pv;
306         _mc->sc_regs[REG_RA] = (ptrint) es->ra;
307 #endif
308 }
309
310
311 /*
312  * These are local overrides for various environment variables in Emacs.
313  * Please do not remove this and leave it at the end of the file, where
314  * Emacs will automagically detect them.
315  * ---------------------------------------------------------------------
316  * Local variables:
317  * mode: c
318  * indent-tabs-mode: t
319  * c-basic-offset: 4
320  * tab-width: 4
321  * End:
322  */
323