aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/powerpc/fpu/fenv_private.h
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/powerpc/fpu/fenv_private.h')
-rw-r--r--sysdeps/powerpc/fpu/fenv_private.h38
1 files changed, 36 insertions, 2 deletions
diff --git a/sysdeps/powerpc/fpu/fenv_private.h b/sysdeps/powerpc/fpu/fenv_private.h
index 8c126f9..5ebe6cd 100644
--- a/sysdeps/powerpc/fpu/fenv_private.h
+++ b/sysdeps/powerpc/fpu/fenv_private.h
@@ -132,7 +132,17 @@ libc_fesetenv_ppc (const fenv_t *envp)
static __always_inline void
libc_feresetround_ppc (fenv_t *envp)
{
- __libc_femergeenv_ppc (envp, _FPU_MASK_TRAPS_RN, _FPU_MASK_FRAC_INEX_RET_CC);
+ fenv_union_t new = { .fenv = *envp };
+
+ /* If the old env has no enabled exceptions and the new env has any enabled
+ exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put the
+ hardware into "precise mode" and may cause the FPU to run slower on some
+ hardware. */
+ if ((new.l & _FPU_ALL_TRAPS) != 0)
+ (void) __fe_nomask_env_priv ();
+
+ /* Atomically enable and raise (if appropriate) exceptions set in `new'. */
+ fesetenv_mode (new.fenv);
}
static __always_inline int
@@ -176,9 +186,30 @@ libc_feholdsetround_ppc_ctx (struct rm_ctx *ctx, int r)
{
fenv_union_t old, new;
+ old.fenv = fegetenv_status ();
+
+ new.l = (old.l & ~(FPSCR_ENABLES_MASK|FPSCR_RN_MASK)) | r;
+
+ ctx->env = old.fenv;
+ if (__glibc_unlikely (new.l != old.l))
+ {
+ if ((old.l & _FPU_ALL_TRAPS) != 0)
+ (void) __fe_mask_env ();
+ fesetenv_mode (new.fenv);
+ ctx->updated_status = true;
+ }
+ else
+ ctx->updated_status = false;
+}
+
+static __always_inline void
+libc_feholdsetround_noex_ppc_ctx (struct rm_ctx *ctx, int r)
+{
+ fenv_union_t old, new;
+
old.fenv = fegetenv_register ();
- new.l = (old.l & _FPU_MASK_TRAPS_RN) | r;
+ new.l = (old.l & ~(FPSCR_ENABLES_MASK|FPSCR_RN_MASK)) | r;
ctx->env = old.fenv;
if (__glibc_unlikely (new.l != old.l))
@@ -218,6 +249,9 @@ libc_feresetround_ppc_ctx (struct rm_ctx *ctx)
#define libc_feholdsetround_ctx libc_feholdsetround_ppc_ctx
#define libc_feholdsetroundf_ctx libc_feholdsetround_ppc_ctx
#define libc_feholdsetroundl_ctx libc_feholdsetround_ppc_ctx
+#define libc_feholdsetround_noex_ctx libc_feholdsetround_noex_ppc_ctx
+#define libc_feholdsetround_noexf_ctx libc_feholdsetround_noex_ppc_ctx
+#define libc_feholdsetround_noexl_ctx libc_feholdsetround_noex_ppc_ctx
#define libc_feresetround_ctx libc_feresetround_ppc_ctx
#define libc_feresetroundf_ctx libc_feresetround_ppc_ctx
#define libc_feresetroundl_ctx libc_feresetround_ppc_ctx