Commit 51fe68905b7638799d32668776a589b546c5fb38
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 | 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 | 431 | void OPPROTO op_divl_EAX_T0(void) |
| 416 | 432 | { |
| 417 | 433 | unsigned int den, q, r; |
| ... | ... | @@ -421,8 +437,12 @@ void OPPROTO op_divl_EAX_T0(void) |
| 421 | 437 | den = T0; |
| 422 | 438 | if (den == 0) |
| 423 | 439 | raise_exception(EXCP00_DIVZ); |
| 440 | +#ifdef BUGGY_GCC_DIV64 | |
| 441 | + r = div64(&q, num, den); | |
| 442 | +#else | |
| 424 | 443 | q = (num / den); |
| 425 | 444 | r = (num % den); |
| 445 | +#endif | |
| 426 | 446 | EAX = q; |
| 427 | 447 | EDX = r; |
| 428 | 448 | } |
| ... | ... | @@ -436,8 +456,12 @@ void OPPROTO op_idivl_EAX_T0(void) |
| 436 | 456 | den = T0; |
| 437 | 457 | if (den == 0) |
| 438 | 458 | raise_exception(EXCP00_DIVZ); |
| 459 | +#ifdef BUGGY_GCC_DIV64 | |
| 460 | + r = idiv64(&q, num, den); | |
| 461 | +#else | |
| 439 | 462 | q = (num / den); |
| 440 | 463 | r = (num % den); |
| 464 | +#endif | |
| 441 | 465 | EAX = q; |
| 442 | 466 | EDX = r; |
| 443 | 467 | } |
| ... | ... | @@ -1503,6 +1527,26 @@ extern CPU86_LDouble floor(CPU86_LDouble x); |
| 1503 | 1527 | extern CPU86_LDouble ceil(CPU86_LDouble x); |
| 1504 | 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 | 1550 | #define RC_MASK 0xc00 |
| 1507 | 1551 | #define RC_NEAR 0x000 |
| 1508 | 1552 | #define RC_DOWN 0x400 | ... | ... |