diff options
author | aph <aph@138bc75d-0d04-0410-961f-82ee72b054a4> | 1999-05-20 08:26:55 +0000 |
---|---|---|
committer | aph <aph@138bc75d-0d04-0410-961f-82ee72b054a4> | 1999-05-20 08:26:55 +0000 |
commit | a5b1e8ad34500f24632c0dbcaa4c0788c0a48d06 (patch) | |
tree | c773f8d236cca5c8caaa0578e6211289e6fc850a /libjava/include | |
parent | 8f68d3b43cb2436a1faf8f5cf35b20ea3584d65a (diff) | |
download | gcc-a5b1e8ad34500f24632c0dbcaa4c0788c0a48d06.tar.gz |
1999-05-20 Andrew Haley <aph@cygnus.com>
* libjava/prims.cc (catch_fpe): Call to HANDLE_DIVIDE_OVERFLOW
added.
* include/i386-signal.h (HANDLE_DIVIDE_OVERFLOW): New macro.
(INIT_FPE): Exception string made more informative.
* include/sparc-signal.h (INIT_FPE): Exception string made more
informative.
* testsuite/libjava.lang/Divide_1.java: New file.
* testsuite/libjava.lang/Divide_1.out: New file.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@27056 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava/include')
-rw-r--r-- | libjava/include/i386-signal.h | 83 | ||||
-rw-r--r-- | libjava/include/sparc-signal.h | 3 |
2 files changed, 79 insertions, 7 deletions
diff --git a/libjava/include/i386-signal.h b/libjava/include/i386-signal.h index 73d8bbbbfc0..12ffe2ada1f 100644 --- a/libjava/include/i386-signal.h +++ b/libjava/include/i386-signal.h @@ -25,16 +25,86 @@ details. */ static void _name (int _dummy) #define MAKE_THROW_FRAME \ +do \ { \ void **_p = (void **)&_dummy; \ struct sigcontext_struct *_regs = (struct sigcontext_struct *)++_p; \ \ register unsigned long _ebp = _regs->ebp; \ - register unsigned long _eip = _regs->eip; \ - \ + register unsigned char *_eip = (unsigned char *)_regs->eip; \ + \ + asm volatile ("mov %0, (%%ebp); mov %1, 4(%%ebp)" \ + : : "r"(_ebp), "r"(_eip)); \ +} \ +while (0) + +#define HANDLE_DIVIDE_OVERFLOW \ +do \ +{ \ + void **_p = (void **)&_dummy; \ + struct sigcontext_struct *_regs = (struct sigcontext_struct *)++_p; \ + \ + register unsigned long *_ebp = (unsigned long *)_regs->ebp; \ + register unsigned char *_eip = (unsigned char *)_regs->eip; \ + \ + /* According to the JVM spec, "if the dividend is the negative \ + * integer of the smallest magnitude and the divisor is -1, then \ + * overflow occurs and the result is equal to the dividend. Despite \ + * the overflow, no exception occurs". \ + \ + * We handle this by inspecting the instruction which generated the \ + * signal and advancing eip to point to the following instruction. \ + * As the instructions are variable length it is necessary to do a \ + * little calculation to figure out where the following instruction \ + * actually is. \ + \ + */ \ + \ + if (_eip[0] == 0xf7) \ + { \ + unsigned char _modrm = _eip[1]; \ + \ + if (_regs->eax == 0x80000000 \ + && ((_modrm >> 3) & 7) == 7) /* Signed divide */ \ + { \ + _regs->edx = 0; /* the remainder is zero */ \ + switch (_modrm >> 6) \ + { \ + case 0: \ + if ((_modrm & 7) == 5) \ + _eip += 4; \ + break; \ + case 1: \ + _eip += 1; \ + break; \ + case 2: \ + _eip += 4; \ + break; \ + case 3: \ + break; \ + } \ + _eip += 2; \ + _regs->eip = (unsigned long)_eip; \ + return; \ + } \ + else if (((_modrm >> 3) & 7) == 6) /* Unsigned divide */ \ + { \ + /* We assume that unsigned divisions are in library code, so \ + * we throw one level down the stack, which was hopefully \ + * the place that called the library routine. This will \ + * break if the library is ever compiled with \ + * -fomit-frame-pointer, but at least this way we've got a \ + * good chance of finding the exception handler. */ \ + \ + _eip = (unsigned char *)_ebp[1]; \ + _ebp = (unsigned long *)_ebp[0]; \ + } \ + } \ + \ asm volatile ("mov %0, (%%ebp); mov %1, 4(%%ebp)" \ : : "r"(_ebp), "r"(_eip)); \ -} +} \ +while (0) #define INIT_SEGV \ do \ @@ -48,10 +118,11 @@ do \ } \ while (0) -#define INIT_FPE \ +#define INIT_FPE \ do \ - { \ - arithexception = new java::lang::ArithmeticException (); \ + { \ + arithexception = new java::lang::ArithmeticException \ + (JvNewStringLatin1 ("/ by zero")); \ struct sigaction act; \ act.sa_handler = catch_fpe; \ sigemptyset (&act.sa_mask); \ diff --git a/libjava/include/sparc-signal.h b/libjava/include/sparc-signal.h index dfe8635e3eb..03b5cdc4dc6 100644 --- a/libjava/include/sparc-signal.h +++ b/libjava/include/sparc-signal.h @@ -51,7 +51,8 @@ while (0) #define INIT_FPE \ do \ { \ - arithexception = new java::lang::ArithmeticException (); \ + arithexception = new java::lang::ArithmeticException \ + (JvNewStringLatin1 ("/ by zero")); \ struct sigaction act; \ act.sa_flags = SA_SIGINFO; \ act.sa_sigaction = catch_fpe; \ |