diff options
author | joseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2010-05-11 20:48:50 +0000 |
---|---|---|
committer | joseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2010-05-11 20:48:50 +0000 |
commit | 8788ce3787ac33ece2f77ee530b7858b2bc202f3 (patch) | |
tree | 3a0c8d1e9cf225512c85c6366d2a78fff715d229 /ports/sysdeps/alpha/fpu | |
parent | 7900271c9a94743597a2d3e63c372a8e26fd02e0 (diff) | |
download | eglibc2-8788ce3787ac33ece2f77ee530b7858b2bc202f3.tar.gz |
Merge changes between r10371 and r10438 from /fsf/trunk.
git-svn-id: svn://svn.eglibc.org/trunk@10439 7b3dc134-2b1b-0410-93df-9e9f96275f8d
Diffstat (limited to 'ports/sysdeps/alpha/fpu')
-rw-r--r-- | ports/sysdeps/alpha/fpu/s_ceil.c | 27 | ||||
-rw-r--r-- | ports/sysdeps/alpha/fpu/s_ceilf.c | 32 | ||||
-rw-r--r-- | ports/sysdeps/alpha/fpu/s_floor.c | 32 | ||||
-rw-r--r-- | ports/sysdeps/alpha/fpu/s_floorf.c | 37 | ||||
-rw-r--r-- | ports/sysdeps/alpha/fpu/s_rint.c | 27 | ||||
-rw-r--r-- | ports/sysdeps/alpha/fpu/s_rintf.c | 33 |
6 files changed, 122 insertions, 66 deletions
diff --git a/ports/sysdeps/alpha/fpu/s_ceil.c b/ports/sysdeps/alpha/fpu/s_ceil.c index 40c237928..fe2090245 100644 --- a/ports/sysdeps/alpha/fpu/s_ceil.c +++ b/ports/sysdeps/alpha/fpu/s_ceil.c @@ -27,20 +27,25 @@ double __ceil (double x) { - double two52 = copysign (0x1.0p52, x); - double r, tmp; - - __asm ( + if (isless (fabs (x), 9007199254740992.0)) /* 1 << DBL_MANT_DIG */ + { + double tmp1, new_x; + + new_x = -x; + __asm ( #ifdef _IEEE_FP_INEXACT - "addt/suim %2, %3, %1\n\tsubt/suim %1, %3, %0" + "cvttq/svim %2,%1\n\t" #else - "addt/sum %2, %3, %1\n\tsubt/sum %1, %3, %0" + "cvttq/svm %2,%1\n\t" #endif - : "=&f"(r), "=&f"(tmp) - : "f"(-x), "f"(-two52)); - - /* Fix up the negation we did above, as well as handling -0 properly. */ - return copysign (r, x); + "cvtqt/m %1,%0\n\t" + : "=f"(new_x), "=&f"(tmp1) + : "f"(new_x)); + + /* Fix up the negation we did above, as well as handling -0 properly. */ + x = copysign(new_x, x); + } + return x; } weak_alias (__ceil, ceil) diff --git a/ports/sysdeps/alpha/fpu/s_ceilf.c b/ports/sysdeps/alpha/fpu/s_ceilf.c index 0df651f40..c722e7294 100644 --- a/ports/sysdeps/alpha/fpu/s_ceilf.c +++ b/ports/sysdeps/alpha/fpu/s_ceilf.c @@ -26,20 +26,30 @@ float __ceilf (float x) { - float two23 = copysignf (0x1.0p23, x); - float r, tmp; - - __asm ( + if (isless (fabsf (x), 16777216.0f)) /* 1 << FLT_MANT_DIG */ + { + /* Note that Alpha S_Floating is stored in registers in a + restricted T_Floating format, so we don't even need to + convert back to S_Floating in the end. The initial + conversion to T_Floating is needed to handle denormals. */ + + float tmp1, tmp2, new_x; + + new_x = -x; + __asm ("cvtst/s %3,%2\n\t" #ifdef _IEEE_FP_INEXACT - "adds/suim %2, %3, %1\n\tsubs/suim %1, %3, %0" + "cvttq/svim %2,%1\n\t" #else - "adds/sum %2, %3, %1\n\tsubs/sum %1, %3, %0" + "cvttq/svm %2,%1\n\t" #endif - : "=&f"(r), "=&f"(tmp) - : "f"(-x), "f"(-two23)); - - /* Fix up the negation we did above, as well as handling -0 properly. */ - return copysignf (r, x); + "cvtqt/m %1,%0\n\t" + : "=f"(new_x), "=&f"(tmp1), "=&f"(tmp2) + : "f"(new_x)); + + /* Fix up the negation we did above, as well as handling -0 properly. */ + x = copysignf(new_x, x); + } + return x; } weak_alias (__ceilf, ceilf) diff --git a/ports/sysdeps/alpha/fpu/s_floor.c b/ports/sysdeps/alpha/fpu/s_floor.c index 5af638615..6b16401e4 100644 --- a/ports/sysdeps/alpha/fpu/s_floor.c +++ b/ports/sysdeps/alpha/fpu/s_floor.c @@ -21,26 +21,32 @@ #include <math_ldbl_opt.h> -/* Use the -inf rounding mode conversion instructions to implement floor. */ +/* Use the -inf rounding mode conversion instructions to implement + floor. We note when the exponent is large enough that the value + must be integral, as this avoids unpleasant integer overflows. */ double __floor (double x) { - double two52 = copysign (0x1.0p52, x); - double r, tmp; - - __asm ( + if (isless (fabs (x), 9007199254740992.0)) /* 1 << DBL_MANT_DIG */ + { + double tmp1, new_x; + + __asm ( #ifdef _IEEE_FP_INEXACT - "addt/suim %2, %3, %1\n\tsubt/suim %1, %3, %0" + "cvttq/svim %2,%1\n\t" #else - "addt/sum %2, %3, %1\n\tsubt/sum %1, %3, %0" + "cvttq/svm %2,%1\n\t" #endif - : "=&f"(r), "=&f"(tmp) - : "f"(x), "f"(two52)); - - /* floor(-0) == -0, and in general we'll always have the same - sign as our input. */ - return copysign (r, x); + "cvtqt/m %1,%0\n\t" + : "=f"(new_x), "=&f"(tmp1) + : "f"(x)); + + /* floor(-0) == -0, and in general we'll always have the same + sign as our input. */ + x = copysign(new_x, x); + } + return x; } weak_alias (__floor, floor) diff --git a/ports/sysdeps/alpha/fpu/s_floorf.c b/ports/sysdeps/alpha/fpu/s_floorf.c index 8b421705c..5da08ae10 100644 --- a/ports/sysdeps/alpha/fpu/s_floorf.c +++ b/ports/sysdeps/alpha/fpu/s_floorf.c @@ -20,26 +20,37 @@ #include <math.h> -/* Use the -inf rounding mode conversion instructions to implement floor. */ +/* Use the -inf rounding mode conversion instructions to implement + floor. We note when the exponent is large enough that the value + must be integral, as this avoids unpleasant integer overflows. */ float __floorf (float x) { - float two23 = copysignf (0x1.0p23, x); - float r, tmp; - - __asm ( + if (isless (fabsf (x), 16777216.0f)) /* 1 << FLT_MANT_DIG */ + { + /* Note that Alpha S_Floating is stored in registers in a + restricted T_Floating format, so we don't even need to + convert back to S_Floating in the end. The initial + conversion to T_Floating is needed to handle denormals. */ + + float tmp1, tmp2, new_x; + + __asm ("cvtst/s %3,%2\n\t" #ifdef _IEEE_FP_INEXACT - "adds/suim %2, %3, %1\n\tsubs/suim %1, %3, %0" + "cvttq/svim %2,%1\n\t" #else - "adds/sum %2, %3, %1\n\tsubs/sum %1, %3, %0" + "cvttq/svm %2,%1\n\t" #endif - : "=&f"(r), "=&f"(tmp) - : "f"(x), "f"(two23)); - - /* floor(-0) == -0, and in general we'll always have the same - sign as our input. */ - return copysignf (r, x); + "cvtqt/m %1,%0\n\t" + : "=f"(new_x), "=&f"(tmp1), "=&f"(tmp2) + : "f"(x)); + + /* floor(-0) == -0, and in general we'll always have the same + sign as our input. */ + x = copysignf(new_x, x); + } + return x; } weak_alias (__floorf, floorf) diff --git a/ports/sysdeps/alpha/fpu/s_rint.c b/ports/sysdeps/alpha/fpu/s_rint.c index e9aa02882..962463129 100644 --- a/ports/sysdeps/alpha/fpu/s_rint.c +++ b/ports/sysdeps/alpha/fpu/s_rint.c @@ -24,15 +24,24 @@ double __rint (double x) { - double two52 = copysign (0x1.0p52, x); - double r; - - r = x + two52; - r = r - two52; - - /* rint(-0.1) == -0, and in general we'll always have the same sign - as our input. */ - return copysign (r, x); + if (isless (fabs (x), 9007199254740992.0)) /* 1 << DBL_MANT_DIG */ + { + double tmp1, new_x; + __asm ( +#ifdef _IEEE_FP_INEXACT + "cvttq/svid %2,%1\n\t" +#else + "cvttq/svd %2,%1\n\t" +#endif + "cvtqt/d %1,%0\n\t" + : "=f"(new_x), "=&f"(tmp1) + : "f"(x)); + + /* rint(-0.1) == -0, and in general we'll always have the same + sign as our input. */ + x = copysign(new_x, x); + } + return x; } weak_alias (__rint, rint) diff --git a/ports/sysdeps/alpha/fpu/s_rintf.c b/ports/sysdeps/alpha/fpu/s_rintf.c index 9e4cbd1ff..39fb72fb6 100644 --- a/ports/sysdeps/alpha/fpu/s_rintf.c +++ b/ports/sysdeps/alpha/fpu/s_rintf.c @@ -23,15 +23,30 @@ float __rintf (float x) { - float two23 = copysignf (0x1.0p23, x); - float r; - - r = x + two23; - r = r - two23; - - /* rint(-0.1) == -0, and in general we'll always have the same sign - as our input. */ - return copysign (r, x); + if (isless (fabsf (x), 16777216.0f)) /* 1 << FLT_MANT_DIG */ + { + /* Note that Alpha S_Floating is stored in registers in a + restricted T_Floating format, so we don't even need to + convert back to S_Floating in the end. The initial + conversion to T_Floating is needed to handle denormals. */ + + float tmp1, tmp2, new_x; + + __asm ("cvtst/s %3,%2\n\t" +#ifdef _IEEE_FP_INEXACT + "cvttq/svid %2,%1\n\t" +#else + "cvttq/svd %2,%1\n\t" +#endif + "cvtqt/d %1,%0\n\t" + : "=f"(new_x), "=&f"(tmp1), "=&f"(tmp2) + : "f"(x)); + + /* rint(-0.1) == -0, and in general we'll always have the same + sign as our input. */ + x = copysignf(new_x, x); + } + return x; } weak_alias (__rintf, rintf) |