summaryrefslogtreecommitdiff
path: root/sysdeps/x86_64/fpu/math_private.h
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2012-03-10 08:53:05 -0800
committerRichard Henderson <rth@twiddle.net>2012-03-19 06:50:41 -0700
commit0fe0f1f86f82f9e08ca4d4b85111de03f4c2f876 (patch)
treeb7daee8ebf19cc6f493921a1862408ef166b6b14 /sysdeps/x86_64/fpu/math_private.h
parenteb92c487b35e26aa1e08815c4480d0bc5cc9f370 (diff)
Create and use libc_feupdateenv_test.
We can reduce the number of STMXCSR, and often we can avoid the call to __feraiseexcept.
Diffstat (limited to 'sysdeps/x86_64/fpu/math_private.h')
-rw-r--r--sysdeps/x86_64/fpu/math_private.h28
1 files changed, 24 insertions, 4 deletions
diff --git a/sysdeps/x86_64/fpu/math_private.h b/sysdeps/x86_64/fpu/math_private.h
index 3289afc58b..aa208b2e18 100644
--- a/sysdeps/x86_64/fpu/math_private.h
+++ b/sysdeps/x86_64/fpu/math_private.h
@@ -108,13 +108,33 @@ libc_fesetenv (fenv_t *e)
#define libc_fesetenv libc_fesetenv
#define libc_fesetenvf libc_fesetenv
+static __always_inline int
+libc_feupdateenv_test (fenv_t *e, int ex)
+{
+ unsigned int mxcsr, old_mxcsr, cur_ex;
+ asm volatile (STMXCSR " %0" : "=m" (*&mxcsr));
+ cur_ex = mxcsr & FE_ALL_EXCEPT;
+
+ /* Merge current exceptions with the old environment. */
+ old_mxcsr = e->__mxcsr;
+ mxcsr = old_mxcsr | cur_ex;
+ asm volatile (LDMXCSR " %0" : : "m" (*&mxcsr));
+
+ /* Raise SIGFPE for any new exceptions since the hold. Expect that
+ the normal environment has all exceptions masked. */
+ if (__builtin_expect ((old_mxcsr >> 7) & cur_ex, 0))
+ __feraiseexcept (cur_ex);
+
+ /* Test for exceptions raised since the hold. */
+ return cur_ex & ex;
+}
+#define libc_feupdateenv_test libc_feupdateenv_test
+#define libc_feupdateenv_testf libc_feupdateenv_test
+
static __always_inline void
libc_feupdateenv (fenv_t *e)
{
- unsigned int mxcsr;
- asm volatile (STMXCSR " %0" : "=m" (*&mxcsr));
- asm volatile (LDMXCSR " %0" : : "m" ((e)->__mxcsr));
- __feraiseexcept (mxcsr & FE_ALL_EXCEPT);
+ libc_feupdateenv_test (e, 0);
}
#define libc_feupdateenv libc_feupdateenv
#define libc_feupdateenvf libc_feupdateenv