yann@1625: http://sources.redhat.com/bugzilla/show_bug.cgi?id=5350 yann@1625: https://bugs.gentoo.org/264335 yann@1625: yann@1625: diff -durN glibc-2.10.1.orig/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_ceil.c glibc-2.10.1/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_ceil.c yann@1625: --- glibc-2.10.1.orig/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_ceil.c 2009-05-16 10:36:20.000000000 +0200 yann@1625: +++ glibc-2.10.1/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_ceil.c 2009-11-13 00:50:59.000000000 +0100 yann@1625: @@ -27,20 +27,25 @@ yann@1625: double yann@1625: __ceil (double x) yann@1625: { yann@1625: - double two52 = copysign (0x1.0p52, x); yann@1625: - double r, tmp; yann@1625: - yann@1625: - __asm ( yann@1625: + if (isless (fabs (x), 9007199254740992.0)) /* 1 << DBL_MANT_DIG */ yann@1625: + { yann@1625: + double tmp1, new_x; yann@1625: + yann@1625: + new_x = -x; yann@1625: + __asm ( yann@1625: #ifdef _IEEE_FP_INEXACT yann@1625: - "addt/suim %2, %3, %1\n\tsubt/suim %1, %3, %0" yann@1625: + "cvttq/svim %2,%1\n\t" yann@1625: #else yann@1625: - "addt/sum %2, %3, %1\n\tsubt/sum %1, %3, %0" yann@1625: + "cvttq/svm %2,%1\n\t" yann@1625: #endif yann@1625: - : "=&f"(r), "=&f"(tmp) yann@1625: - : "f"(-x), "f"(-two52)); yann@1625: + "cvtqt/m %1,%0\n\t" yann@1625: + : "=f"(new_x), "=&f"(tmp1) yann@1625: + : "f"(new_x)); yann@1625: yann@1625: - /* Fix up the negation we did above, as well as handling -0 properly. */ yann@1625: - return copysign (r, x); yann@1625: + /* Fix up the negation we did above, as well as handling -0 properly. */ yann@1625: + x = copysign(new_x, x); yann@1625: + } yann@1625: + return x; yann@1625: } yann@1625: yann@1625: weak_alias (__ceil, ceil) yann@1625: diff -durN glibc-2.10.1.orig/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_ceilf.c glibc-2.10.1/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_ceilf.c yann@1625: --- glibc-2.10.1.orig/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_ceilf.c 2009-05-16 10:36:20.000000000 +0200 yann@1625: +++ glibc-2.10.1/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_ceilf.c 2009-11-13 00:50:59.000000000 +0100 yann@1625: @@ -26,20 +26,30 @@ yann@1625: float yann@1625: __ceilf (float x) yann@1625: { yann@1625: - float two23 = copysignf (0x1.0p23, x); yann@1625: - float r, tmp; yann@1625: - yann@1625: - __asm ( yann@1625: + if (isless (fabsf (x), 16777216.0f)) /* 1 << FLT_MANT_DIG */ yann@1625: + { yann@1625: + /* Note that Alpha S_Floating is stored in registers in a yann@1625: + restricted T_Floating format, so we don't even need to yann@1625: + convert back to S_Floating in the end. The initial yann@1625: + conversion to T_Floating is needed to handle denormals. */ yann@1625: + yann@1625: + float tmp1, tmp2, new_x; yann@1625: + yann@1625: + new_x = -x; yann@1625: + __asm ("cvtst/s %3,%2\n\t" yann@1625: #ifdef _IEEE_FP_INEXACT yann@1625: - "adds/suim %2, %3, %1\n\tsubs/suim %1, %3, %0" yann@1625: + "cvttq/svim %2,%1\n\t" yann@1625: #else yann@1625: - "adds/sum %2, %3, %1\n\tsubs/sum %1, %3, %0" yann@1625: + "cvttq/svm %2,%1\n\t" yann@1625: #endif yann@1625: - : "=&f"(r), "=&f"(tmp) yann@1625: - : "f"(-x), "f"(-two23)); yann@1625: + "cvtqt/m %1,%0\n\t" yann@1625: + : "=f"(new_x), "=&f"(tmp1), "=&f"(tmp2) yann@1625: + : "f"(new_x)); yann@1625: yann@1625: - /* Fix up the negation we did above, as well as handling -0 properly. */ yann@1625: - return copysignf (r, x); yann@1625: + /* Fix up the negation we did above, as well as handling -0 properly. */ yann@1625: + x = copysignf(new_x, x); yann@1625: + } yann@1625: + return x; yann@1625: } yann@1625: yann@1625: weak_alias (__ceilf, ceilf) yann@1625: diff -durN glibc-2.10.1.orig/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_floor.c glibc-2.10.1/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_floor.c yann@1625: --- glibc-2.10.1.orig/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_floor.c 2009-05-16 10:36:20.000000000 +0200 yann@1625: +++ glibc-2.10.1/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_floor.c 2009-11-13 00:50:59.000000000 +0100 yann@1625: @@ -21,26 +21,32 @@ yann@1625: #include yann@1625: yann@1625: yann@1625: -/* Use the -inf rounding mode conversion instructions to implement floor. */ yann@1625: +/* Use the -inf rounding mode conversion instructions to implement yann@1625: + floor. We note when the exponent is large enough that the value yann@1625: + must be integral, as this avoids unpleasant integer overflows. */ yann@1625: yann@1625: double yann@1625: __floor (double x) yann@1625: { yann@1625: - double two52 = copysign (0x1.0p52, x); yann@1625: - double r, tmp; yann@1625: - yann@1625: - __asm ( yann@1625: + if (isless (fabs (x), 9007199254740992.0)) /* 1 << DBL_MANT_DIG */ yann@1625: + { yann@1625: + double tmp1, new_x; yann@1625: + yann@1625: + __asm ( yann@1625: #ifdef _IEEE_FP_INEXACT yann@1625: - "addt/suim %2, %3, %1\n\tsubt/suim %1, %3, %0" yann@1625: + "cvttq/svim %2,%1\n\t" yann@1625: #else yann@1625: - "addt/sum %2, %3, %1\n\tsubt/sum %1, %3, %0" yann@1625: + "cvttq/svm %2,%1\n\t" yann@1625: #endif yann@1625: - : "=&f"(r), "=&f"(tmp) yann@1625: - : "f"(x), "f"(two52)); yann@1625: + "cvtqt/m %1,%0\n\t" yann@1625: + : "=f"(new_x), "=&f"(tmp1) yann@1625: + : "f"(x)); yann@1625: yann@1625: - /* floor(-0) == -0, and in general we'll always have the same yann@1625: - sign as our input. */ yann@1625: - return copysign (r, x); yann@1625: + /* floor(-0) == -0, and in general we'll always have the same yann@1625: + sign as our input. */ yann@1625: + x = copysign(new_x, x); yann@1625: + } yann@1625: + return x; yann@1625: } yann@1625: yann@1625: weak_alias (__floor, floor) yann@1625: diff -durN glibc-2.10.1.orig/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_floorf.c glibc-2.10.1/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_floorf.c yann@1625: --- glibc-2.10.1.orig/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_floorf.c 2009-05-16 10:36:20.000000000 +0200 yann@1625: +++ glibc-2.10.1/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_floorf.c 2009-11-13 00:50:59.000000000 +0100 yann@1625: @@ -20,26 +20,37 @@ yann@1625: #include yann@1625: yann@1625: yann@1625: -/* Use the -inf rounding mode conversion instructions to implement floor. */ yann@1625: +/* Use the -inf rounding mode conversion instructions to implement yann@1625: + floor. We note when the exponent is large enough that the value yann@1625: + must be integral, as this avoids unpleasant integer overflows. */ yann@1625: yann@1625: float yann@1625: __floorf (float x) yann@1625: { yann@1625: - float two23 = copysignf (0x1.0p23, x); yann@1625: - float r, tmp; yann@1625: - yann@1625: - __asm ( yann@1625: + if (isless (fabsf (x), 16777216.0f)) /* 1 << FLT_MANT_DIG */ yann@1625: + { yann@1625: + /* Note that Alpha S_Floating is stored in registers in a yann@1625: + restricted T_Floating format, so we don't even need to yann@1625: + convert back to S_Floating in the end. The initial yann@1625: + conversion to T_Floating is needed to handle denormals. */ yann@1625: + yann@1625: + float tmp1, tmp2, new_x; yann@1625: + yann@1625: + __asm ("cvtst/s %3,%2\n\t" yann@1625: #ifdef _IEEE_FP_INEXACT yann@1625: - "adds/suim %2, %3, %1\n\tsubs/suim %1, %3, %0" yann@1625: + "cvttq/svim %2,%1\n\t" yann@1625: #else yann@1625: - "adds/sum %2, %3, %1\n\tsubs/sum %1, %3, %0" yann@1625: + "cvttq/svm %2,%1\n\t" yann@1625: #endif yann@1625: - : "=&f"(r), "=&f"(tmp) yann@1625: - : "f"(x), "f"(two23)); yann@1625: + "cvtqt/m %1,%0\n\t" yann@1625: + : "=f"(new_x), "=&f"(tmp1), "=&f"(tmp2) yann@1625: + : "f"(x)); yann@1625: yann@1625: - /* floor(-0) == -0, and in general we'll always have the same yann@1625: - sign as our input. */ yann@1625: - return copysignf (r, x); yann@1625: + /* floor(-0) == -0, and in general we'll always have the same yann@1625: + sign as our input. */ yann@1625: + x = copysignf(new_x, x); yann@1625: + } yann@1625: + return x; yann@1625: } yann@1625: yann@1625: weak_alias (__floorf, floorf) yann@1625: diff -durN glibc-2.10.1.orig/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_rint.c glibc-2.10.1/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_rint.c yann@1625: --- glibc-2.10.1.orig/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_rint.c 2009-05-16 10:36:20.000000000 +0200 yann@1625: +++ glibc-2.10.1/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_rint.c 2009-11-13 00:50:59.000000000 +0100 yann@1625: @@ -24,15 +24,24 @@ yann@1625: double yann@1625: __rint (double x) yann@1625: { yann@1625: - double two52 = copysign (0x1.0p52, x); yann@1625: - double r; yann@1625: - yann@1625: - r = x + two52; yann@1625: - r = r - two52; yann@1625: + if (isless (fabs (x), 9007199254740992.0)) /* 1 << DBL_MANT_DIG */ yann@1625: + { yann@1625: + double tmp1, new_x; yann@1625: + __asm ( yann@1625: +#ifdef _IEEE_FP_INEXACT yann@1625: + "cvttq/svid %2,%1\n\t" yann@1625: +#else yann@1625: + "cvttq/svd %2,%1\n\t" yann@1625: +#endif yann@1625: + "cvtqt/d %1,%0\n\t" yann@1625: + : "=f"(new_x), "=&f"(tmp1) yann@1625: + : "f"(x)); yann@1625: yann@1625: - /* rint(-0.1) == -0, and in general we'll always have the same sign yann@1625: - as our input. */ yann@1625: - return copysign (r, x); yann@1625: + /* rint(-0.1) == -0, and in general we'll always have the same yann@1625: + sign as our input. */ yann@1625: + x = copysign(new_x, x); yann@1625: + } yann@1625: + return x; yann@1625: } yann@1625: yann@1625: weak_alias (__rint, rint) yann@1625: diff -durN glibc-2.10.1.orig/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_rintf.c glibc-2.10.1/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_rintf.c yann@1625: --- glibc-2.10.1.orig/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_rintf.c 2009-05-16 10:36:20.000000000 +0200 yann@1625: +++ glibc-2.10.1/glibc-ports-2.10.1/sysdeps/alpha/fpu/s_rintf.c 2009-11-13 00:50:59.000000000 +0100 yann@1625: @@ -23,15 +23,30 @@ yann@1625: float yann@1625: __rintf (float x) yann@1625: { yann@1625: - float two23 = copysignf (0x1.0p23, x); yann@1625: - float r; yann@1625: + if (isless (fabsf (x), 16777216.0f)) /* 1 << FLT_MANT_DIG */ yann@1625: + { yann@1625: + /* Note that Alpha S_Floating is stored in registers in a yann@1625: + restricted T_Floating format, so we don't even need to yann@1625: + convert back to S_Floating in the end. The initial yann@1625: + conversion to T_Floating is needed to handle denormals. */ yann@1625: yann@1625: - r = x + two23; yann@1625: - r = r - two23; yann@1625: + float tmp1, tmp2, new_x; yann@1625: yann@1625: - /* rint(-0.1) == -0, and in general we'll always have the same sign yann@1625: - as our input. */ yann@1625: - return copysign (r, x); yann@1625: + __asm ("cvtst/s %3,%2\n\t" yann@1625: +#ifdef _IEEE_FP_INEXACT yann@1625: + "cvttq/svid %2,%1\n\t" yann@1625: +#else yann@1625: + "cvttq/svd %2,%1\n\t" yann@1625: +#endif yann@1625: + "cvtqt/d %1,%0\n\t" yann@1625: + : "=f"(new_x), "=&f"(tmp1), "=&f"(tmp2) yann@1625: + : "f"(x)); yann@1625: + yann@1625: + /* rint(-0.1) == -0, and in general we'll always have the same yann@1625: + sign as our input. */ yann@1625: + x = copysignf(new_x, x); yann@1625: + } yann@1625: + return x; yann@1625: } yann@1625: yann@1625: weak_alias (__rintf, rintf) yann@1625: diff -durN glibc-2.10.1.orig/ports/sysdeps/alpha/fpu/s_ceil.c glibc-2.10.1/ports/sysdeps/alpha/fpu/s_ceil.c yann@1625: diff -durN glibc-2.10.1.orig/ports/sysdeps/alpha/fpu/s_ceilf.c glibc-2.10.1/ports/sysdeps/alpha/fpu/s_ceilf.c yann@1625: diff -durN glibc-2.10.1.orig/ports/sysdeps/alpha/fpu/s_floor.c glibc-2.10.1/ports/sysdeps/alpha/fpu/s_floor.c yann@1625: diff -durN glibc-2.10.1.orig/ports/sysdeps/alpha/fpu/s_floorf.c glibc-2.10.1/ports/sysdeps/alpha/fpu/s_floorf.c yann@1625: diff -durN glibc-2.10.1.orig/ports/sysdeps/alpha/fpu/s_rint.c glibc-2.10.1/ports/sysdeps/alpha/fpu/s_rint.c yann@1625: diff -durN glibc-2.10.1.orig/ports/sysdeps/alpha/fpu/s_rintf.c glibc-2.10.1/ports/sysdeps/alpha/fpu/s_rintf.c