merged volatile memory barriers
[cacao.git] / src / vm / jit / x86_64 / linux / md-os.c
1 /* src/vm/jit/x86_64/linux/md-os.c - machine dependent x86_64 Linux functions
2
3    Copyright (C) 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 #define _GNU_SOURCE
27
28 #include "config.h"
29
30 #include <assert.h>
31 #include <stdint.h>
32 #include <stdlib.h>
33 #include <ucontext.h>
34
35 #include "vm/types.h"
36
37 #include "vm/jit/x86_64/codegen.h"
38 #include "vm/jit/x86_64/md.h"
39
40 #include "threads/thread.hpp"
41
42 #include "vm/signallocal.hpp"
43
44 #include "vm/jit/asmpart.h"
45 #include "vm/jit/executionstate.h"
46 #include "vm/jit/trap.hpp"
47
48
49 /**
50  * Signal handler for hardware exception.
51  */
52 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
53 {
54         ucontext_t* _uc = (ucontext_t *) _p;
55         mcontext_t* _mc = &_uc->uc_mcontext;
56
57         /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
58            different to the ones in <ucontext.h>. */
59
60         void* xpc = (void*) _mc->gregs[REG_RIP];
61
62         // Handle the trap.
63         trap_handle(TRAP_SIGSEGV, xpc, _p);
64 }
65
66
67 /**
68  * ArithmeticException signal handler for hardware divide by zero
69  * check.
70  */
71 void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
72 {
73         ucontext_t* _uc = (ucontext_t *) _p;
74         mcontext_t* _mc = &_uc->uc_mcontext;
75
76         /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
77            different to the ones in <ucontext.h>. */
78
79         void* xpc = (void*) _mc->gregs[REG_RIP];
80
81         // Handle the trap.
82         trap_handle(TRAP_SIGFPE, xpc, _p);
83 }
84
85
86 /**
87  * Signal handler for patchers.
88  */
89 void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
90 {
91         ucontext_t* _uc = (ucontext_t *) _p;
92         mcontext_t* _mc = &_uc->uc_mcontext;
93
94         /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
95            different to the ones in <ucontext.h>. */
96
97         void* xpc = (void*) _mc->gregs[REG_RIP];
98
99         // Handle the trap.
100         trap_handle(TRAP_SIGILL, xpc, _p);
101 }
102
103
104 /* md_signal_handler_sigusr2 ***************************************************
105
106    Signal handler for profiling sampling.
107
108 *******************************************************************************/
109
110 #if defined(ENABLE_THREADS)
111 void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
112 {
113         threadobject *t;
114         ucontext_t   *_uc;
115         mcontext_t   *_mc;
116         u1           *pc;
117
118         t = THREADOBJECT;
119
120         _uc = (ucontext_t *) _p;
121         _mc = &_uc->uc_mcontext;
122
123         /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
124            different to the ones in <ucontext.h>. */
125
126         pc = (u1 *) _mc->gregs[REG_RIP];
127
128         t->pc = pc;
129 }
130 #endif
131
132
133 /* md_executionstate_read ******************************************************
134
135    Read the given context into an executionstate.
136
137 *******************************************************************************/
138
139 void md_executionstate_read(executionstate_t *es, void *context)
140 {
141         ucontext_t *_uc;
142         mcontext_t *_mc;
143         s4          i;
144         s4          d;
145
146         _uc = (ucontext_t *) context;
147         _mc = &_uc->uc_mcontext;
148
149         /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
150            different to the ones in <ucontext.h>. */
151
152         /* read special registers */
153         es->pc = (u1 *) _mc->gregs[REG_RIP];
154         es->sp = (u1 *) _mc->gregs[REG_RSP];
155         es->pv = NULL;
156
157         /* read integer registers */
158         for (i = 0; i < INT_REG_CNT; i++) {
159                 /* XXX FIX ME! */
160
161                 switch (i) {
162                 case 0:  /* REG_RAX == 13 */
163                         d = REG_RAX;
164                         break;
165                 case 1:  /* REG_RCX == 14 */
166                         d = REG_RCX;
167                         break;
168                 case 2:  /* REG_RDX == 12 */
169                         d = REG_RDX;
170                         break;
171                 case 3:  /* REG_RBX == 11 */
172                         d = REG_RBX;
173                         break;
174                 case 4:  /* REG_RSP == 15 */
175                         d = REG_RSP;
176                         break;
177                 case 5:  /* REG_RBP == 10 */
178                         d = REG_RBP;
179                         break;
180                 case 6:  /* REG_RSI == 9  */
181                         d = REG_RSI;
182                         break;
183                 case 7:  /* REG_RDI == 8  */
184                         d = REG_RDI;
185                         break;
186                 case 8:  /* REG_R8  == 0  */
187                 case 9:  /* REG_R9  == 1  */
188                 case 10: /* REG_R10 == 2  */
189                 case 11: /* REG_R11 == 3  */
190                 case 12: /* REG_R12 == 4  */
191                 case 13: /* REG_R13 == 5  */
192                 case 14: /* REG_R14 == 6  */
193                 case 15: /* REG_R15 == 7  */
194                         d = i - 8;
195                         break;
196                 }
197
198                 es->intregs[i] = _mc->gregs[d];
199         }
200
201         /* read float registers */
202         for (i = 0; i < FLT_REG_CNT; i++)
203                 es->fltregs[i] = 0xdeadbeefdeadbeefL;
204 }
205
206
207 /* md_executionstate_write *****************************************************
208
209    Write the given executionstate back to the context.
210
211 *******************************************************************************/
212
213 void md_executionstate_write(executionstate_t *es, void *context)
214 {
215         ucontext_t *_uc;
216         mcontext_t *_mc;
217         s4          i;
218         s4          d;
219
220         _uc = (ucontext_t *) context;
221         _mc = &_uc->uc_mcontext;
222
223         /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
224            different to the ones in <ucontext.h>. */
225
226         /* write integer registers */
227         for (i = 0; i < INT_REG_CNT; i++) {
228                 /* XXX FIX ME! */
229
230                 switch (i) {
231                 case 0:  /* REG_RAX == 13 */
232                         d = REG_RAX;
233                         break;
234                 case 1:  /* REG_RCX == 14 */
235                         d = REG_RCX;
236                         break;
237                 case 2:  /* REG_RDX == 12 */
238                         d = REG_RDX;
239                         break;
240                 case 3:  /* REG_RBX == 11 */
241                         d = REG_RBX;
242                         break;
243                 case 4:  /* REG_RSP == 15 */
244                         d = REG_RSP;
245                         break;
246                 case 5:  /* REG_RBP == 10 */
247                         d = REG_RBP;
248                         break;
249                 case 6:  /* REG_RSI == 9  */
250                         d = REG_RSI;
251                         break;
252                 case 7:  /* REG_RDI == 8  */
253                         d = REG_RDI;
254                         break;
255                 case 8:  /* REG_R8  == 0  */
256                 case 9:  /* REG_R9  == 1  */
257                 case 10: /* REG_R10 == 2  */
258                 case 11: /* REG_R11 == 3  */
259                 case 12: /* REG_R12 == 4  */
260                 case 13: /* REG_R13 == 5  */
261                 case 14: /* REG_R14 == 6  */
262                 case 15: /* REG_R15 == 7  */
263                         d = i - 8;
264                         break;
265                 }
266
267                 _mc->gregs[d] = es->intregs[i];
268         }
269
270         /* write special registers */
271         _mc->gregs[REG_RIP] = (ptrint) es->pc;
272         _mc->gregs[REG_RSP] = (ptrint) es->sp;
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  * vim:noexpandtab:sw=4:ts=4:
288  */