Commit 51fe68905b7638799d32668776a589b546c5fb38

Authored by bellard
1 parent 7fe70ecc

powerpc div and rint fixes


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@81 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 44 additions and 0 deletions
op-i386.c
@@ -412,6 +412,22 @@ void OPPROTO op_idivw_AX_T0(void) @@ -412,6 +412,22 @@ void OPPROTO op_idivw_AX_T0(void)
412 EDX = (EDX & 0xffff0000) | r; 412 EDX = (EDX & 0xffff0000) | r;
413 } 413 }
414 414
  415 +#ifdef BUGGY_GCC_DIV64
  416 +/* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we
  417 + call it from another function */
  418 +uint32_t div64(uint32_t *q_ptr, uint64_t num, uint32_t den)
  419 +{
  420 + *q_ptr = num / den;
  421 + return num % den;
  422 +}
  423 +
  424 +int32_t idiv64(int32_t *q_ptr, int64_t num, int32_t den)
  425 +{
  426 + *q_ptr = num / den;
  427 + return num % den;
  428 +}
  429 +#endif
  430 +
415 void OPPROTO op_divl_EAX_T0(void) 431 void OPPROTO op_divl_EAX_T0(void)
416 { 432 {
417 unsigned int den, q, r; 433 unsigned int den, q, r;
@@ -421,8 +437,12 @@ void OPPROTO op_divl_EAX_T0(void) @@ -421,8 +437,12 @@ void OPPROTO op_divl_EAX_T0(void)
421 den = T0; 437 den = T0;
422 if (den == 0) 438 if (den == 0)
423 raise_exception(EXCP00_DIVZ); 439 raise_exception(EXCP00_DIVZ);
  440 +#ifdef BUGGY_GCC_DIV64
  441 + r = div64(&q, num, den);
  442 +#else
424 q = (num / den); 443 q = (num / den);
425 r = (num % den); 444 r = (num % den);
  445 +#endif
426 EAX = q; 446 EAX = q;
427 EDX = r; 447 EDX = r;
428 } 448 }
@@ -436,8 +456,12 @@ void OPPROTO op_idivl_EAX_T0(void) @@ -436,8 +456,12 @@ void OPPROTO op_idivl_EAX_T0(void)
436 den = T0; 456 den = T0;
437 if (den == 0) 457 if (den == 0)
438 raise_exception(EXCP00_DIVZ); 458 raise_exception(EXCP00_DIVZ);
  459 +#ifdef BUGGY_GCC_DIV64
  460 + r = idiv64(&q, num, den);
  461 +#else
439 q = (num / den); 462 q = (num / den);
440 r = (num % den); 463 r = (num % den);
  464 +#endif
441 EAX = q; 465 EAX = q;
442 EDX = r; 466 EDX = r;
443 } 467 }
@@ -1503,6 +1527,26 @@ extern CPU86_LDouble floor(CPU86_LDouble x); @@ -1503,6 +1527,26 @@ extern CPU86_LDouble floor(CPU86_LDouble x);
1503 extern CPU86_LDouble ceil(CPU86_LDouble x); 1527 extern CPU86_LDouble ceil(CPU86_LDouble x);
1504 extern CPU86_LDouble rint(CPU86_LDouble x); 1528 extern CPU86_LDouble rint(CPU86_LDouble x);
1505 1529
  1530 +#if defined(__powerpc__)
  1531 +extern CPU86_LDouble copysign(CPU86_LDouble, CPU86_LDouble);
  1532 +
  1533 +/* correct (but slow) PowerPC rint() (glibc version is incorrect) */
  1534 +double qemu_rint(double x)
  1535 +{
  1536 + double y = 4503599627370496.0;
  1537 + if (fabs(x) >= y)
  1538 + return x;
  1539 + if (x < 0)
  1540 + y = -y;
  1541 + y = (x + y) - y;
  1542 + if (y == 0.0)
  1543 + y = copysign(y, x);
  1544 + return y;
  1545 +}
  1546 +
  1547 +#define rint qemu_rint
  1548 +#endif
  1549 +
1506 #define RC_MASK 0xc00 1550 #define RC_MASK 0xc00
1507 #define RC_NEAR 0x000 1551 #define RC_NEAR 0x000
1508 #define RC_DOWN 0x400 1552 #define RC_DOWN 0x400