From 51fe68905b7638799d32668776a589b546c5fb38 Mon Sep 17 00:00:00 2001 From: bellard Date: Mon, 7 Apr 2003 21:34:14 +0000 Subject: [PATCH] powerpc div and rint fixes git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@81 c046a42c-6fe2-441c-8c8c-71466251a162 --- op-i386.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/op-i386.c b/op-i386.c index 43303784d..323fce33d 100644 --- a/op-i386.c +++ b/op-i386.c @@ -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 -- 2.39.2