aboutsummaryrefslogtreecommitdiff
path: root/target-mips
diff options
context:
space:
mode:
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2007-04-15 21:21:33 +0000
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2007-04-15 21:21:33 +0000
commit80c27194a7be757ef5a9cec978d1d8faaa4cee81 (patch)
treed70b8fe5bf3574d586a01bf7194f95f65368b741 /target-mips
parenta85427b147f3174748a4eed13a7379a769bb05fd (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.h7
-rw-r--r--target-mips/op.c23
-rw-r--r--target-mips/op_helper.c11
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)
{