1 // s390-signal.h - Catch runtime signals and turn them into exceptions
2 // on an s390 based Linux system.
4 /* Copyright (C) 2002, 2010 Free Software Foundation
6 This file is part of libgcj.
8 This software is copyrighted work licensed under the terms of the
9 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
14 #define JAVA_SIGNAL_H 1
17 #include <sys/syscall.h>
24 #define SIGNAL_HANDLER(_name) \
25 static void _name (int, siginfo_t *_si __attribute__((unused)), \
26 ucontext_t *_uc __attribute__((unused)))
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)
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
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. */
42 #define UC_EXTENDED 0x00000001
44 #define HANDLE_DIVIDE_OVERFLOW \
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; \
53 unsigned long int uc_flags; \
54 struct ucontext *uc_link; \
56 mcontext_t uc_mcontext; \
57 unsigned long sigmask[2]; \
58 unsigned long ext_regs[16]; \
59 } *_uc_ext = (typeof(_uc_ext))_uc; \
61 /* First, a couple of helper routines to decode instructions. */ \
64 /* Decode RR instruction format. */ \
65 static inline int _is_rr (unsigned char *_eip, \
71 *_r1 = _eip[1] >> 4; \
72 *_r2 = _eip[1] & 0xf; \
78 /* Decode RX instruction format. */ \
79 static inline int _is_rx (unsigned char *_eip, \
81 int *_r1, int *_d2, int *_x2, int *_b2) \
85 *_r1 = _eip[1] >> 4; \
86 *_x2 = _eip[1] & 0xf; \
87 *_b2 = _eip[2] >> 4; \
88 *_d2 = ((_eip[2] & 0xf) << 8) + _eip[3]; \
94 /* Decode RRE instruction format. */ \
95 static inline int _is_rre (unsigned char *_eip, \
96 unsigned char _op1, unsigned char _op2,\
99 if (_eip[0] == _op1 && _eip[1] == _op2) \
101 *_r1 = _eip[3] >> 4; \
102 *_r2 = _eip[3] & 0xf; \
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)\
113 if (_eip[0] == _op1 && _eip[5] == _op2) \
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; \
126 /* Compute effective address. */ \
127 static inline unsigned long _eff (unsigned long *_regs, \
128 long _d, int _x, int _b) \
130 return _d + (_x? _regs[_x] : 0) + (_b? _regs[_b] : 0); \
133 static inline int is_long_long_min_p (unsigned long *_regs, \
134 unsigned long *_ext_regs, \
137 return ((long long)_regs[_r] \
138 | (long long)_ext_regs[_r] << 32) == \
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) \
148 _regs[_r1] &= ~0xffffffff; \
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) \
157 _regs[_r1] &= ~0xffffffff; \
162 if (_decode::_is_rre (_eip, 0xb9, 0x0d, &_r1, &_r2) \
163 && (long) _regs[_r1+1] == LONG_MIN \
164 && (long) _regs[_r2] == -1L) \
171 if (_decode::_is_rre (_eip, 0xb9, 0x1d, &_r1, &_r2) \
172 && (long) _regs[_r1+1] == LONG_MIN \
173 && (int) _regs[_r2] == -1) \
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) \
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) \
197 /* The extended ucontext contains the upper halfs of the 64bit \
198 registers in 31bit applications. */ \
199 if (_uc->uc_flags & 1 == 1) \
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, \
209 _uc_ext->ext_regs[_r1] = 0; \
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, \
220 _uc_ext->ext_regs[_r1] = 0; \
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, \
232 _uc_ext->ext_regs[_r1] = 0; \
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, \
243 _uc_ext->ext_regs[_r1] = 0; \
250 /* For an explanation why we cannot simply use sigaction to
251 install the handlers, see i386-signal.h. */
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. */
258 struct old_s390_kernel_sigaction
{
259 void (*k_sa_handler
) (int, siginfo_t
*, ucontext_t
*);
260 unsigned long k_sa_mask
;
261 unsigned long k_sa_flags
;
262 void (*sa_restorer
) (void);
268 struct old_s390_kernel_sigaction kact; \
269 kact.k_sa_handler = catch_segv; \
270 kact.k_sa_mask = 0; \
271 kact.k_sa_flags = SA_SIGINFO; \
272 syscall (SYS_sigaction, SIGSEGV, &kact, NULL); \
279 struct old_s390_kernel_sigaction kact; \
280 kact.k_sa_handler = catch_fpe; \
281 kact.k_sa_mask = 0; \
282 kact.k_sa_flags = SA_SIGINFO; \
283 syscall (SYS_sigaction, SIGFPE, &kact, NULL); \
287 #endif /* JAVA_SIGNAL_H */