Revert "ARM: Improve fenv implementation"
authorMarcus Shawcroft <marcus.shawcroft@arm.com>
Mon, 19 May 2014 08:08:59 +0000 (09:08 +0100)
committerMarcus Shawcroft <marcus.shawcroft@arm.com>
Mon, 19 May 2014 08:08:59 +0000 (09:08 +0100)
This reverts commit c0c08d02c82275353f5c556f935a1a01714d9d7f.

13 files changed:
ChangeLog
sysdeps/arm/fclrexcpt.c
sysdeps/arm/fedisblxcpt.c
sysdeps/arm/feenablxcpt.c
sysdeps/arm/fegetround.c
sysdeps/arm/feholdexcpt.c
sysdeps/arm/fesetenv.c
sysdeps/arm/fesetround.c
sysdeps/arm/feupdateenv.c
sysdeps/arm/fgetexcptflg.c
sysdeps/arm/fsetexcptflg.c
sysdeps/arm/ftestexcept.c
sysdeps/arm/setfpucw.c

index c606b0d..0a9a265 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 
 2014-05-14  Wilco  <wdijkstr@arm.com>
 
 
 2014-05-14  Wilco  <wdijkstr@arm.com>
 
-       * sysdeps/arm/fclrexcpt.c: Optimize to avoid unnecessary FPSCR writes.
-       * sysdeps/arm/fedisblxcpt.c: Likewise.
-       * sysdeps/arm/feenablxcpt.c: Likewise.
-       * sysdeps/arm/fegetround.c: Call (get_rounding_mode).
-       * sysdeps/arm/feholdexcpt.c: Call optimized (libc_feholdexcept_vfp).
-       * sysdeps/arm/fesetenv.c: Special case FE_DFL_ENV and FE_NOMASK_ENV.
-       Call optimized (libc_fesetenv_vfp).
-       * sysdeps/arm/fesetround.c: Call optimized (libc_fesetround_vfp).
-       * sysdeps/arm/feupdateenv.c: Special case FE_DFL_ENV and FE_NOMASK_ENV.
-       Call optimized (libc_feupdateenv_vfp).
-       * sysdeps/arm/fgetexcptflg.c: Call optimized (libc_fetestexcept_vfp).
-       * sysdeps/arm/fsetexcptflg.c: Optimize to avoid unnecessary FPSCR
-       writes.
-       * sysdeps/arm/ftestexcept.c: Call optimized (libc_fetestexcept_vfp).
-       * sysdeps/arm/setfpucw.c: Optimize to avoid unnecessary FPSCR writes.
-
-2014-05-14  Wilco  <wdijkstr@arm.com>
-
        * sysdeps/arm/fclrexcpt.c: Cleanup.
        * sysdeps/arm/fedisblxcpt.c: Cleanup.
        * sysdeps/arm/feenablxcpt.c: Cleanup.
        * sysdeps/arm/fclrexcpt.c: Cleanup.
        * sysdeps/arm/fedisblxcpt.c: Cleanup.
        * sysdeps/arm/feenablxcpt.c: Cleanup.
index 31420ed..cbf61a6 100644 (file)
@@ -24,7 +24,7 @@
 int
 feclearexcept (int excepts)
 {
 int
 feclearexcept (int excepts)
 {
-  fpu_control_t fpscr, new_fpscr;
+  fpu_control_t fpscr;
 
   /* Fail if a VFP unit isn't present unless nothing needs to be done.  */
   if (!ARM_HAVE_VFP)
 
   /* Fail if a VFP unit isn't present unless nothing needs to be done.  */
   if (!ARM_HAVE_VFP)
@@ -32,11 +32,11 @@ feclearexcept (int excepts)
 
   _FPU_GETCW (fpscr);
   excepts &= FE_ALL_EXCEPT;
 
   _FPU_GETCW (fpscr);
   excepts &= FE_ALL_EXCEPT;
-  new_fpscr = fpscr & ~excepts;
 
 
-  /* Write new exception flags if changed.  */
-  if (new_fpscr != fpscr)
-    _FPU_SETCW (new_fpscr);
+  /* Clear the relevant bits.  */
+  fpscr = (fpscr & ~FE_ALL_EXCEPT) | (fpscr & FE_ALL_EXCEPT & ~excepts);
+
+  _FPU_SETCW (fpscr);
 
   return 0;
 }
 
   return 0;
 }
