* elfos.h (const_section): Output a tab before assembler directives.
[official-gcc.git] / libjava / include / i386-signal.h
blob12ffe2ada1f730c03b8602a0d314cebadaa2fad5
1 // i386-signal.h - Catch runtime signals and turn them into exceptions.
3 /* Copyright (C) 1998, 1999 Cygnus Solutions
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
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
16 #ifndef JAVA_SIGNAL_H
17 #define JAVA_SIGNAL_H 1
19 #include <signal.h>
21 #define HANDLE_SEGV 1
22 #define HANDLE_FPE 1
24 #define SIGNAL_HANDLER(_name) \
25 static void _name (int _dummy)
27 #define MAKE_THROW_FRAME \
28 do \
29 { \
30 void **_p = (void **)&_dummy; \
31 struct sigcontext_struct *_regs = (struct sigcontext_struct *)++_p; \
33 register unsigned long _ebp = _regs->ebp; \
34 register unsigned char *_eip = (unsigned char *)_regs->eip; \
36 asm volatile ("mov %0, (%%ebp); mov %1, 4(%%ebp)" \
37 : : "r"(_ebp), "r"(_eip)); \
38 } \
39 while (0)
41 #define HANDLE_DIVIDE_OVERFLOW \
42 do \
43 { \
44 void **_p = (void **)&_dummy; \
45 struct sigcontext_struct *_regs = (struct sigcontext_struct *)++_p; \
47 register unsigned long *_ebp = (unsigned long *)_regs->ebp; \
48 register unsigned char *_eip = (unsigned char *)_regs->eip; \
50 /* According to the JVM spec, "if the dividend is the negative \
51 * integer of the smallest magnitude and the divisor is -1, then \
52 * overflow occurs and the result is equal to the dividend. Despite \
53 * the overflow, no exception occurs". \
55 * We handle this by inspecting the instruction which generated the \
56 * signal and advancing eip to point to the following instruction. \
57 * As the instructions are variable length it is necessary to do a \
58 * little calculation to figure out where the following instruction \
59 * actually is. \
61 */ \
63 if (_eip[0] == 0xf7) \
64 { \
65 unsigned char _modrm = _eip[1]; \
67 if (_regs->eax == 0x80000000 \
68 && ((_modrm >> 3) & 7) == 7) /* Signed divide */ \
69 { \
70 _regs->edx = 0; /* the remainder is zero */ \
71 switch (_modrm >> 6) \
72 { \
73 case 0: \
74 if ((_modrm & 7) == 5) \
75 _eip += 4; \
76 break; \
77 case 1: \
78 _eip += 1; \
79 break; \
80 case 2: \
81 _eip += 4; \
82 break; \
83 case 3: \
84 break; \
85 } \
86 _eip += 2; \
87 _regs->eip = (unsigned long)_eip; \
88 return; \
89 } \
90 else if (((_modrm >> 3) & 7) == 6) /* Unsigned divide */ \
91 { \
92 /* We assume that unsigned divisions are in library code, so \
93 * we throw one level down the stack, which was hopefully \
94 * the place that called the library routine. This will \
95 * break if the library is ever compiled with \
96 * -fomit-frame-pointer, but at least this way we've got a \
97 * good chance of finding the exception handler. */ \
99 _eip = (unsigned char *)_ebp[1]; \
100 _ebp = (unsigned long *)_ebp[0]; \
104 asm volatile ("mov %0, (%%ebp); mov %1, 4(%%ebp)" \
105 : : "r"(_ebp), "r"(_eip)); \
107 while (0)
109 #define INIT_SEGV \
110 do \
112 nullp = new java::lang::NullPointerException (); \
113 struct sigaction act; \
114 act.sa_handler = catch_segv; \
115 sigemptyset (&act.sa_mask); \
116 act.sa_flags = 0; \
117 sigaction (SIGSEGV, &act, NULL); \
119 while (0)
121 #define INIT_FPE \
122 do \
124 arithexception = new java::lang::ArithmeticException \
125 (JvNewStringLatin1 ("/ by zero")); \
126 struct sigaction act; \
127 act.sa_handler = catch_fpe; \
128 sigemptyset (&act.sa_mask); \
129 act.sa_flags = 0; \
130 sigaction (SIGFPE, &act, NULL); \
132 while (0)
134 #endif /* JAVA_SIGNAL_H */