diff options
author | Richard Henderson <rth@redhat.com> | 2000-03-20 20:32:11 +0000 |
---|---|---|
committer | Richard Henderson <rth@redhat.com> | 2000-03-20 20:32:11 +0000 |
commit | 9dc874df52f8e7d251e4684cefe95320c31074fd (patch) | |
tree | e8f8c0174e4f00b203efaaa41d40f1852304d2d6 /sysdeps/alpha/fpu | |
parent | cd112ac0a347fe08ba42273a365b5471d3dfca88 (diff) | |
download | glibc-9dc874df52f8e7d251e4684cefe95320c31074fd.tar.gz glibc-9dc874df52f8e7d251e4684cefe95320c31074fd.tar.xz glibc-9dc874df52f8e7d251e4684cefe95320c31074fd.zip |
* sysdeps/alpha/fpu/fraiseexcpt.c: Use get/set_fp_control instead
of arithmetic instructions. * sysdeps/alpha/fpu/s_ceil.c: Use round to -inf instead of playing with the fpcr. Protect from INV exception. * sysdeps/alpha/fpu/s_ceilf.c: Likewise. * sysdeps/alpha/fpu/s_floor.c: Protect from INV exception. * sysdeps/alpha/fpu/s_floorf.c: Likewise. * sysdeps/alpha/fpu/s_copysign.c: New. * sysdeps/alpha/fpu/s_copysignf.c: New. * sysdeps/alpha/fpu/s_fabs.c: New. * sysdeps/alpha/fpu/s_fabsf.c: New. * sysdeps/alpha/fpu/s_rint.c: New. * sysdeps/alpha/fpu/s_rintf.c: New.
Diffstat (limited to 'sysdeps/alpha/fpu')
-rw-r--r-- | sysdeps/alpha/fpu/fraiseexcpt.c | 41 | ||||
-rw-r--r-- | sysdeps/alpha/fpu/s_ceil.c | 36 | ||||
-rw-r--r-- | sysdeps/alpha/fpu/s_ceilf.c | 44 | ||||
-rw-r--r-- | sysdeps/alpha/fpu/s_copysign.c | 33 | ||||
-rw-r--r-- | sysdeps/alpha/fpu/s_copysignf.c | 29 | ||||
-rw-r--r-- | sysdeps/alpha/fpu/s_fabs.c | 37 | ||||
-rw-r--r-- | sysdeps/alpha/fpu/s_fabsf.c | 33 | ||||
-rw-r--r-- | sysdeps/alpha/fpu/s_floor.c | 14 | ||||
-rw-r--r-- | sysdeps/alpha/fpu/s_floorf.c | 13 | ||||
-rw-r--r-- | sysdeps/alpha/fpu/s_rint.c | 50 | ||||
-rw-r--r-- | sysdeps/alpha/fpu/s_rintf.c | 52 |
11 files changed, 294 insertions, 88 deletions
diff --git a/sysdeps/alpha/fpu/fraiseexcpt.c b/sysdeps/alpha/fpu/fraiseexcpt.c index a3e60d02eb..b0eab000cb 100644 --- a/sysdeps/alpha/fpu/fraiseexcpt.c +++ b/sysdeps/alpha/fpu/fraiseexcpt.c @@ -24,43 +24,16 @@ int __feraiseexcept (int excepts) { - double tmp; - double dummy; + unsigned long int tmp; - /* Raise exceptions represented by EXPECTS. But we must raise only - one signal at a time. It is important the if the overflow/underflow - exception and the inexact exception are given at the same time, - the overflow/underflow exception precedes the inexact exception. */ + /* Get the current exception state. */ + tmp = __ieee_get_fp_control (); - /* We do these bits in assembly to be certain GCC doesn't optimize - away something important. */ + /* Set all the bits that were called for. */ + tmp |= (excepts & FE_ALL_EXCEPT); - /* First: invalid exception. */ - if (FE_INVALID & excepts) - /* One example of a invalid operation is 0 * Infinity. */ - __asm__ __volatile__("mult/sui $f31,%1,%0; trapb" - : "=&f" (tmp) : "f" (HUGE_VAL)); - - /* Next: division by zero. */ - if (FE_DIVBYZERO & excepts) - __asm__ __volatile__("cmpteq $f31,$f31,%1; divt/sui %1,$f31,%0; trapb" - : "=&f" (tmp), "=f" (dummy)); - - /* Next: overflow. */ - if (FE_OVERFLOW & excepts) - __asm__ __volatile__("mult/sui %1,%1,%0; trapb" - : "=&f" (tmp) : "f" (DBL_MAX)); - - /* Next: underflow. */ - if (FE_UNDERFLOW & excepts) - __asm__ __volatile__("divt/sui %1,%2,%0; trapb" - : "=&f" (tmp) : "f" (DBL_MIN), - "f" ((double) (1UL << 60))); - - /* Last: inexact. */ - if (FE_INEXACT & excepts) - __asm__ __volatile__("divt/sui %1,%2,%0; trapb" - : "=&f" (tmp) : "f" (1.0), "f" (M_PI)); + /* And store it back. */ + __ieee_set_fp_control (tmp); /* Success. */ return 0; diff --git a/sysdeps/alpha/fpu/s_ceil.c b/sysdeps/alpha/fpu/s_ceil.c index 23491db5ac..f30db008ce 100644 --- a/sysdeps/alpha/fpu/s_ceil.c +++ b/sysdeps/alpha/fpu/s_ceil.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998 Free Software Foundation, Inc. +/* Copyright (C) 1998, 2000 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson. @@ -19,34 +19,30 @@ #include <math.h> +/* Use the -inf rounding mode conversion instructions to implement + ceil, via something akin to -floor(-x). This is much faster than + playing with the fpcr to achieve +inf rounding mode. */ + double __ceil (double x) { - if (x != 0 && fabs (x) < 9007199254740992.0) /* 1 << DBL_MANT_DIG */ + if (isless (fabs (x), 9007199254740992.0)) /* 1 << DBL_MANT_DIG */ { - double tmp1; - unsigned long fpcr0, fpcr1; - unsigned long pinf = 3UL << 58; - - /* Set round to +inf. */ - __asm __volatile("excb; mf_fpcr %0" : "=f"(fpcr0)); - __asm __volatile("mt_fpcr %0; excb" : : "f"(fpcr0 | pinf)); + double tmp1, new_x; - /* Calculate! */ + new_x = -x; + __asm ( #ifdef _IEEE_FP_INEXACT - __asm("cvttq/svid %2,%1\n\tcvtqt/suid %1,%0" - : "=f"(x), "=&f"(tmp1) - : "f"(x)); + "cvttq/svim %2,%1\n\t" #else - __asm("cvttq/svd %2,%1\n\tcvtqt/d %1,%0" - : "=f"(x), "=&f"(tmp1) - : "f"(x)); + "cvttq/svm %2,%1\n\t" #endif + "cvtqt/m %1,%0\n\t" + : "=f"(new_x), "=&f"(tmp1) + : "f"(new_x)); - /* Reset rounding mode, while retaining new exception bits. */ - __asm __volatile("excb; mf_fpcr %0" : "=f"(fpcr1)); - fpcr0 = (fpcr0 & pinf) | (fpcr1 & ~pinf); - __asm __volatile("mt_fpcr %0; excb" : : "f"(fpcr0)); + /* Fix up the negation we did above, as well as handling -0 properly. */ + x = copysign(new_x, x); } return x; } diff --git a/sysdeps/alpha/fpu/s_ceilf.c b/sysdeps/alpha/fpu/s_ceilf.c index 3defaeb01e..35c51a2766 100644 --- a/sysdeps/alpha/fpu/s_ceilf.c +++ b/sysdeps/alpha/fpu/s_ceilf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998 Free Software Foundation, Inc. +/* Copyright (C) 1998, 2000 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson. @@ -19,39 +19,35 @@ #include <math.h> +/* Use the -inf rounding mode conversion instructions to implement + ceil, via something akin to -floor(-x). This is much faster than + playing with the fpcr to achieve +inf rounding mode. */ + float __ceilf (float x) { - if (x != 0 && fabsf (x) < 16777216.0f) /* 1 << FLT_MANT_DIG */ + if (isless (fabsf (x), 16777216.0f)) /* 1 << FLT_MANT_DIG */ { - float tmp1, tmp2; - unsigned long fpcr0, fpcr1; - unsigned long pinf = 3UL << 58; - - /* Set round to +inf. */ - __asm __volatile("excb; mf_fpcr %0" : "=f"(fpcr0)); - __asm __volatile("mt_fpcr %0; excb" : : "f"(fpcr0 | pinf)); + /* 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. */ - /* Calculate! - 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 - __asm("cvtst/s %3,%2\n\tcvttq/svid %2,%1\n\tcvtqt/suid %1,%0" - : "=f"(x), "=&f"(tmp1), "=&f"(tmp2) - : "f"(x)); + "cvttq/svim %2,%1\n\t" #else - __asm("cvtst/s %3,%2\n\tcvttq/svd %2,%1\n\tcvtqt/d %1,%0" - : "=f"(x), "=&f"(tmp1), "=&f"(tmp2) - : "f"(x)); + "cvttq/svm %2,%1\n\t" #endif + "cvtqt/m %1,%0\n\t" + : "=f"(new_x), "=&f"(tmp1), "=&f"(tmp2) + : "f"(new_x)); - /* Reset rounding mode, while retaining new exception bits. */ - __asm __volatile("excb; mf_fpcr %0" : "=f"(fpcr1)); - fpcr0 = (fpcr0 & pinf) | (fpcr1 & ~pinf); - __asm __volatile("mt_fpcr %0; excb" : : "f"(fpcr0)); + /* Fix up the negation we did above, as well as handling -0 properly. */ + x = copysignf(new_x, x); } return x; } diff --git a/sysdeps/alpha/fpu/s_copysign.c b/sysdeps/alpha/fpu/s_copysign.c new file mode 100644 index 0000000000..5c8d827018 --- /dev/null +++ b/sysdeps/alpha/fpu/s_copysign.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <math.h> + +double +__copysign (double x, double y) +{ + __asm ("cpys %1, %2, %0" : "=f" (x) : "f" (y), "f" (x)); + return x; +} + +weak_alias (__copysign, copysign) +#ifdef NO_LONG_DOUBLE +strong_alias (__copysign, __copysignl) +weak_alias (__copysign, copysignl) +#endif diff --git a/sysdeps/alpha/fpu/s_copysignf.c b/sysdeps/alpha/fpu/s_copysignf.c new file mode 100644 index 0000000000..d2c5d886d0 --- /dev/null +++ b/sysdeps/alpha/fpu/s_copysignf.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <math.h> + +float +__copysignf (float x, float y) +{ + __asm ("cpys %1, %2, %0" : "=f" (x) : "f" (y), "f" (x)); + return x; +} + +weak_alias (__copysignf, copysignf) diff --git a/sysdeps/alpha/fpu/s_fabs.c b/sysdeps/alpha/fpu/s_fabs.c new file mode 100644 index 0000000000..fb446d8cb9 --- /dev/null +++ b/sysdeps/alpha/fpu/s_fabs.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <math.h> + +double +__fabs (double x) +{ +#if __GNUC_PREREQ (2, 8) + return __builtin_fabs (x); +#else + __asm ("cpys $f31, %1, %0" : "=f" (x) : "f" (x)); + return x; +#endif +} + +weak_alias (__fabs, fabs) +#ifdef NO_LONG_DOUBLE +strong_alias (__fabs, __fabsl) +weak_alias (__fabs, fabsl) +#endif diff --git a/sysdeps/alpha/fpu/s_fabsf.c b/sysdeps/alpha/fpu/s_fabsf.c new file mode 100644 index 0000000000..ec5390747f --- /dev/null +++ b/sysdeps/alpha/fpu/s_fabsf.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <math.h> + +float +__fabsf (float x) +{ +#if __GNUC_PREREQ (2, 8) + return __builtin_fabsf (x); +#else + __asm ("cpys $f31, %1, %0" : "=f" (x) : "f" (x)); + return x; +#endif +} + +weak_alias (__fabsf, fabsf) diff --git a/sysdeps/alpha/fpu/s_floor.c b/sysdeps/alpha/fpu/s_floor.c index 146e19b35a..b6d01f5947 100644 --- a/sysdeps/alpha/fpu/s_floor.c +++ b/sysdeps/alpha/fpu/s_floor.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. +/* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson. @@ -27,10 +27,10 @@ double __floor (double x) { - /* Check not zero since floor(-0) == -0. */ - if (x != 0 && fabs (x) < 9007199254740992.0) /* 1 << DBL_MANT_DIG */ + if (isless (fabs (x), 9007199254740992.0)) /* 1 << DBL_MANT_DIG */ { - double __tmp1; + double tmp1, new_x; + __asm ( #ifdef _IEEE_FP_INEXACT "cvttq/svim %2,%1\n\t" @@ -38,8 +38,12 @@ __floor (double x) "cvttq/svm %2,%1\n\t" #endif "cvtqt/m %1,%0\n\t" - : "=f"(x), "=&f"(__tmp1) + : "=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; } diff --git a/sysdeps/alpha/fpu/s_floorf.c b/sysdeps/alpha/fpu/s_floorf.c index 9e693642dd..624e7c87b8 100644 --- a/sysdeps/alpha/fpu/s_floorf.c +++ b/sysdeps/alpha/fpu/s_floorf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. +/* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson. @@ -27,15 +27,14 @@ float __floorf (float x) { - /* Check not zero since floor(-0) == -0. */ - if (x != 0 && fabsf (x) < 16777216.0f) /* 1 << FLT_MANT_DIG */ + 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; + float tmp1, tmp2, new_x; __asm ("cvtst/s %3,%2\n\t" #ifdef _IEEE_FP_INEXACT @@ -44,8 +43,12 @@ __floorf (float x) "cvttq/svm %2,%1\n\t" #endif "cvtqt/m %1,%0\n\t" - : "=f"(x), "=&f"(tmp1), "=&f"(tmp2) + : "=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; } diff --git a/sysdeps/alpha/fpu/s_rint.c b/sysdeps/alpha/fpu/s_rint.c new file mode 100644 index 0000000000..7309b4134e --- /dev/null +++ b/sysdeps/alpha/fpu/s_rint.c @@ -0,0 +1,50 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <math.h> + + +double +__rint (double 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) +#ifdef NO_LONG_DOUBLE +strong_alias (__rint, __rintl) +weak_alias (__rint, rintl) +#endif diff --git a/sysdeps/alpha/fpu/s_rintf.c b/sysdeps/alpha/fpu/s_rintf.c new file mode 100644 index 0000000000..044f7e5f7a --- /dev/null +++ b/sysdeps/alpha/fpu/s_rintf.c @@ -0,0 +1,52 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <math.h> + + +float +__rintf (float 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) |