index d5e0f00..f2956cd 100644 (file)
@@ -35,9 +35,7 @@ fedisableexcept (int excepts)
   excepts &= FE_ALL_EXCEPT;
   new_fpscr = fpscr & ~(excepts << FE_EXCEPT_SHIFT);
 
   excepts &= FE_ALL_EXCEPT;
   new_fpscr = fpscr & ~(excepts << FE_EXCEPT_SHIFT);
 
-  /* Write new exceptions if changed.  */
-  if (new_fpscr != fpscr)
-    _FPU_SETCW (new_fpscr);
+  _FPU_SETCW (new_fpscr);
 
   return (fpscr >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT;
 }
 
   return (fpscr >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT;
 }
index e649b2f..afd8943 100644 (file)
@@ -35,15 +35,15 @@ feenableexcept (int excepts)
   excepts &= FE_ALL_EXCEPT;
   new_fpscr = fpscr | (excepts << FE_EXCEPT_SHIFT);
 
   excepts &= FE_ALL_EXCEPT;
   new_fpscr = fpscr | (excepts << FE_EXCEPT_SHIFT);
 
-  if (new_fpscr != fpscr)
-    {
-      _FPU_SETCW (new_fpscr);
+  _FPU_SETCW (new_fpscr);
 
 
+  if (excepts != 0)
+    {
       /* Not all VFP architectures support trapping exceptions, so
         test whether the relevant bits were set and fail if not.  */
       _FPU_GETCW (new_fpscr);
       /* Not all VFP architectures support trapping exceptions, so
         test whether the relevant bits were set and fail if not.  */
       _FPU_GETCW (new_fpscr);
-
-      if (((new_fpscr >> FE_EXCEPT_SHIFT) & excepts) != excepts)
+      if ((new_fpscr & (excepts << FE_EXCEPT_SHIFT))
+         != (excepts << FE_EXCEPT_SHIFT))
        return -1;
     }
 
        return -1;
     }
 
index fbad0b3..1c9c151 100644 (file)
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <get-rounding-mode.h>
+#include <fenv.h>
+#include <fpu_control.h>
+#include <arm-features.h>
 
 
 int
 fegetround (void)
 {
 
 
 int
 fegetround (void)
 {
-  return get_rounding_mode ();
+  fpu_control_t fpscr;
+
+  /* FE_TONEAREST is the only supported rounding mode
+     if a VFP unit isn't present.  */
+  if (!ARM_HAVE_VFP)
+    return FE_TONEAREST;
+
+  _FPU_GETCW (fpscr);
+  return fpscr & FE_TOWARDZERO;
 }
 libm_hidden_def (fegetround)
 }
 libm_hidden_def (fegetround)
index 2d79e0c..258ba66 100644 (file)
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <fenv_private.h>
+#include <fenv.h>
+#include <fpu_control.h>
 #include <arm-features.h>
 
 
 int
 feholdexcept (fenv_t *envp)
 {
 #include <arm-features.h>
 
 
 int
 feholdexcept (fenv_t *envp)
 {
+  fpu_control_t fpscr;
+
   /* Fail if a VFP unit isn't present.  */
   if (!ARM_HAVE_VFP)
     return 1;
 
   /* Fail if a VFP unit isn't present.  */
   if (!ARM_HAVE_VFP)
     return 1;
 
-  libc_feholdexcept_vfp (envp);
+  _FPU_GETCW (fpscr);
+  envp->__cw = fpscr;
+
+  /* Now set all exceptions to non-stop.  */
+  fpscr &= ~(FE_ALL_EXCEPT << FE_EXCEPT_SHIFT);
+
+  /* And clear all exception flags.  */
+  fpscr &= ~FE_ALL_EXCEPT;
+
+  _FPU_SETCW (fpscr);
   return 0;
 }
 
   return 0;
 }
 
