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 | 82 | #endif |
83 | 83 | #endif |
84 | 84 | |
85 | +#if HOST_LONG_BITS < 64 | |
86 | +void do_div (void); | |
87 | +#endif | |
85 | 88 | #if TARGET_LONG_BITS > HOST_LONG_BITS |
86 | 89 | void do_mult (void); |
87 | 90 | void do_multu (void); |
... | ... | @@ -89,10 +92,12 @@ void do_madd (void); |
89 | 92 | void do_maddu (void); |
90 | 93 | void do_msub (void); |
91 | 94 | void do_msubu (void); |
95 | +#endif | |
96 | +#ifdef TARGET_MIPS64 | |
92 | 97 | void do_ddiv (void); |
98 | +#if TARGET_LONG_BITS > HOST_LONG_BITS | |
93 | 99 | void do_ddivu (void); |
94 | 100 | #endif |
95 | -#ifdef TARGET_MIPS64 | |
96 | 101 | void do_dmult (void); |
97 | 102 | void do_dmultu (void); |
98 | 103 | #endif | ... | ... |
target-mips/op.c
... | ... | @@ -368,14 +368,22 @@ void op_mul (void) |
368 | 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 | 378 | void op_div (void) |
372 | 379 | { |
373 | 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 | 384 | RETURN(); |
378 | 385 | } |
386 | +#endif | |
379 | 387 | |
380 | 388 | void op_divu (void) |
381 | 389 | { |
... | ... | @@ -432,7 +440,6 @@ void op_dmul (void) |
432 | 440 | RETURN(); |
433 | 441 | } |
434 | 442 | |
435 | -#if TARGET_LONG_BITS > HOST_LONG_BITS | |
436 | 443 | /* Those might call libgcc functions. */ |
437 | 444 | void op_ddiv (void) |
438 | 445 | { |
... | ... | @@ -440,21 +447,13 @@ void op_ddiv (void) |
440 | 447 | RETURN(); |
441 | 448 | } |
442 | 449 | |
450 | +#if TARGET_LONG_BITS > HOST_LONG_BITS | |
443 | 451 | void op_ddivu (void) |
444 | 452 | { |
445 | 453 | do_ddivu(); |
446 | 454 | RETURN(); |
447 | 455 | } |
448 | 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 | 457 | void op_ddivu (void) |
459 | 458 | { |
460 | 459 | if (T1 != 0) { | ... | ... |
target-mips/op_helper.c
... | ... | @@ -216,6 +216,17 @@ void do_msubu (void) |
216 | 216 | } |
217 | 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 | 230 | #ifdef TARGET_MIPS64 |
220 | 231 | void do_dmult (void) |
221 | 232 | { | ... | ... |