[Sablevm-bugs] [ sablevm-Bugs-597368 ] Need to workaround the x86 division bug
Brought to you by:
egagnon
From: SourceForge.net <no...@so...> - 2004-03-27 13:37:00
|
Bugs item #597368, was opened at 2002-08-19 16:36 Message generated for change (Settings changed) made by egagnon You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=105523&aid=597368&group_id=5523 Category: Execution Problem Group: SableVM Status: Open Resolution: None Priority: 7 Submitted By: Nobody/Anonymous (nobody) >Assigned to: Nobody/Anonymous (nobody) Summary: Need to workaround the x86 division bug Initial Comment: /* test that we don't get tripped up by x86 problem */ public class divtest { public static int divfunc(int x, int y) { return x/y; } public static void main(String args[]) { int i = 0x80000000; int j = -1; int k = divfunc(i,j); // x86 causes trap for no good reason System.out.println("Result is "+Integer.toHexString(k)); } } This program should output "Result is 80000000" but instead we get (when running on i386): java.lang.ArithmeticException at divtest.divfunc(divtest.java:6) at divtest.main(divtest.java:14) at java.lang.VirtualMachine.invokeMain(VirtualMachine.java) at java.lang.VirtualMachine.main(VirtualMachine.java:88) Kaffe ran into this same problem. I don't know the details but it has something to do with an x86 integer division bug. ---------------------------------------------------------------------- Comment By: David Bélanger (davidbelanger) Date: 2003-07-27 22:13 Message: Logged In: YES user_id=694080 Hi, I did a fix for this bug. I tested it with and without signal for exception on x86. The change has been done in my *unstable* sablevm branch: /developers/belanger/sandbox/sablejit/sablevm/sablevm/ (revison 441). Basically, it can take advantage of the exception generated on x86 to avoid a check everytime. It may work with other processors, but my current patch assumes that it does not. Index: src/libsablevm/interpreter.c =================================================================== --- src/libsablevm/interpreter.c (revision 438) +++ src/libsablevm/interpreter.c (working copy) @@ -83,7 +83,28 @@ case SVM_SIGNAL_ARITHMETIC_EXCEPTION: { - goto arithmeticexception_handler; + /* + fprintf(stderr, "value1: %d value2: %d\n", + stack[stack_size - 1], + stack[stack_size]); + */ + if (stack[stack_size - 1].jint == 0x80000000 && + stack[stack_size].jint == -1) + { + /* Continue normally + * + * Note: result slot already contains value1 + */ +#if defined(_SABLEVM_INLINED_THREADED_INTERPRETER) || defined(_SABLEVM_DIRECT_TH READED_INTERPRETER) + goto *((pc++)->implementation); +#else + goto dispatch; +#endif /* defined(_SABLEVM_INLINED_THREADED_INTERPRETER) || defined(_SABLEVM_DIR ECT_THREADED_INTERPRETER) */ + } + else + { + goto arithmeticexception_handler; + } } break; Index: src/libsablevm/instructions.m4.c =================================================================== --- src/libsablevm/instructions.m4.c (revision 438) +++ src/libsablevm/instructions.m4.c (working copy) @@ -1174,7 +1174,6 @@ { env->sigfpe_expected = JNI_TRUE; } - #endif /* save pc in case exception is raised */ @@ -1187,10 +1186,40 @@ env->stack.current_frame->pc = pc; goto arithmeticexception_handler; } - #endif /* _SABLEVM_SIGNALS_FOR_EXCEPTIONS */ + + /* + * Handling of exceptional case: 0x80000000 / -1 + * + * Note: Not all processors will generate an exception. + * + */ +#if defined(_SABLEVM_SIGNALS_FOR_EXCEPTIONS) && defined(__i386__) + +#ifndef NDEBUG + if (value1 == 0x80000000 && value2 == -1) + { + env->sigfpe_expected = JNI_TRUE; + } +#endif + /* save pc in case exception is raised */ + env->stack.current_frame->pc = pc; stack[stack_size - 1].jint = value1 / value2; + +#else + + if (value1 == 0x80000000 && value2 == -1) + { + /* Nothing to do as result slot already contains value1 */ + } + else + { + stack[stack_size - 1].jint = value1 / value2; + } + +#endif /* _SABLEVM_SIGNALS_FOR_EXCEPTIONS && __i386__ */ + } m4svm_instruction_tail (); @@ -1236,7 +1265,18 @@ #endif /* _SABLEVM_SIGNALS_FOR_EXCEPTIONS */ - *((jlong *) &stack[stack_size - 2]) = value1 / value2; + /* Note: On i386 the (gcc) implementation is okay */ + /* + if (value1 == 0x8000000000000000L && value2 == -1L) + { + *((jlong *) &stack[stack_size - 2]) = value1; + } + else + */ + { + *((jlong *) &stack[stack_size - 2]) = value1 / value2; + } + } m4svm_instruction_tail (); @@ -1597,7 +1637,7 @@ if (value1 != value1 || value2 != value2) { /* NaN */ - stack[(stack_size -= 3) - 1].jint = -1; + stack[(stack_size -= 3) - 1].jint = 1; } else { ---------------------------------------------------------------------- Comment By: David Bélanger (davidbelanger) Date: 2003-01-31 08:21 Message: Logged In: YES user_id=694080 On PPC, that division produces undefined result (on a G3, it gives -1). No exception is raised, however it would be possible to check for overflow (probably would require some inlined assembly). We may need some #define in system.c to handle it for each architecture that produces "incorrect" result. FYI, due to the asymmetry of 2's complement, there is no positive integer equal to 0x80000000 / -1. David ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=105523&aid=597368&group_id=5523 |