index 9e2aa81..62031d5 100644 (file)
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <fenv_private.h>
+#include <fenv.h>
+#include <fpu_control.h>
 #include <arm-features.h>
 
 
 int
 fesetenv (const fenv_t *envp)
 {
 #include <arm-features.h>
 
 
 int
 fesetenv (const fenv_t *envp)
 {
+  fpu_control_t fpscr;
+
   /* Fail if a VFP unit isn't present.  */
   if (!ARM_HAVE_VFP)
     return 1;
 
   /* Fail if a VFP unit isn't present.  */
   if (!ARM_HAVE_VFP)
     return 1;
 
-  if ((envp == FE_DFL_ENV) || (envp == FE_NOMASK_ENV))
-    {
-      fpu_control_t fpscr, new_fpscr;
-
-      _FPU_GETCW (fpscr);
+  _FPU_GETCW (fpscr);
 
 
-      /* Preserve the reserved FPSCR flags.  */
-      new_fpscr = fpscr & _FPU_RESERVED;
+  /* Preserve the reserved FPSCR flags.  */
+  fpscr &= _FPU_RESERVED;
 
 
-      if (envp == FE_DFL_ENV)
-       _FPU_SETCW (new_fpscr | _FPU_DEFAULT);
-      else
-       {
-         _FPU_SETCW (new_fpscr | _FPU_IEEE);
-         /* Not all VFP architectures support trapping exceptions, so
-            test whether the relevant bits were set and fail if not.  */
-         _FPU_GETCW (fpscr);
+  if (envp == FE_DFL_ENV)
+    fpscr |= _FPU_DEFAULT;
+  else if (envp == FE_NOMASK_ENV)
+    fpscr |= _FPU_IEEE;
+  else
+    fpscr |= envp->__cw & ~_FPU_RESERVED;
 
 
-         if ((fpscr & _FPU_IEEE) != _FPU_IEEE)
-           return 1;
-       }
+  _FPU_SETCW (fpscr);
 
 
-      return 0;
+  if (envp == FE_NOMASK_ENV)
+    {
+      /* Not all VFP architectures support trapping exceptions, so
+        test whether the relevant bits were set and fail if not.  */
+      _FPU_GETCW (fpscr);
+      if ((fpscr & _FPU_IEEE) != _FPU_IEEE)
+       return 1;
     }
 
     }
 
-  libc_fesetenv_vfp (envp);
   return 0;
 }
 
   return 0;
 }
 
index f52c50a..d1b92dc 100644 (file)
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <fenv_private.h>
+#include <fenv.h>
+#include <fpu_control.h>
 #include <arm-features.h>
 
 
 int
 fesetround (int round)
 {
 #include <arm-features.h>
 
 
 int
 fesetround (int round)
 {
+  fpu_control_t fpscr;
+
   /* FE_TONEAREST is the only supported rounding mode
      if a VFP unit isn't present.  */
   if (!ARM_HAVE_VFP)
     return (round == FE_TONEAREST) ? 0 : 1;
 
   /* FE_TONEAREST is the only supported rounding mode
      if a VFP unit isn't present.  */
   if (!ARM_HAVE_VFP)
     return (round == FE_TONEAREST) ? 0 : 1;
 
+  /* Fail if the rounding mode is not valid.  */
   if (round & ~FE_TOWARDZERO)
     return 1;
 
   if (round & ~FE_TOWARDZERO)
     return 1;
 
-  libc_fesetround_vfp (round);
+  _FPU_GETCW (fpscr);
+  fpscr = (fpscr & ~FE_TOWARDZERO) | round;
+  _FPU_SETCW (fpscr);
   return 0;
 }
 
   return 0;
 }
 
index 2a7b3ec..55a1502 100644 (file)
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <fenv_private.h>
+#include <fenv.h>
+#include <fpu_control.h>
 #include <arm-features.h>
 
 
 int
 feupdateenv (const fenv_t *envp)
 {
 #include <arm-features.h>
 
 
 int
 feupdateenv (const fenv_t *envp)
 {
-  fenv_t fenv;
+  fpu_control_t fpscr;
 
   /* Fail if a VFP unit isn't present.  */
   if (!ARM_HAVE_VFP)
     return 1;
 
 
   /* Fail if a VFP unit isn't present.  */
   if (!ARM_HAVE_VFP)
     return 1;
 
-  if ((envp == FE_DFL_ENV) || (envp == FE_NOMASK_ENV))
-    {
-      fpu_control_t fpscr;
+  _FPU_GETCW (fpscr);
 
 
-      _FPU_GETCW (fpscr);
+  /* Install new environment.  */
+  fesetenv (envp);
 
 
-      /* Preserve the reserved FPSCR flags.  */
-      fpscr &= _FPU_RESERVED;
-      fpscr |= (envp == FE_DFL_ENV) ? _FPU_DEFAULT : _FPU_IEEE;
-
-      /* Create a valid fenv to pass to libc_feupdateenv_vfp.  */
-      fenv.__cw = fpscr;
-      envp = &fenv;
-    }
-
-  libc_feupdateenv_vfp (envp);
+  /* Raise the saved exceptions.  */
+  feraiseexcept (fpscr & FE_ALL_EXCEPT);
   return 0;
 }
 libm_hidden_def (feupdateenv)
   return 0;
 }
 libm_hidden_def (feupdateenv)
