* merged with tip (040f180a056b)
[cacao.git] / src / vm / jit / alpha / linux / md-os.c
1 /* src/vm/jit/alpha/linux/md-os.c - machine dependent Alpha 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 <assert.h>
29 #include <stdint.h>
30 #include <ucontext.h>
31
32 #include "vm/types.h"
33
34 #include "vm/jit/alpha/codegen.h"
35 #include "vm/jit/alpha/md.h"
36 #include "vm/jit/alpha/md-abi.h"
37
38 #include "threads/thread.hpp"
39
40 #include "vm/builtin.h"
41 #include "vm/signallocal.h"
42 #include "vm/os.hpp"
43
44 #include "vm/jit/asmpart.h"
45 #include "vm/jit/executionstate.h"
46 #include "vm/jit/trap.h"
47
48
49 /* md_signal_handler_sigsegv ***************************************************
50
51    NullPointerException signal handler for hardware null pointer
52    check.
53
54 *******************************************************************************/
55
56 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
57 {
58         ucontext_t     *_uc;
59         mcontext_t     *_mc;
60         u1             *pv;
61         u1             *sp;
62         u1             *ra;
63         u1             *xpc;
64         u4              mcode;
65         s4              d;
66         s4              s1;
67         s4              disp;
68         intptr_t        val;
69         intptr_t        addr;
70         int             type;
71         void           *p;
72
73         _uc = (ucontext_t *) _p;
74         _mc = &_uc->uc_mcontext;
75
76         pv  = (u1 *) _mc->sc_regs[REG_PV];
77         sp  = (u1 *) _mc->sc_regs[REG_SP];
78         ra  = (u1 *) _mc->sc_regs[REG_RA];           /* this is correct for leafs */
79         xpc = (u1 *) _mc->sc_pc;
80
81         /* get exception-throwing instruction */
82
83         mcode = *((u4 *) xpc);
84
85         d    = M_MEM_GET_Ra(mcode);
86         s1   = M_MEM_GET_Rb(mcode);
87         disp = M_MEM_GET_Memory_disp(mcode);
88
89         val  = _mc->sc_regs[d];
90
91         /* check for special-load */
92
93         if (s1 == REG_ZERO) {
94                 /* we use the exception type as load displacement */
95
96                 type = disp;
97
98                 if (type == TRAP_COMPILER) {
99                         /* The XPC is the RA minus 1, because the RA points to the
100                            instruction after the call. */
101
102                         xpc = ra - 4;
103                 }
104         }
105         else {
106                 /* This is a normal NPE: addr must be NULL and the NPE-type
107                    define is 0. */
108
109                 addr = _mc->sc_regs[s1];
110                 type = (int) addr;
111         }
112
113         /* Handle the trap. */
114
115         p = trap_handle(type, val, pv, sp, ra, xpc, _p);
116
117         /* Set registers. */
118
119         switch (type) {
120         case TRAP_COMPILER:
121                 if (p != NULL) {
122                         _mc->sc_regs[REG_PV] = (uintptr_t) p;
123                         _mc->sc_pc           = (uintptr_t) p;
124                         break;
125                 }
126
127                 /* Get and set the PV from the parent Java method. */
128
129                 pv = md_codegen_get_pv_from_pc(ra);
130
131                 _mc->sc_regs[REG_PV] = (uintptr_t) pv;
132
133                 /* Get the exception object. */
134
135                 p = builtin_retrieve_exception();
136
137                 assert(p != NULL);
138
139                 /* fall-through */
140
141         case TRAP_PATCHER:
142                 if (p == NULL)
143                         break;
144
145                 /* fall-through */
146                 
147         default:
148                 _mc->sc_regs[REG_ITMP1_XPTR] = (uintptr_t) p;
149                 _mc->sc_regs[REG_ITMP2_XPC]  = (uintptr_t) xpc;
150                 _mc->sc_pc                   = (uintptr_t) asm_handle_exception;
151         }
152 }
153
154
155 /* md_signal_handler_sigusr1 ***************************************************
156
157    Signal handler for suspending threads.
158
159 *******************************************************************************/
160
161 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
162 void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
163 {
164         ucontext_t *_uc;
165         mcontext_t *_mc;
166         u1         *pc;
167         u1         *sp;
168
169         _uc = (ucontext_t *) _p;
170         _mc = &_uc->uc_mcontext;
171
172         /* get the PC and SP for this thread */
173         pc = (u1 *) _mc->sc_pc;
174         sp = (u1 *) _mc->sc_regs[REG_SP];
175
176         /* now suspend the current thread */
177         threads_suspend_ack(pc, sp);
178 }
179 #endif
180
181
182 /* md_signal_handler_sigusr2 ***************************************************
183
184    Signal handler for profiling sampling.
185
186 *******************************************************************************/
187
188 #if defined(ENABLE_THREADS)
189 void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
190 {
191         threadobject *tobj;
192         ucontext_t   *_uc;
193         mcontext_t   *_mc;
194         u1           *pc;
195
196         tobj = THREADOBJECT;
197
198         _uc = (ucontext_t *) _p;
199         _mc = &_uc->uc_mcontext;
200
201         pc = (u1 *) _mc->sc_pc;
202
203         tobj->pc = pc;
204 }
205 #endif
206
207
208 /* md_executionstate_read ******************************************************
209
210    Read the given context into an executionstate.
211
212 *******************************************************************************/
213
214 void md_executionstate_read(executionstate_t *es, void *context)
215 {
216         ucontext_t *_uc;
217         mcontext_t *_mc;
218         int         i;
219
220         _uc = (ucontext_t *) context;
221         _mc = &_uc->uc_mcontext;
222
223         /* read special registers */
224         es->pc = (u1 *) _mc->sc_pc;
225         es->sp = (u1 *) _mc->sc_regs[REG_SP];
226         es->pv = (u1 *) _mc->sc_regs[REG_PV];
227         es->ra = (u1 *) _mc->sc_regs[REG_RA];
228
229         /* read integer registers */
230         for (i = 0; i < INT_REG_CNT; i++)
231                 es->intregs[i] = _mc->sc_regs[i];
232
233         /* read float registers */
234         /* Do not use the assignment operator '=', as the type of
235          * the _mc->sc_fpregs[i] can cause invalid conversions. */
236
237         assert(sizeof(_mc->sc_fpregs) == sizeof(es->fltregs));
238         os_memcpy(&es->fltregs, &_mc->sc_fpregs, sizeof(_mc->sc_fpregs));
239 }
240
241
242 /* md_executionstate_write *****************************************************
243
244    Write the given executionstate back to the context.
245
246 *******************************************************************************/
247
248 void md_executionstate_write(executionstate_t *es, void *context)
249 {
250         ucontext_t *_uc;
251         mcontext_t *_mc;
252         int         i;
253
254         _uc = (ucontext_t *) context;
255         _mc = &_uc->uc_mcontext;
256
257         /* write integer registers */
258         for (i = 0; i < INT_REG_CNT; i++)
259                 _mc->sc_regs[i] = es->intregs[i];
260
261         /* write float registers */
262         /* Do not use the assignment operator '=', as the type of
263          * the _mc->sc_fpregs[i] can cause invalid conversions. */
264
265         assert(sizeof(_mc->sc_fpregs) == sizeof(es->fltregs));
266         os_memcpy(&_mc->sc_fpregs, &es->fltregs, sizeof(_mc->sc_fpregs));
267
268         /* write special registers */
269         _mc->sc_pc           = (ptrint) es->pc;
270         _mc->sc_regs[REG_SP] = (ptrint) es->sp;
271         _mc->sc_regs[REG_PV] = (ptrint) es->pv;
272         _mc->sc_regs[REG_RA] = (ptrint) es->ra;
273 }
274
275
276 /*
277  * These are local overrides for various environment variables in Emacs.
278  * Please do not remove this and leave it at the end of the file, where
279  * Emacs will automagically detect them.
280  * ---------------------------------------------------------------------
281  * Local variables:
282  * mode: c
283  * indent-tabs-mode: t
284  * c-basic-offset: 4
285  * tab-width: 4
286  * End:
287  */