about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--sysdeps/arm/fclrexcpt.c10
-rw-r--r--sysdeps/arm/fedisblxcpt.c4
-rw-r--r--sysdeps/arm/feenablxcpt.c14
-rw-r--r--sysdeps/arm/fsetexcptflg.c13
-rw-r--r--sysdeps/arm/setfpucw.c11
6 files changed, 38 insertions, 23 deletions
diff --git a/ChangeLog b/ChangeLog
index 28bc633e37..0b0f61affa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 2014-06-24  Wilco  <wdijkstr@arm.com>
 
+	* sysdeps/arm/fclrexcpt.c (feclearexcept):
+	Optimize to avoid unnecessary FPSCR writes.
+	* sysdeps/arm/fedisblxcpt.c (fedisableexcept): Likewise.
+	* sysdeps/arm/feenablxcpt.c (feenableexcept): Likewise.
+	* sysdeps/arm/fsetexcptflg.c (fesetexceptflag): Likewise.
+	* sysdeps/arm/setfpucw.c (__setfpucw): Likewise.
+
+2014-06-24  Wilco  <wdijkstr@arm.com>
+
 	* sysdeps/arm/fegetround.c (fegetround): Call get_rounding_mode.
 	* sysdeps/arm/feholdexcpt.c (feholdexcept): Call libc_feholdexcept_vfp.
 	* sysdeps/arm/fesetround.c (fesetround): Call libc_fesetround_vfp.
diff --git a/sysdeps/arm/fclrexcpt.c b/sysdeps/arm/fclrexcpt.c
index cbf61a6f4a..31420ed3c7 100644
--- a/sysdeps/arm/fclrexcpt.c
+++ b/sysdeps/arm/fclrexcpt.c
@@ -24,7 +24,7 @@
 int
 feclearexcept (int excepts)
 {
-  fpu_control_t fpscr;
+  fpu_control_t fpscr, new_fpscr;
 
   /* 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;
+  new_fpscr = fpscr & ~excepts;
 
-  /* Clear the relevant bits.  */
-  fpscr = (fpscr & ~FE_ALL_EXCEPT) | (fpscr & FE_ALL_EXCEPT & ~excepts);
-
-  _FPU_SETCW (fpscr);
+  /* Write new exception flags if changed.  */
+  if (new_fpscr != fpscr)
+    _FPU_SETCW (new_fpscr);
 
   return 0;
 }
diff --git a/sysdeps/arm/fedisblxcpt.c b/sysdeps/arm/fedisblxcpt.c
index f2956cd32a..d5e0f0031a 100644
--- a/sysdeps/arm/fedisblxcpt.c
+++ b/sysdeps/arm/fedisblxcpt.c
@@ -35,7 +35,9 @@ fedisableexcept (int excepts)
   excepts &= FE_ALL_EXCEPT;
   new_fpscr = fpscr & ~(excepts << FE_EXCEPT_SHIFT);
 
-  _FPU_SETCW (new_fpscr);
+  /* Write new exceptions if changed.  */
+  if (new_fpscr != fpscr)
+    _FPU_SETCW (new_fpscr);
 
   return (fpscr >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT;
 }
diff --git a/sysdeps/arm/feenablxcpt.c b/sysdeps/arm/feenablxcpt.c
index afd8943638..f54ca6edf4 100644
--- a/sysdeps/arm/feenablxcpt.c
+++ b/sysdeps/arm/feenablxcpt.c
@@ -25,7 +25,7 @@
 int
 feenableexcept (int excepts)
 {
-  fpu_control_t fpscr, new_fpscr;
+  fpu_control_t fpscr, new_fpscr, updated_fpscr;
 
   /* Fail if a VFP unit isn't present.  */
   if (!ARM_HAVE_VFP)
@@ -35,15 +35,15 @@ feenableexcept (int excepts)
   excepts &= FE_ALL_EXCEPT;
   new_fpscr = fpscr | (excepts << FE_EXCEPT_SHIFT);
 
-  _FPU_SETCW (new_fpscr);
-
-  if (excepts != 0)
+  if (new_fpscr != fpscr)
     {
+      _FPU_SETCW (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 & (excepts << FE_EXCEPT_SHIFT))
-	  != (excepts << FE_EXCEPT_SHIFT))
+      _FPU_GETCW (updated_fpscr);
+
+      if (new_fpscr & ~updated_fpscr)
 	return -1;
     }
 
diff --git a/sysdeps/arm/fsetexcptflg.c b/sysdeps/arm/fsetexcptflg.c
index 1a610ff912..28810d3ec8 100644
--- a/sysdeps/arm/fsetexcptflg.c
+++ b/sysdeps/arm/fsetexcptflg.c
@@ -25,19 +25,22 @@
 int
 fesetexceptflag (const fexcept_t *flagp, int excepts)
 {
-  fpu_control_t fpscr;
+  fpu_control_t fpscr, new_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.  */
-  fpscr &= ~(excepts & FE_ALL_EXCEPT);
-  fpscr |= (*flagp & excepts & FE_ALL_EXCEPT);
+  new_fpscr = fpscr & ~excepts;
+  new_fpscr |= *flagp & excepts;
+
+  /* Write new exception flags if changed.  */
+  if (new_fpscr != fpscr)
+    _FPU_SETCW (new_fpscr);
 
-  /* Save state back to the FPU.  */
-  _FPU_SETCW (fpscr);
   return 0;
 }
diff --git a/sysdeps/arm/setfpucw.c b/sysdeps/arm/setfpucw.c
index 7416377f9e..259b020f81 100644
--- a/sysdeps/arm/setfpucw.c
+++ b/sysdeps/arm/setfpucw.c
@@ -24,19 +24,20 @@
 void
 __setfpucw (fpu_control_t set)
 {
-  fpu_control_t fpscr;
+  fpu_control_t fpscr, new_fpscr;
 
   /* 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).  */
-  fpscr &= _FPU_RESERVED;
-  fpscr |= set & ~_FPU_RESERVED;
+  new_fpscr = fpscr & _FPU_RESERVED;
+  new_fpscr |= set & ~_FPU_RESERVED;
 
-  _FPU_SETCW (fpscr);
+  /* Write FPSCR if changed.  */
+  if (new_fpscr != fpscr)
+    _FPU_SETCW (fpscr);
 }