index 994555c..63fdfbf 100644 (file)
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <fenv_private.h>
+#include <fenv.h>
+#include <fpu_control.h>
 #include <arm-features.h>
 
 
 int
 fegetexceptflag (fexcept_t *flagp, int excepts)
 {
 #include <arm-features.h>
 
 
 int
 fegetexceptflag (fexcept_t *flagp, int excepts)
 {
+  fpu_control_t fpscr;
+
   /* Fail if a VFP unit isn't present.  */
   if (!ARM_HAVE_VFP)
     return 1;
 
   /* Fail if a VFP unit isn't present.  */
   if (!ARM_HAVE_VFP)
     return 1;
 
-  *flagp = libc_fetestexcept_vfp (excepts);
+  _FPU_GETCW (fpscr);
+
+  *flagp = fpscr & excepts & FE_ALL_EXCEPT;
   return 0;
 }
   return 0;
 }
index 28810d3..1a610ff 100644 (file)
 int
 fesetexceptflag (const fexcept_t *flagp, int excepts)
 {
 int
 fesetexceptflag (const fexcept_t *flagp, int excepts)
 {
-  fpu_control_t fpscr, new_fpscr;
+  fpu_control_t fpscr;
 
   /* Fail if a VFP unit isn't present unless nothing needs to be done.  */
   if (!ARM_HAVE_VFP)
     return (excepts != 0);
 
   _FPU_GETCW (fpscr);
 
   /* Fail if a VFP unit isn't present unless nothing needs to be done.  */
   if (!ARM_HAVE_VFP)
     return (excepts != 0);
 
   _FPU_GETCW (fpscr);
-  excepts &= FE_ALL_EXCEPT;
 
   /* Set the desired exception mask.  */
 
   /* Set the desired exception mask.  */
-  new_fpscr = fpscr & ~excepts;
-  new_fpscr |= *flagp & excepts;
-
-  /* Write new exception flags if changed.  */
-  if (new_fpscr != fpscr)
-    _FPU_SETCW (new_fpscr);
+  fpscr &= ~(excepts & FE_ALL_EXCEPT);
+  fpscr |= (*flagp & excepts & FE_ALL_EXCEPT);
 
 
+  /* Save state back to the FPU.  */
+  _FPU_SETCW (fpscr);
   return 0;
 }
   return 0;
 }
index 6c5d3a8..de082b2 100644 (file)
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <fenv_private.h>
+#include <fenv.h>
+#include <fpu_control.h>
 #include <arm-features.h>
 
 
 int
 fetestexcept (int excepts)
 {
 #include <arm-features.h>
 
 
 int
 fetestexcept (int excepts)
 {
+  fpu_control_t fpscr;
+
   /* Return no exception flags if a VFP unit isn't present.  */
   if (!ARM_HAVE_VFP)
     return 0;
 
   /* Return no exception flags if a VFP unit isn't present.  */
   if (!ARM_HAVE_VFP)
     return 0;
 
-  return libc_fetestexcept_vfp (excepts);
-}
+  /* Get current exceptions.  */
+  _FPU_GETCW (fpscr);
 
 
+  return fpscr & excepts & FE_ALL_EXCEPT;
+}
 libm_hidden_def (fetestexcept)
 libm_hidden_def (fetestexcept)
index 259b020..7416377 100644 (file)
 void
 __setfpucw (fpu_control_t set)
 {
 void
 __setfpucw (fpu_control_t set)
 {
-  fpu_control_t fpscr, new_fpscr;
+  fpu_control_t fpscr;
 
   /* Do nothing if a VFP unit isn't present.  */
   if (!ARM_HAVE_VFP)
     return;
 
 
   /* Do nothing if a VFP unit isn't present.  */
   if (!ARM_HAVE_VFP)
     return;
 
+  /* Fetch the current control word.  */
   _FPU_GETCW (fpscr);
 
   /* Preserve the reserved bits, and set the rest as the user
      specified (or the default, if the user gave zero).  */
   _FPU_GETCW (fpscr);
 
   /* Preserve the reserved bits, and set the rest as the user
      specified (or the default, if the user gave zero).  */
-  new_fpscr = fpscr & _FPU_RESERVED;
-  new_fpscr |= set & ~_FPU_RESERVED;
+  fpscr &= _FPU_RESERVED;
+  fpscr |= set & ~_FPU_RESERVED;
 
 
-  /* Write FPSCR if changed.  */
-  if (new_fpscr != fpscr)
-    _FPU_SETCW (fpscr);
+  _FPU_SETCW (fpscr);
 }
 }