* src/vm/jit/codegen-common.cpp, src/vm/jit/x86_64/codegen.c: Generate
[cacao.git] / src / vm / jit / x86_64 / solaris / md-os.c
1 /* src/vm/jit/x86_64/solaris/md-os.c - machine dependent x86_64 Solaris functions
2
3    Copyright (C) 2008, 2009
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 <stdlib.h>
31 #include <ucontext.h>
32
33 #include "vm/types.h"
34
35 #include "vm/jit/x86_64/codegen.h"
36 #include "vm/jit/x86_64/md.h"
37
38 #include "threads/thread.hpp"
39
40 #include "vm/signallocal.hpp"
41
42 #include "vm/jit/asmpart.h"
43 #include "vm/jit/executionstate.h"
44 #include "vm/jit/trap.hpp"
45
46
47 /**
48  * Signal handler for hardware exceptions.
49  */
50 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
51 {
52         ucontext_t *_uc = (ucontext_t *) _p;
53         mcontext_t *_mc = &_uc->uc_mcontext;
54
55         /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
56            different to the ones in <ucontext.h>. */
57
58         void* xpc = (void *) _mc->gregs[REG_RIP];
59
60     // Handle the trap.
61     trap_handle(TRAP_SIGSEGV, xpc, _p);
62 }
63
64
65 /**
66  * Signal handler for hardware divide by zero (ArithmeticException)
67  * check.
68  */
69 void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
70 {
71         ucontext_t *_uc = (ucontext_t *) _p;
72         mcontext_t *_mc = &_uc->uc_mcontext;
73
74         /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
75            different to the ones in <ucontext.h>. */
76
77         void* xpc = (void *) _mc->gregs[REG_RIP];
78
79     // Handle the trap.
80     trap_handle(TRAP_SIGFPE, xpc, _p);
81 }
82
83
84 /**
85  * Signal handler for hardware patcher traps (ud2).
86  */
87 void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
88 {
89         ucontext_t *_uc = (ucontext_t *) _p;
90         mcontext_t *_mc = &_uc->uc_mcontext;
91
92         /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
93            different to the ones in <ucontext.h>. */
94
95         void* xpc = (void *) _mc->gregs[REG_RIP];
96
97     // Handle the trap.
98     trap_handle(TRAP_SIGILL, xpc, _p);
99 }
100
101
102 /* md_signal_handler_sigusr1 ***************************************************
103
104    Signal handler for suspending threads.
105
106 *******************************************************************************/
107
108 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
109 void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
110 {
111         ucontext_t *_uc;
112         mcontext_t *_mc;
113         u1         *pc;
114         u1         *sp;
115
116         _uc = (ucontext_t *) _p;
117         _mc = &_uc->uc_mcontext;
118
119         /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
120            different to the ones in <ucontext.h>. */
121
122         /* get the PC and SP for this thread */
123         pc = (u1 *) _mc->gregs[REG_RIP];
124         sp = (u1 *) _mc->gregs[REG_RSP];
125
126         /* now suspend the current thread */
127         threads_suspend_ack(pc, sp);
128 }
129 #endif
130
131
132 /* md_signal_handler_sigusr2 ***************************************************
133
134    Signal handler for profiling sampling.
135
136 *******************************************************************************/
137
138 #if defined(ENABLE_THREADS)
139 void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
140 {
141         threadobject *t;
142         ucontext_t   *_uc;
143         mcontext_t   *_mc;
144         u1           *pc;
145
146         t = THREADOBJECT;
147
148         _uc = (ucontext_t *) _p;
149         _mc = &_uc->uc_mcontext;
150
151         /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
152            different to the ones in <ucontext.h>. */
153
154         pc = (u1 *) _mc->gregs[REG_RIP];
155
156         t->pc = pc;
157 }
158 #endif
159
160
161 /* md_executionstate_read ******************************************************
162
163    Read the given context into an executionstate.
164
165 *******************************************************************************/
166
167 void md_executionstate_read(executionstate_t *es, void *context)
168 {
169         ucontext_t *_uc;
170         mcontext_t *_mc;
171         s4          i;
172         s4          d;
173
174         _uc = (ucontext_t *) context;
175         _mc = &_uc->uc_mcontext;
176
177         /* read special registers */
178         es->pc = (u1 *) _mc->gregs[REG_RIP];
179         es->sp = (u1 *) _mc->gregs[REG_RSP];
180         es->pv = NULL;
181
182         /* read integer registers */
183         for (i = 0; i < INT_REG_CNT; i++) {
184                 switch (i) {
185                 case 0:  /* REG_RAX */
186                         d = REG_RAX;
187                         break;
188                 case 1:  /* REG_RCX */
189                         d = REG_RCX;
190                         break;
191                 case 2:  /* REG_RDX */
192                         d = REG_RDX;
193                         break;
194                 case 3:  /* REG_RBX */
195                         d = REG_RBX;
196                         break;
197                 case 4:  /* REG_RSP */
198                         d = REG_RSP;
199                         break;
200                 case 5:  /* REG_RBP */
201                         d = REG_RBP;
202                         break;
203                 case 6:  /* REG_RSI */
204                         d = REG_RSI;
205                         break;
206                 case 7:  /* REG_RDI */
207                         d = REG_RDI;
208                         break;
209                 case 8:  /* REG_R8  == 7  */
210                 case 9:  /* REG_R9  == 6  */
211                 case 10: /* REG_R10 == 5  */
212                 case 11: /* REG_R11 == 4  */
213                 case 12: /* REG_R12 == 3  */
214                 case 13: /* REG_R13 == 2  */
215                 case 14: /* REG_R14 == 1  */
216                 case 15: /* REG_R15 == 0  */
217                         d = 15 - i;
218                         break;
219                 }
220
221                 es->intregs[i] = _mc->gregs[d];
222         }
223
224         /* read float registers */
225         for (i = 0; i < FLT_REG_CNT; i++)
226                 es->fltregs[i] = 0xdeadbeefdeadbeefL;
227 }
228
229
230 /* md_executionstate_write *****************************************************
231
232    Write the given executionstate back to the context.
233
234 *******************************************************************************/
235
236 void md_executionstate_write(executionstate_t *es, void *context)
237 {
238         ucontext_t *_uc;
239         mcontext_t *_mc;
240         s4          i;
241         s4          d;
242
243         _uc = (ucontext_t *) context;
244         _mc = &_uc->uc_mcontext;
245
246         /* write integer registers */
247         for (i = 0; i < INT_REG_CNT; i++) {
248                 switch (i) {
249                 case 0:  /* REG_RAX */
250                         d = REG_RAX;
251                         break;
252                 case 1:  /* REG_RCX */
253                         d = REG_RCX;
254                         break;
255                 case 2:  /* REG_RDX */
256                         d = REG_RDX;
257                         break;
258                 case 3:  /* REG_RBX */
259                         d = REG_RBX;
260                         break;
261                 case 4:  /* REG_RSP */
262                         d = REG_RSP;
263                         break;
264                 case 5:  /* REG_RBP */
265                         d = REG_RBP;
266                         break;
267                 case 6:  /* REG_RSI */
268                         d = REG_RSI;
269                         break;
270                 case 7:  /* REG_RDI */
271                         d = REG_RDI;
272                         break;
273                 case 8:  /* REG_R8  == 7  */
274                 case 9:  /* REG_R9  == 6  */
275                 case 10: /* REG_R10 == 5  */
276                 case 11: /* REG_R11 == 4  */
277                 case 12: /* REG_R12 == 3  */
278                 case 13: /* REG_R13 == 2  */
279                 case 14: /* REG_R14 == 1  */
280                 case 15: /* REG_R15 == 0  */
281                         d = 15 - i;
282                         break;
283                 }
284
285                 _mc->gregs[d] = es->intregs[i];
286         }
287
288         /* write special registers */
289         _mc->gregs[REG_RIP] = (ptrint) es->pc;
290         _mc->gregs[REG_RSP] = (ptrint) es->sp;
291 }
292
293
294 /*
295  * These are local overrides for various environment variables in Emacs.
296  * Please do not remove this and leave it at the end of the file, where
297  * Emacs will automagically detect them.
298  * ---------------------------------------------------------------------
299  * Local variables:
300  * mode: c
301  * indent-tabs-mode: t
302  * c-basic-offset: 4
303  * tab-width: 4
304  * End:
305  * vim:noexpandtab:sw=4:ts=4:
306  */