diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-04-07 21:34:14 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-04-07 21:34:14 +0000 |
commit | 51fe68905b7638799d32668776a589b546c5fb38 (patch) | |
tree | b0ff3560cfb6b8d3af7067cd5a4c42a3fe65fc43 /op-i386.c | |
parent | 7fe70ecc567c8cd51d512a879485ab1048734d5f (diff) |
powerpc div and rint fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@81 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'op-i386.c')
-rw-r--r-- | op-i386.c | 44 |
1 files changed, 44 insertions, 0 deletions
@@ -412,6 +412,22 @@ void OPPROTO op_idivw_AX_T0(void) EDX = (EDX & 0xffff0000) | r; } +#ifdef BUGGY_GCC_DIV64 +/* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we + call it from another function */ +uint32_t div64(uint32_t *q_ptr, uint64_t num, uint32_t den) +{ + *q_ptr = num / den; + return num % den; +} + +int32_t idiv64(int32_t *q_ptr, int64_t num, int32_t den) +{ + *q_ptr = num / den; + return num % den; +} +#endif + void OPPROTO op_divl_EAX_T0(void) { unsigned int den, q, r; @@ -421,8 +437,12 @@ void OPPROTO op_divl_EAX_T0(void) den = T0; if (den == 0) raise_exception(EXCP00_DIVZ); +#ifdef BUGGY_GCC_DIV64 + r = div64(&q, num, den); +#else q = (num / den); r = (num % den); +#endif EAX = q; EDX = r; } @@ -436,8 +456,12 @@ void OPPROTO op_idivl_EAX_T0(void) den = T0; if (den == 0) raise_exception(EXCP00_DIVZ); +#ifdef BUGGY_GCC_DIV64 + r = idiv64(&q, num, den); +#else q = (num / den); r = (num % den); +#endif EAX = q; EDX = r; } @@ -1503,6 +1527,26 @@ extern CPU86_LDouble floor(CPU86_LDouble x); extern CPU86_LDouble ceil(CPU86_LDouble x); extern CPU86_LDouble rint(CPU86_LDouble x); +#if defined(__powerpc__) +extern CPU86_LDouble copysign(CPU86_LDouble, CPU86_LDouble); + +/* correct (but slow) PowerPC rint() (glibc version is incorrect) */ +double qemu_rint(double x) +{ + double y = 4503599627370496.0; + if (fabs(x) >= y) + return x; + if (x < 0) + y = -y; + y = (x + y) - y; + if (y == 0.0) + y = copysign(y, x); + return y; +} + +#define rint qemu_rint +#endif + #define RC_MASK 0xc00 #define RC_NEAR 0x000 #define RC_DOWN 0x400 |