OSDN Git Service

* All files: Updated copyright information.
[pf3gnuchains/gcc-fork.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