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 | ... | ... |