]> gcc.gnu.org Git - gcc.git/blame - libjava/include/s390-signal.h
Update Copyright years for files modified in 2010.
[gcc.git] / libjava / include / s390-signal.h
CommitLineData
e793a714
UW
1// s390-signal.h - Catch runtime signals and turn them into exceptions
2// on an s390 based Linux system.
3
d652f226 4/* Copyright (C) 2002, 2010 Free Software Foundation
e793a714
UW
5
6 This file is part of libgcj.
7
8This software is copyrighted work licensed under the terms of the
9Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
10details. */
11
12
13#ifndef JAVA_SIGNAL_H
14#define JAVA_SIGNAL_H 1
15
16#include <signal.h>
17#include <sys/syscall.h>
220a826e
UW
18#include <ucontext.h>
19#include <limits.h>
e793a714
UW
20
21#define HANDLE_SEGV 1
220a826e 22#define HANDLE_FPE 1
e793a714
UW
23
24#define SIGNAL_HANDLER(_name) \
220a826e
UW
25static void _name (int, siginfo_t *_si __attribute__((unused)), \
26 ucontext_t *_uc __attribute__((unused)))
e793a714 27
bbb362e6
UW
28/* We no longer need to fiddle with the PSW address in the signal handler;
29 this is now all handled correctly in MD_FALLBACK_FRAME_STATE_FOR. */
30#define MAKE_THROW_FRAME(_exception)
e793a714
UW
31
32
220a826e
UW
33/* According to the JVM spec, "if the dividend is the negative integer
34 of the smallest magnitude and the divisor is -1, then overflow occurs
35 and the result is equal to the dividend. Despite the overflow, no
36 exception occurs".
37
38 We handle this by inspecting the instruction which generated the signal,
39 and if dividend and divisor are as above, we simply return from the signal
40 handler. This causes execution to continue after the instruction.
41 Before returning, we the set result registers as expected. */
9602b6a1 42#define UC_EXTENDED 0x00000001
220a826e
UW
43
44#define HANDLE_DIVIDE_OVERFLOW \
45do \
46{ \
47 unsigned char *_eip = (unsigned char *) \
48 __builtin_extract_return_addr (_si->si_addr); \
49 unsigned long *_regs = _uc->uc_mcontext.gregs; \
50 int _r1, _r2, _d2, _x2, _b2; \
9602b6a1
AK
51 struct \
52 { \
53 unsigned long int uc_flags; \
54 struct ucontext *uc_link; \
55 stack_t uc_stack; \
56 mcontext_t uc_mcontext; \
57 unsigned long sigmask[2]; \
58 unsigned long ext_regs[16]; \
59 } *_uc_ext = (typeof(_uc_ext))_uc; \
220a826e
UW
60 \
61 /* First, a couple of helper routines to decode instructions. */ \
62 struct _decode \
63 { \
64 /* Decode RR instruction format. */ \
65 static inline int _is_rr (unsigned char *_eip, \
66 unsigned char _op, \
67 int *_r1, int *_r2) \
68 { \
69 if (_eip[0] == _op) \
70 { \
71 *_r1 = _eip[1] >> 4; \
72 *_r2 = _eip[1] & 0xf; \
73 return 1; \
74 } \
75 return 0; \
76 } \
77 \
78 /* Decode RX instruction format. */ \
79 static inline int _is_rx (unsigned char *_eip, \
80 unsigned char _op, \
81 int *_r1, int *_d2, int *_x2, int *_b2) \
82 { \
83 if (_eip[0] == _op) \
84 { \
85 *_r1 = _eip[1] >> 4; \
86 *_x2 = _eip[1] & 0xf; \
87 *_b2 = _eip[2] >> 4; \
88 *_d2 = ((_eip[2] & 0xf) << 8) + _eip[3]; \
89 return 1; \
90 } \
91 return 0; \
92 } \
93 \
94 /* Decode RRE instruction format. */ \
95 static inline int _is_rre (unsigned char *_eip, \
96 unsigned char _op1, unsigned char _op2,\
97 int *_r1, int *_r2) \
98 { \
99 if (_eip[0] == _op1 && _eip[1] == _op2) \
100 { \
101 *_r1 = _eip[3] >> 4; \
102 *_r2 = _eip[3] & 0xf; \
103 return 1; \
104 } \
105 return 0; \
106 } \
107 \
108 /* Decode RXY instruction format. */ \
109 static inline int _is_rxy (unsigned char *_eip, \
110 unsigned char _op1, unsigned char _op2,\
111 int *_r1, int *_d2, int *_x2, int *_b2)\
112 { \
113 if (_eip[0] == _op1 && _eip[5] == _op2) \
114 { \
115 *_r1 = _eip[1] >> 4; \
116 *_x2 = _eip[1] & 0xf; \
117 *_b2 = _eip[2] >> 4; \
118 *_d2 = ((_eip[2] & 0xf) << 8) + _eip[3] + (_eip[4] << 12); \
119 /* We have a 20-bit signed displacement. */ \
120 *_d2 = (*_d2 ^ 0x80000) - 0x80000; \
121 return 1; \
122 } \
123 return 0; \
124 } \
125 \
126 /* Compute effective address. */ \
127 static inline unsigned long _eff (unsigned long *_regs, \
128 long _d, int _x, int _b) \
129 { \
130 return _d + (_x? _regs[_x] : 0) + (_b? _regs[_b] : 0); \
131 } \
220a826e 132 \
9602b6a1
AK
133 static inline int is_long_long_min_p (unsigned long *_regs, \
134 unsigned long *_ext_regs, \
135 int _r) \
136 { \
137 return ((long long)_regs[_r] \
138 | (long long)_ext_regs[_r] << 32) == \
139 LONG_LONG_MIN; \
140 } \
141 }; \
220a826e
UW
142 \
143 /* DR r1,r2 */ \
144 if (_decode::_is_rr (_eip, 0x1d, &_r1, &_r2) \
145 && (int) _regs[_r1] == -1 && (int) _regs[_r1+1] == INT_MIN \
146 && (int) _regs[_r2] == -1) \
147 { \
148 _regs[_r1] &= ~0xffffffff; \
149 return; \
150 } \
151 \
152 /* D r1,d2(x2,b2) */ \
153 if (_decode::_is_rx (_eip, 0x5d, &_r1, &_d2, &_x2, &_b2) \
154 && (int) _regs[_r1] == -1 && (int) _regs[_r1+1] == INT_MIN \
155 && *(int *) _decode::_eff (_regs, _d2, _x2, _b2) == -1) \
156 { \
157 _regs[_r1] &= ~0xffffffff; \
158 return; \
159 } \
160 \
161 /* DSGR r1,r2 */ \
162 if (_decode::_is_rre (_eip, 0xb9, 0x0d, &_r1, &_r2) \
163 && (long) _regs[_r1+1] == LONG_MIN \
164 && (long) _regs[_r2] == -1L) \
165 { \
166 _regs[_r1] = 0; \
167 return; \
168 } \
169 \
170 /* DSGFR r1,r2 */ \
171 if (_decode::_is_rre (_eip, 0xb9, 0x1d, &_r1, &_r2) \
172 && (long) _regs[_r1+1] == LONG_MIN \
173 && (int) _regs[_r2] == -1) \
174 { \
175 _regs[_r1] = 0; \
176 return; \
177 } \
178 \
179 /* DSG r1,d2(x2,b2) */ \
180 if (_decode::_is_rxy (_eip, 0xe3, 0x0d, &_r1, &_d2, &_x2, &_b2) \
181 && (long) _regs[_r1+1] == LONG_MIN \
182 && *(long *) _decode::_eff (_regs, _d2, _x2, _b2) == -1L) \
183 { \
184 _regs[_r1] = 0; \
185 return; \
186 } \
187 \
188 /* DSGF r1,d2(x2,b2) */ \
189 if (_decode::_is_rxy (_eip, 0xe3, 0x1d, &_r1, &_d2, &_x2, &_b2) \
190 && (long) _regs[_r1+1] == LONG_MIN \
191 && *(int *) _decode::_eff (_regs, _d2, _x2, _b2) == -1) \
192 { \
193 _regs[_r1] = 0; \
194 return; \
195 } \
9602b6a1
AK
196 \
197 /* The extended ucontext contains the upper halfs of the 64bit \
198 registers in 31bit applications. */ \
199 if (_uc->uc_flags & 1 == 1) \
200 { \
201 /* DSGR r1,r2 */ \
202 if (_decode::_is_rre (_eip, 0xb9, 0x0d, &_r1, &_r2) \
203 && (int) _regs[_r2] == -1 \
204 && (int) _uc_ext->ext_regs[_r2] == -1 \
205 && _decode::is_long_long_min_p (_regs, _uc_ext->ext_regs, \
206 _r1 + 1)) \
207 { \
208 _regs[_r1] = 0; \
209 _uc_ext->ext_regs[_r1] = 0; \
210 return; \
211 } \
212 \
213 /* DSGFR r1,r2 */ \
214 if (_decode::_is_rre (_eip, 0xb9, 0x1d, &_r1, &_r2) \
215 && (int) _regs[_r2] == -1 \
216 && _decode::is_long_long_min_p (_regs, _uc_ext->ext_regs, \
217 _r1 + 1)) \
218 { \
219 _regs[_r1] = 0; \
220 _uc_ext->ext_regs[_r1] = 0; \
221 return; \
222 } \
223 \
224 /* DSG r1,d2(x2,b2) */ \
225 if (_decode::_is_rxy (_eip, 0xe3, 0x0d, &_r1, &_d2, &_x2, &_b2) \
226 && *(int *) _decode::_eff (_regs, _d2, _x2, _b2) == -1 \
227 && *(int *) _decode::_eff (_regs, _d2 + 4, _x2, _b2) == -1 \
228 && _decode::is_long_long_min_p (_regs, _uc_ext->ext_regs, \
229 _r1 + 1)) \
230 { \
231 _regs[_r1] = 0; \
232 _uc_ext->ext_regs[_r1] = 0; \
233 return; \
234 } \
235 \
236 /* DSGF r1,d2(x2,b2) */ \
237 if (_decode::_is_rxy (_eip, 0xe3, 0x1d, &_r1, &_d2, &_x2, &_b2) \
238 && *(int *) _decode::_eff (_regs, _d2, _x2, _b2) == -1 \
239 && _decode::is_long_long_min_p (_regs, _uc_ext->ext_regs, \
240 _r1 + 1)) \
241 { \
242 _regs[_r1] = 0; \
243 _uc_ext->ext_regs[_r1] = 0; \
244 return; \
245 } \
246 } \
247 } \
220a826e
UW
248while (0)
249
e793a714
UW
250/* For an explanation why we cannot simply use sigaction to
251 install the handlers, see i386-signal.h. */
252
253/* We use old_kernel_sigaction here because we're calling the kernel
254 directly rather than via glibc. The sigaction structure that the
255 syscall uses is a different shape from the one in userland and not
256 visible to us in a header file so we define it here. */
257
258struct old_s390_kernel_sigaction {
220a826e 259 void (*k_sa_handler) (int, siginfo_t *, ucontext_t *);
e793a714
UW
260 unsigned long k_sa_mask;
261 unsigned long k_sa_flags;
262 void (*sa_restorer) (void);
263};
264
265#define INIT_SEGV \
266do \
267 { \
e793a714
UW
268 struct old_s390_kernel_sigaction kact; \
269 kact.k_sa_handler = catch_segv; \
270 kact.k_sa_mask = 0; \
bbb362e6 271 kact.k_sa_flags = SA_SIGINFO; \
e793a714
UW
272 syscall (SYS_sigaction, SIGSEGV, &kact, NULL); \
273 } \
274while (0)
275
276#define INIT_FPE \
277do \
278 { \
e793a714
UW
279 struct old_s390_kernel_sigaction kact; \
280 kact.k_sa_handler = catch_fpe; \
281 kact.k_sa_mask = 0; \
bbb362e6 282 kact.k_sa_flags = SA_SIGINFO; \
e793a714
UW
283 syscall (SYS_sigaction, SIGFPE, &kact, NULL); \
284 } \
285while (0)
286
287#endif /* JAVA_SIGNAL_H */
288
This page took 0.77751 seconds and 5 git commands to generate.