summaryrefslogtreecommitdiff
path: root/libjava/include
diff options
context:
space:
mode:
authoraph <aph@138bc75d-0d04-0410-961f-82ee72b054a4>1999-05-20 08:26:55 +0000
committeraph <aph@138bc75d-0d04-0410-961f-82ee72b054a4>1999-05-20 08:26:55 +0000
commita5b1e8ad34500f24632c0dbcaa4c0788c0a48d06 (patch)
treec773f8d236cca5c8caaa0578e6211289e6fc850a /libjava/include
parent8f68d3b43cb2436a1faf8f5cf35b20ea3584d65a (diff)
downloadgcc-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.h83
-rw-r--r--libjava/include/sparc-signal.h3
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; \