diff options
author | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-04-15 21:21:33 +0000 |
---|---|---|
committer | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-04-15 21:21:33 +0000 |
commit | 80c27194a7be757ef5a9cec978d1d8faaa4cee81 (patch) | |
tree | d70b8fe5bf3574d586a01bf7194f95f65368b741 /target-mips | |
parent | a85427b147f3174748a4eed13a7379a769bb05fd (diff) |
Fix qemu SIGFPE caused by division-by-zero due to underflow.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2673 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-mips')
-rw-r--r-- | target-mips/exec.h | 7 | ||||
-rw-r--r-- | target-mips/op.c | 23 | ||||
-rw-r--r-- | target-mips/op_helper.c | 11 |
3 files changed, 28 insertions, 13 deletions
diff --git a/target-mips/exec.h b/target-mips/exec.h index 54f4d5a75f..cfe69a3ffa 100644 --- a/target-mips/exec.h +++ b/target-mips/exec.h @@ -82,6 +82,9 @@ void do_drotrv (void); #endif #endif +#if HOST_LONG_BITS < 64 +void do_div (void); +#endif #if TARGET_LONG_BITS > HOST_LONG_BITS void do_mult (void); void do_multu (void); @@ -89,10 +92,12 @@ void do_madd (void); void do_maddu (void); void do_msub (void); void do_msubu (void); +#endif +#ifdef TARGET_MIPS64 void do_ddiv (void); +#if TARGET_LONG_BITS > HOST_LONG_BITS void do_ddivu (void); #endif -#ifdef TARGET_MIPS64 void do_dmult (void); void do_dmultu (void); #endif diff --git a/target-mips/op.c b/target-mips/op.c index 9e9f8eb759..2ea84b65a0 100644 --- a/target-mips/op.c +++ b/target-mips/op.c @@ -368,14 +368,22 @@ void op_mul (void) RETURN(); } +#if HOST_LONG_BITS < 64 +void op_div (void) +{ + CALL_FROM_TB0(do_div); + RETURN(); +} +#else void op_div (void) { if (T1 != 0) { - env->LO = (int32_t)((int32_t)T0 / (int32_t)T1); - env->HI = (int32_t)((int32_t)T0 % (int32_t)T1); + env->LO = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1); + env->HI = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1); } RETURN(); } +#endif void op_divu (void) { @@ -432,7 +440,6 @@ void op_dmul (void) RETURN(); } -#if TARGET_LONG_BITS > HOST_LONG_BITS /* Those might call libgcc functions. */ void op_ddiv (void) { @@ -440,21 +447,13 @@ void op_ddiv (void) RETURN(); } +#if TARGET_LONG_BITS > HOST_LONG_BITS void op_ddivu (void) { do_ddivu(); RETURN(); } #else -void op_ddiv (void) -{ - if (T1 != 0) { - env->LO = (int64_t)T0 / (int64_t)T1; - env->HI = (int64_t)T0 % (int64_t)T1; - } - RETURN(); -} - void op_ddivu (void) { if (T1 != 0) { diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 576787d3f4..14696aa925 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -216,6 +216,17 @@ void do_msubu (void) } #endif +#if HOST_LONG_BITS < 64 +void do_div (void) +{ + /* 64bit datatypes because we may see overflow/underflow. */ + if (T1 != 0) { + env->LO = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1); + env->HI = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1); + } +} +#endif + #ifdef TARGET_MIPS64 void do_dmult (void) { |