Commit 80c27194a7be757ef5a9cec978d1d8faaa4cee81
1 parent
a85427b1
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
Showing
3 changed files
with
28 additions
and
13 deletions
target-mips/exec.h
| @@ -82,6 +82,9 @@ void do_drotrv (void); | @@ -82,6 +82,9 @@ void do_drotrv (void); | ||
| 82 | #endif | 82 | #endif |
| 83 | #endif | 83 | #endif |
| 84 | 84 | ||
| 85 | +#if HOST_LONG_BITS < 64 | ||
| 86 | +void do_div (void); | ||
| 87 | +#endif | ||
| 85 | #if TARGET_LONG_BITS > HOST_LONG_BITS | 88 | #if TARGET_LONG_BITS > HOST_LONG_BITS |
| 86 | void do_mult (void); | 89 | void do_mult (void); |
| 87 | void do_multu (void); | 90 | void do_multu (void); |
| @@ -89,10 +92,12 @@ void do_madd (void); | @@ -89,10 +92,12 @@ void do_madd (void); | ||
| 89 | void do_maddu (void); | 92 | void do_maddu (void); |
| 90 | void do_msub (void); | 93 | void do_msub (void); |
| 91 | void do_msubu (void); | 94 | void do_msubu (void); |
| 95 | +#endif | ||
| 96 | +#ifdef TARGET_MIPS64 | ||
| 92 | void do_ddiv (void); | 97 | void do_ddiv (void); |
| 98 | +#if TARGET_LONG_BITS > HOST_LONG_BITS | ||
| 93 | void do_ddivu (void); | 99 | void do_ddivu (void); |
| 94 | #endif | 100 | #endif |
| 95 | -#ifdef TARGET_MIPS64 | ||
| 96 | void do_dmult (void); | 101 | void do_dmult (void); |
| 97 | void do_dmultu (void); | 102 | void do_dmultu (void); |
| 98 | #endif | 103 | #endif |
target-mips/op.c
| @@ -368,14 +368,22 @@ void op_mul (void) | @@ -368,14 +368,22 @@ void op_mul (void) | ||
| 368 | RETURN(); | 368 | RETURN(); |
| 369 | } | 369 | } |
| 370 | 370 | ||
| 371 | +#if HOST_LONG_BITS < 64 | ||
| 372 | +void op_div (void) | ||
| 373 | +{ | ||
| 374 | + CALL_FROM_TB0(do_div); | ||
| 375 | + RETURN(); | ||
| 376 | +} | ||
| 377 | +#else | ||
| 371 | void op_div (void) | 378 | void op_div (void) |
| 372 | { | 379 | { |
| 373 | if (T1 != 0) { | 380 | if (T1 != 0) { |
| 374 | - env->LO = (int32_t)((int32_t)T0 / (int32_t)T1); | ||
| 375 | - env->HI = (int32_t)((int32_t)T0 % (int32_t)T1); | 381 | + env->LO = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1); |
| 382 | + env->HI = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1); | ||
| 376 | } | 383 | } |
| 377 | RETURN(); | 384 | RETURN(); |
| 378 | } | 385 | } |
| 386 | +#endif | ||
| 379 | 387 | ||
| 380 | void op_divu (void) | 388 | void op_divu (void) |
| 381 | { | 389 | { |
| @@ -432,7 +440,6 @@ void op_dmul (void) | @@ -432,7 +440,6 @@ void op_dmul (void) | ||
| 432 | RETURN(); | 440 | RETURN(); |
| 433 | } | 441 | } |
| 434 | 442 | ||
| 435 | -#if TARGET_LONG_BITS > HOST_LONG_BITS | ||
| 436 | /* Those might call libgcc functions. */ | 443 | /* Those might call libgcc functions. */ |
| 437 | void op_ddiv (void) | 444 | void op_ddiv (void) |
| 438 | { | 445 | { |
| @@ -440,21 +447,13 @@ void op_ddiv (void) | @@ -440,21 +447,13 @@ void op_ddiv (void) | ||
| 440 | RETURN(); | 447 | RETURN(); |
| 441 | } | 448 | } |
| 442 | 449 | ||
| 450 | +#if TARGET_LONG_BITS > HOST_LONG_BITS | ||
| 443 | void op_ddivu (void) | 451 | void op_ddivu (void) |
| 444 | { | 452 | { |
| 445 | do_ddivu(); | 453 | do_ddivu(); |
| 446 | RETURN(); | 454 | RETURN(); |
| 447 | } | 455 | } |
| 448 | #else | 456 | #else |
| 449 | -void op_ddiv (void) | ||
| 450 | -{ | ||
| 451 | - if (T1 != 0) { | ||
| 452 | - env->LO = (int64_t)T0 / (int64_t)T1; | ||
| 453 | - env->HI = (int64_t)T0 % (int64_t)T1; | ||
| 454 | - } | ||
| 455 | - RETURN(); | ||
| 456 | -} | ||
| 457 | - | ||
| 458 | void op_ddivu (void) | 457 | void op_ddivu (void) |
| 459 | { | 458 | { |
| 460 | if (T1 != 0) { | 459 | if (T1 != 0) { |
target-mips/op_helper.c
| @@ -216,6 +216,17 @@ void do_msubu (void) | @@ -216,6 +216,17 @@ void do_msubu (void) | ||
| 216 | } | 216 | } |
| 217 | #endif | 217 | #endif |
| 218 | 218 | ||
| 219 | +#if HOST_LONG_BITS < 64 | ||
| 220 | +void do_div (void) | ||
| 221 | +{ | ||
| 222 | + /* 64bit datatypes because we may see overflow/underflow. */ | ||
| 223 | + if (T1 != 0) { | ||
| 224 | + env->LO = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1); | ||
| 225 | + env->HI = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1); | ||
| 226 | + } | ||
| 227 | +} | ||
| 228 | +#endif | ||
| 229 | + | ||
| 219 | #ifdef TARGET_MIPS64 | 230 | #ifdef TARGET_MIPS64 |
| 220 | void do_dmult (void) | 231 | void do_dmult (void) |
| 221 | { | 232 | { |