Commit 80c27194a7be757ef5a9cec978d1d8faaa4cee81

Authored by ths
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
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 {