diff options
author | Wilco <wdijkstr@arm.com> | 2014-06-02 12:20:17 +0100 |
---|---|---|
committer | Marcus Shawcroft <marcus.shawcroft@arm.com> | 2014-06-02 12:36:34 +0100 |
commit | c95b3011018893fcc473279768a67a24a73bbef2 (patch) | |
tree | 1f1bb0d68007030ff5bb22a54d62ff621e0abd7a | |
parent | 6b4d7a909ffeb49a7b91ba5d0bac5b4f9c5b6d1b (diff) | |
download | glibc-c95b3011018893fcc473279768a67a24a73bbef2.tar glibc-c95b3011018893fcc473279768a67a24a73bbef2.tar.gz glibc-c95b3011018893fcc473279768a67a24a73bbef2.tar.bz2 glibc-c95b3011018893fcc473279768a67a24a73bbef2.zip |
[AArch64] Rewrite feupdateenv (BZ 17009).
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | sysdeps/aarch64/fpu/feupdateenv.c | 59 |
3 files changed, 62 insertions, 6 deletions
@@ -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. @@ -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. diff --git a/sysdeps/aarch64/fpu/feupdateenv.c b/sysdeps/aarch64/fpu/feupdateenv.c index 6d64a9b727..ac2f6fe7f8 100644 --- a/sysdeps/aarch64/fpu/feupdateenv.c +++ b/sysdeps/aarch64/fpu/feupdateenv.c @@ -22,16 +22,65 @@ 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; } |