]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - sysdeps/powerpc/fpu/fenv_private.h
[powerpc] SET_RESTORE_ROUND optimizations and bug fix
[thirdparty/glibc.git] / sysdeps / powerpc / fpu / fenv_private.h
index 877f25bcf24b81c5bf2d085aa324e606a7e732da..92a3e927873783abfbad8d0ae401aef31b658a2b 100644 (file)
@@ -1,5 +1,5 @@
 /* Private floating point rounding and exceptions handling. PowerPC version.
-   Copyright (C) 2013-2017 Free Software Foundation, Inc.
+   Copyright (C) 2013-2019 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
 
    You should have received a copy of the GNU Lesser General Public
    License along with the GNU C Library.  If not, see
-   <http://www.gnu.org/licenses/>.  */
+   <https://www.gnu.org/licenses/>.  */
 
-#ifndef FENV_PRIVATE_H
-#define FENV_PRIVATE_H 1
+#ifndef POWERPC_FENV_PRIVATE_H
+#define POWERPC_FENV_PRIVATE_H 1
 
 #include <fenv.h>
 #include <fenv_libc.h>
                       | _FPU_MASK_XM | _FPU_MASK_IM)
 
 /* Mask the rounding mode bits.  */
-#define _FPU_MASK_RN (~0x3)
+#define _FPU_MASK_RN 0xfffffffffffffffcLL
 
-/* Mask everything but the rounding moded and non-IEEE arithmetic flags.  */
-#define _FPU_MASK_NOT_RN_NI 0xffffffff00000007LL
+/* Mask everything but the rounding modes and non-IEEE arithmetic flags.  */
+#define _FPU_MASK_NOT_RN_NI 0xffffffff00000807LL
 
 /* Mask restore rounding mode and exception enabled.  */
-#define _FPU_MASK_TRAPS_RN 0xffffffff1fffff00LL
+#define _FPU_MASK_TRAPS_RN 0xffffffffffffff00LL
 
-/* Mask exception enable but fraction rounded/inexact and FP result/CC
-   bits.  */
-#define _FPU_MASK_FRAC_INEX_RET_CC 0xffffffff1ff80fff
+/* Mask FP result flags, preserve fraction rounded/inexact bits.  */
+#define _FPU_MASK_FRAC_INEX_RET_CC 0xfffffffffff80fffLL
 
 static __always_inline void
 __libc_feholdbits_ppc (fenv_t *envp, unsigned long long mask,
@@ -133,7 +132,8 @@ 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 };
+  fegetenv_and_set_rn (new.l & FPSCR_RN_MASK);
 }
 
 static __always_inline int
@@ -174,12 +174,21 @@ libc_feupdateenv_ppc (fenv_t *e)
 
 static __always_inline void
 libc_feholdsetround_ppc_ctx (struct rm_ctx *ctx, int r)
+{
+  fenv_union_t old;
+
+  ctx->env = old.fenv = fegetenv_and_set_rn (r);
+  ctx->updated_status = (r != (old.l & FPSCR_RN_MASK));
+}
+
+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))
@@ -219,6 +228,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
@@ -226,4 +238,6 @@ libc_feresetround_ppc_ctx (struct rm_ctx *ctx)
 #define libc_feupdateenvf_ctx            libc_feupdateenv_ppc_ctx
 #define libc_feupdateenvl_ctx            libc_feupdateenv_ppc_ctx
 
+#include_next <fenv_private.h>
+
 #endif