OSDN Git Service

2008-07-06 Kai Tietz <kai.tietz@onevision.com>
[pf3gnuchains/gcc-fork.git] / libjava / include / s390-signal.h
1 // s390-signal.h - Catch runtime signals and turn them into exceptions
2 // on an s390 based Linux system.
3
4 /* Copyright (C) 2002  Free Software Foundation
5
6    This file is part of libgcj.
7
8 This software is copyrighted work licensed under the terms of the
9 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
10 details.  */
11
12
13 #ifndef JAVA_SIGNAL_H
14 #define JAVA_SIGNAL_H 1
15
16 #include <signal.h>
17 #include <sys/syscall.h>
18 #include <ucontext.h>
19 #include <limits.h>
20
21 #define HANDLE_SEGV 1
22 #define HANDLE_FPE 1
23
24 #define SIGNAL_HANDLER(_name)   \
25 static void _name (int, siginfo_t *_si __attribute__((unused)), \
26                    ucontext_t *_uc __attribute__((unused)))
27
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)
31
32
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.  */
42
43 #define HANDLE_DIVIDE_OVERFLOW                                          \
44 do                                                                      \
45 {                                                                       \
46   unsigned char *_eip = (unsigned char *)                               \
47     __builtin_extract_return_addr (_si->si_addr);                       \
48   unsigned long *_regs = _uc->uc_mcontext.gregs;                        \
49   int _r1, _r2, _d2, _x2, _b2;                                          \
50                                                                         \
51   /* First, a couple of helper routines to decode instructions.  */     \
52   struct _decode                                                        \
53     {                                                                   \
54       /* Decode RR instruction format.  */                              \
55       static inline int _is_rr (unsigned char *_eip,                    \
56                                 unsigned char _op,                      \
57                                 int *_r1, int *_r2)                     \
58       {                                                                 \
59         if (_eip[0] == _op)                                             \
60           {                                                             \
61             *_r1 = _eip[1] >> 4;                                        \
62             *_r2 = _eip[1] & 0xf;                                       \
63             return 1;                                                   \
64           }                                                             \
65         return 0;                                                       \
66       }                                                                 \
67                                                                         \
68       /* Decode RX instruction format.  */                              \
69       static inline int _is_rx (unsigned char *_eip,                    \
70                                 unsigned char _op,                      \
71                                 int *_r1, int *_d2, int *_x2, int *_b2) \
72       {                                                                 \
73         if (_eip[0] == _op)                                             \
74           {                                                             \
75             *_r1 = _eip[1] >> 4;                                        \
76             *_x2 = _eip[1] & 0xf;                                       \
77             *_b2 = _eip[2] >> 4;                                        \
78             *_d2 = ((_eip[2] & 0xf) << 8) + _eip[3];                    \
79             return 1;                                                   \
80           }                                                             \
81         return 0;                                                       \
82       }                                                                 \
83                                                                         \
84       /* Decode RRE instruction format.  */                             \
85       static inline int _is_rre (unsigned char *_eip,                   \
86                                  unsigned char _op1, unsigned char _op2,\
87                                  int *_r1, int *_r2)                    \
88       {                                                                 \
89         if (_eip[0] == _op1 && _eip[1] == _op2)                         \
90           {                                                             \
91             *_r1 = _eip[3] >> 4;                                        \
92             *_r2 = _eip[3] & 0xf;                                       \
93             return 1;                                                   \
94           }                                                             \
95         return 0;                                                       \
96       }                                                                 \
97                                                                         \
98       /* Decode RXY instruction format.  */                             \
99       static inline int _is_rxy (unsigned char *_eip,                   \
100                                  unsigned char _op1, unsigned char _op2,\
101                                  int *_r1, int *_d2, int *_x2, int *_b2)\
102       {                                                                 \
103         if (_eip[0] == _op1 && _eip[5] == _op2)                         \
104           {                                                             \
105             *_r1 = _eip[1] >> 4;                                        \
106             *_x2 = _eip[1] & 0xf;                                       \
107             *_b2 = _eip[2] >> 4;                                        \
108             *_d2 = ((_eip[2] & 0xf) << 8) + _eip[3] + (_eip[4] << 12);  \
109             /* We have a 20-bit signed displacement.  */                \
110             *_d2 = (*_d2 ^ 0x80000) - 0x80000;                          \
111             return 1;                                                   \
112           }                                                             \
113         return 0;                                                       \
114       }                                                                 \
115                                                                         \
116       /* Compute effective address.  */                                 \
117       static inline unsigned long _eff (unsigned long *_regs,           \
118                                         long _d, int _x, int _b)        \
119       {                                                                 \
120         return _d + (_x? _regs[_x] : 0) + (_b? _regs[_b] : 0);          \
121       }                                                                 \
122     };                                                                  \
123                                                                         \
124                                                                         \
125   /* DR r1,r2 */                                                        \
126   if (_decode::_is_rr (_eip, 0x1d, &_r1, &_r2)                          \
127       && (int) _regs[_r1] == -1 && (int) _regs[_r1+1] == INT_MIN        \
128       && (int) _regs[_r2] == -1)                                        \
129     {                                                                   \
130       _regs[_r1] &= ~0xffffffff;                                        \
131       return;                                                           \
132     }                                                                   \
133                                                                         \
134   /* D r1,d2(x2,b2) */                                                  \
135   if (_decode::_is_rx (_eip, 0x5d, &_r1, &_d2, &_x2, &_b2)              \
136       && (int) _regs[_r1] == -1 && (int) _regs[_r1+1] == INT_MIN        \
137       && *(int *) _decode::_eff (_regs, _d2, _x2, _b2) == -1)           \
138     {                                                                   \
139       _regs[_r1] &= ~0xffffffff;                                        \
140       return;                                                           \
141     }                                                                   \
142                                                                         \
143   /* DSGR r1,r2 */                                                      \
144   if (_decode::_is_rre (_eip, 0xb9, 0x0d, &_r1, &_r2)                   \
145       && (long) _regs[_r1+1] == LONG_MIN                                \
146       && (long) _regs[_r2] == -1L)                                      \
147     {                                                                   \
148       _regs[_r1] = 0;                                                   \
149       return;                                                           \
150     }                                                                   \
151                                                                         \
152   /* DSGFR r1,r2 */                                                     \
153   if (_decode::_is_rre (_eip, 0xb9, 0x1d, &_r1, &_r2)                   \
154       && (long) _regs[_r1+1] == LONG_MIN                                \
155       && (int) _regs[_r2] == -1)                                        \
156     {                                                                   \
157       _regs[_r1] = 0;                                                   \
158       return;                                                           \
159     }                                                                   \
160                                                                         \
161   /* DSG r1,d2(x2,b2) */                                                \
162   if (_decode::_is_rxy (_eip, 0xe3, 0x0d, &_r1, &_d2, &_x2, &_b2)       \
163       && (long) _regs[_r1+1] == LONG_MIN                                \
164       && *(long *) _decode::_eff (_regs, _d2, _x2, _b2) == -1L)         \
165     {                                                                   \
166       _regs[_r1] = 0;                                                   \
167       return;                                                           \
168     }                                                                   \
169                                                                         \
170   /* DSGF r1,d2(x2,b2) */                                               \
171   if (_decode::_is_rxy (_eip, 0xe3, 0x1d, &_r1, &_d2, &_x2, &_b2)       \
172       && (long) _regs[_r1+1] == LONG_MIN                                \
173       && *(int *) _decode::_eff (_regs, _d2, _x2, _b2) == -1)           \
174     {                                                                   \
175       _regs[_r1] = 0;                                                   \
176       return;                                                           \
177     }                                                                   \
178                                                                         \
179 }                                                                       \
180 while (0)
181
182 /* For an explanation why we cannot simply use sigaction to
183    install the handlers, see i386-signal.h.  */
184
185 /* We use old_kernel_sigaction here because we're calling the kernel
186    directly rather than via glibc.  The sigaction structure that the
187    syscall uses is a different shape from the one in userland and not
188    visible to us in a header file so we define it here.  */
189
190 struct old_s390_kernel_sigaction {
191         void (*k_sa_handler) (int, siginfo_t *, ucontext_t *);
192         unsigned long k_sa_mask;
193         unsigned long k_sa_flags;
194         void (*sa_restorer) (void);
195 };
196
197 #define INIT_SEGV                                       \
198 do                                                      \
199   {                                                     \
200     struct old_s390_kernel_sigaction kact;              \
201     kact.k_sa_handler = catch_segv;                     \
202     kact.k_sa_mask = 0;                                 \
203     kact.k_sa_flags = SA_SIGINFO;                       \
204     syscall (SYS_sigaction, SIGSEGV, &kact, NULL);      \
205   }                                                     \
206 while (0)  
207
208 #define INIT_FPE                                                \
209 do                                                              \
210   {                                                             \
211     struct old_s390_kernel_sigaction kact;                      \
212     kact.k_sa_handler = catch_fpe;                              \
213     kact.k_sa_mask = 0;                                         \
214     kact.k_sa_flags = SA_SIGINFO;                               \
215     syscall (SYS_sigaction, SIGFPE, &kact, NULL);               \
216   }                                                             \
217 while (0)  
218
219 #endif /* JAVA_SIGNAL_H */
220