]> sourceware.org Git - glibc.git/commitdiff
[AArch64] Rewrite feupdateenv (BZ 17009).
authorWilco <wdijkstr@arm.com>
Mon, 2 Jun 2014 11:20:17 +0000 (12:20 +0100)
committerMarcus Shawcroft <marcus.shawcroft@arm.com>
Mon, 2 Jun 2014 11:36:34 +0000 (12:36 +0100)
ChangeLog
NEWS
sysdeps/aarch64/fpu/feupdateenv.c

index 62375be14af9817614680d6290a2a09e968c2663..b20156cb0c4ac8897b89d7f5d2ed714f82d17f90 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2014-06-02  Wilco  <wdijkstr@arm.com>
+
+       [BZ #17009]
+       * sysdeps/aarch64/fpu/feupdateenv (feupdateenv):
+       Rewrite to reduce FPCR/FPSR accesses.
+
 2014-06-01  David S. Miller  <davem@davemloft.net>
 
        * sysdeps/sparc/fpu/libm-test-ulps: Update.
diff --git a/NEWS b/NEWS
index 52d5714d44f35e8e4e4adb793c805eb1d3a34517..f6ace19d5f1f41a02dc41faa78ee87e3833d8a10 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -18,7 +18,8 @@ Version 2.20
   16758, 16759, 16760, 16770, 16786, 16789, 16791, 16796, 16799, 16800,
   16815, 16823, 16824, 16831, 16838, 16849, 16854, 16876, 16877, 16878,
   16885, 16888, 16890, 16912, 16915, 16916, 16917, 16922, 16927, 16928,
-  16932, 16943, 16958, 16966, 16967, 16965, 16977, 16978, 16984, 16990.
+  16932, 16943, 16958, 16966, 16967, 16965, 16977, 16978, 16984, 16990,
+  17009.
 
 * The minimum Linux kernel version that this version of the GNU C Library
   can be used with is 2.6.32.
index 6d64a9b72751fafc29e909cb5a739380114b1df7..ac2f6fe7f80283e30a7e73419a6a693398f8d1b8 100644 (file)
 int
 feupdateenv (const fenv_t *envp)
 {
+  fpu_control_t fpcr;
+  fpu_control_t fpcr_new;
+  fpu_control_t updated_fpcr;
   fpu_fpsr_t fpsr;
+  fpu_fpsr_t fpsr_new;
+  int excepts;
 
-  /* Get the current exception state.  */
+  _FPU_GETCW (fpcr);
   _FPU_GETFPSR (fpsr);
+  excepts = fpsr & FE_ALL_EXCEPT;
 
-  /* Install new environment.  */
-  fesetenv (envp);
+  if ((envp != FE_DFL_ENV) && (envp != FE_NOMASK_ENV))
+    {
+      fpcr_new = envp->__fpcr;
+      fpsr_new = envp->__fpsr | excepts;
 
-  /* Raise the saved exceptions.  */
-  feraiseexcept (fpsr & FE_ALL_EXCEPT);
+      if (fpcr != fpcr_new)
+        _FPU_SETCW (fpcr_new);
+
+      if (fpsr != fpsr_new)
+        _FPU_SETFPSR (fpsr_new);
+
+      if (excepts & (fpcr_new >> FE_EXCEPT_SHIFT))
+        return feraiseexcept (excepts);
+
+      return 0;
+    }
+
+  fpcr_new = fpcr & _FPU_RESERVED;
+  fpsr_new = fpsr & (_FPU_FPSR_RESERVED | FE_ALL_EXCEPT);
+
+  if (envp == FE_DFL_ENV)
+    {
+      fpcr_new |= _FPU_DEFAULT;
+      fpsr_new |= _FPU_FPSR_DEFAULT;
+    }
+  else
+    {
+      fpcr_new |= _FPU_FPCR_IEEE;
+      fpsr_new |= _FPU_FPSR_IEEE;
+    }
+
+  _FPU_SETFPSR (fpsr_new);
+
+  if (fpcr != fpcr_new)
+    {
+      _FPU_SETCW (fpcr_new);
+
+      /* Trapping exceptions are optional in AArch64; the relevant enable
+        bits in FPCR are RES0 hence the absence of support can be detected
+        by reading back the FPCR and comparing with the required value.  */
+      _FPU_GETCW (updated_fpcr);
+
+      if (fpcr_new & ~updated_fpcr)
+        return 1;
+    }
+
+  if (excepts & (fpcr_new >> FE_EXCEPT_SHIFT))
+    return feraiseexcept (excepts);
 
   return 0;
 }
This page took 0.124686 seconds and 5 git commands to generate.