All files: Updated copyright information.
[gcc.git] / libjava / include / i386-signal.h
1 // i386-signal.h - Catch runtime signals and turn them into exceptions.
2
3 /* Copyright (C) 1998, 1999 Free Software Foundation
4
5 This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
10
11 /* This technique should work for all i386 based Unices which conform
12 * to iBCS2. This includes all versions of Linux more recent than 1.3
13 */
14
15
16 #ifndef JAVA_SIGNAL_H
17 #define JAVA_SIGNAL_H 1
18
19 #include <signal.h>
20
21 #define HANDLE_SEGV 1
22 #define HANDLE_FPE 1
23
24 #define SIGNAL_HANDLER(_name) \
25 static void _name (int _dummy)
26
27 #define MAKE_THROW_FRAME \
28 do \
29 { \
30 void **_p = (void **)&_dummy; \
31 struct sigcontext_struct *_regs = (struct sigcontext_struct *)++_p; \
32 \
33 register unsigned long _ebp = _regs->ebp; \
34 register unsigned char *_eip = (unsigned char *)_regs->eip; \
35 \
36 /* Advance the program counter so that it is after the start of the \
37 instruction: the x86 exception handler expects \
38 the PC to point to the instruction after a call. */ \
39 _eip += 2; \
40 \
41 asm volatile ("mov %0, (%%ebp); mov %1, 4(%%ebp)" \
42 : : "r"(_ebp), "r"(_eip)); \
43 } \
44 while (0)
45
46 #define HANDLE_DIVIDE_OVERFLOW \
47 do \
48 { \
49 void **_p = (void **)&_dummy; \
50 struct sigcontext_struct *_regs = (struct sigcontext_struct *)++_p; \
51 \
52 register unsigned long *_ebp = (unsigned long *)_regs->ebp; \
53 register unsigned char *_eip = (unsigned char *)_regs->eip; \
54 \
55 /* According to the JVM spec, "if the dividend is the negative \
56 * integer of the smallest magnitude and the divisor is -1, then \
57 * overflow occurs and the result is equal to the dividend. Despite \
58 * the overflow, no exception occurs". \
59 \
60 * We handle this by inspecting the instruction which generated the \
61 * signal and advancing eip to point to the following instruction. \
62 * As the instructions are variable length it is necessary to do a \
63 * little calculation to figure out where the following instruction \
64 * actually is. \
65 \
66 */ \
67 \
68 if (_eip[0] == 0xf7) \
69 { \
70 unsigned char _modrm = _eip[1]; \
71 \
72 if (_regs->eax == 0x80000000 \
73 && ((_modrm >> 3) & 7) == 7) /* Signed divide */ \
74 { \
75 _regs->edx = 0; /* the remainder is zero */ \
76 switch (_modrm >> 6) \
77 { \
78 case 0: \
79 if ((_modrm & 7) == 5) \
80 _eip += 4; \
81 break; \
82 case 1: \
83 _eip += 1; \
84 break; \
85 case 2: \
86 _eip += 4; \
87 break; \
88 case 3: \
89 break; \
90 } \
91 _eip += 2; \
92 _regs->eip = (unsigned long)_eip; \
93 return; \
94 } \
95 else if (((_modrm >> 3) & 7) == 6) /* Unsigned divide */ \
96 { \
97 /* We assume that unsigned divisions are in library code, so \
98 * we throw one level down the stack, which was hopefully \
99 * the place that called the library routine. This will \
100 * break if the library is ever compiled with \
101 * -fomit-frame-pointer, but at least this way we've got a \
102 * good chance of finding the exception handler. */ \
103 \
104 _eip = (unsigned char *)_ebp[1]; \
105 _ebp = (unsigned long *)_ebp[0]; \
106 } \
107 else \
108 { \
109 /* Advance the program counter so that it is after the start \
110 of the instruction: this is because the x86 exception \
111 handler expects the PC to point to the instruction after a \
112 call. */ \
113 _eip += 2; \
114 } \
115 } \
116 \
117 asm volatile ("mov %0, (%%ebp); mov %1, 4(%%ebp)" \
118 : : "r"(_ebp), "r"(_eip)); \
119 } \
120 while (0)
121
122 #define INIT_SEGV \
123 do \
124 { \
125 nullp = new java::lang::NullPointerException (); \
126 struct sigaction act; \
127 act.sa_handler = catch_segv; \
128 sigemptyset (&act.sa_mask); \
129 act.sa_flags = 0; \
130 __sigaction (SIGSEGV, &act, NULL); \
131 } \
132 while (0)
133
134 #define INIT_FPE \
135 do \
136 { \
137 arithexception = new java::lang::ArithmeticException \
138 (JvNewStringLatin1 ("/ by zero")); \
139 struct sigaction act; \
140 act.sa_handler = catch_fpe; \
141 sigemptyset (&act.sa_mask); \
142 act.sa_flags = 0; \
143 __sigaction (SIGFPE, &act, NULL); \
144 } \
145 while (0)
146
147 #endif /* JAVA_SIGNAL_H */
148