diff options
author | Joseph Myers <joseph@codesourcery.com> | 2018-08-28 20:48:49 +0000 |
---|---|---|
committer | Joseph Myers <joseph@codesourcery.com> | 2018-08-28 20:48:49 +0000 |
commit | ff6b24501f70da7d6375d6f5929262b9509db39e (patch) | |
tree | cee9b22e4bf7880c23718a20e63dc64f659e79d4 | |
parent | 761404b74d9853ce1608195e24f25b78a910591a (diff) | |
download | glibc-ff6b24501f70da7d6375d6f5929262b9509db39e.tar.gz glibc-ff6b24501f70da7d6375d6f5929262b9509db39e.tar.xz glibc-ff6b24501f70da7d6375d6f5929262b9509db39e.zip |
Split fenv_private.h out of math_private.h more consistently.
On some architectures, the parts of math_private.h relating to the floating-point environment are in a separate file fenv_private.h included from math_private.h. As this is purely an architecture-specific convention used by several architectures, however, all such architectures still need their own math_private.h, even if it has nothing to do beyond #include <fenv_private.h> and peculiarity of including the i386 file directly instead of having a shared file in sysdeps/x86. This patch makes the fenv_private.h name an architecture-independent convention in glibc. The include of fenv_private.h from math_private.h becomes architecture-independent (until callers are updated to include fenv_private.h directly so the include from math_private.h is no longer needed). Some architecture math_private.h headers are removed if no longer needed, or renamed to fenv_private.h if all they define belongs in that header; architecture fenv_private.h headers now do require #include_next <fenv_private.h>. The i386 fenv_private.h file moves to sysdeps/x86/fpu/ to reflect how it is actually shared with x86_64. The generic math_private.h gets a new include of <stdbool.h>, as needed for bool in some prototypes in that header (previously that was indirectly included via include/fenv.h, which now only gets included too late in math_private.h, after those prototypes). Tested for x86_64 and x86, and tested with build-many-glibcs.py that installed stripped shared libraries are unchanged by the patch. * sysdeps/aarch64/fpu/fenv_private.h: New file. Based on .... * sysdeps/aarch64/fpu/math_private.h: ... this file. All contents moved to fenv_private.h except for ... (TOINT_INTRINSICS): Kept in math_private.h. (roundtoint): Likewise. (converttoint): Likewise. * sysdeps/arm/fenv_private.h: Change multiple-include guard to [ARM_FENV_PRIVATE_H]. Include next <fenv_private.h>. * sysdeps/arm/math_private.h: Remove. * sysdeps/generic/fenv_private.h: New file. Contents moved from .... * sysdeps/generic/math_private.h: ... this file. Include <stdbool.h>. Do not include <fenv.h> or <get-rounding-mode.h>. Include <fenv_private.h>. Remove functions and macros moved to fenv_private.h. * sysdeps/i386/fpu/math_private.h: Remove. * sysdeps/mips/math_private.h: Move to .... * sysdeps/mips/fpu/fenv_private.h: ... here. Change multiple-include guard to [MIPS_FENV_PRIVATE_H]. Remove [__mips_hard_float] conditional. Include next <fenv_private.h>. * sysdeps/powerpc/fpu/fenv_private.h: Change multiple-include guard to [POWERPC_FENV_PRIVATE_H]. Include next <fenv_private.h>. * sysdeps/powerpc/fpu/math_private.h: Do not include <fenv_private.h>. * sysdeps/riscv/rvf/math_private.h: Move to .... * sysdeps/riscv/rvf/fenv_private.h: ... here. Change multiple-include guard to [RISCV_FENV_PRIVATE_H]. Include next <fenv_private.h>. * sysdeps/sparc/fpu/fenv_private.h: Change multiple-include guard to [SPARC_FENV_PRIVATE_H]. Include next <fenv_private.h>. * sysdeps/sparc/fpu/math_private.h: Remove. * sysdeps/i386/fpu/fenv_private.h: Move to .... * sysdeps/x86/fpu/fenv_private.h: ... here. Change multiple-include guard to [X86_FENV_PRIVATE_H]. Include next <fenv_private.h>. * sysdeps/x86_64/fpu/math_private.h: Do not include <sysdeps/i386/fpu/fenv_private.h>.
-rw-r--r-- | ChangeLog | 40 | ||||
-rw-r--r-- | sysdeps/aarch64/fpu/fenv_private.h | 303 | ||||
-rw-r--r-- | sysdeps/aarch64/fpu/math_private.h | 282 | ||||
-rw-r--r-- | sysdeps/arm/fenv_private.h | 8 | ||||
-rw-r--r-- | sysdeps/arm/math_private.h | 7 | ||||
-rw-r--r-- | sysdeps/generic/fenv_private.h | 417 | ||||
-rw-r--r-- | sysdeps/generic/math_private.h | 395 | ||||
-rw-r--r-- | sysdeps/i386/fpu/math_private.h | 7 | ||||
-rw-r--r-- | sysdeps/mips/fpu/fenv_private.h (renamed from sysdeps/mips/math_private.h) | 108 | ||||
-rw-r--r-- | sysdeps/powerpc/fpu/fenv_private.h | 6 | ||||
-rw-r--r-- | sysdeps/powerpc/fpu/math_private.h | 1 | ||||
-rw-r--r-- | sysdeps/riscv/rvf/fenv_private.h (renamed from sysdeps/riscv/rvf/math_private.h) | 6 | ||||
-rw-r--r-- | sysdeps/sparc/fpu/fenv_private.h | 8 | ||||
-rw-r--r-- | sysdeps/sparc/fpu/math_private.h | 7 | ||||
-rw-r--r-- | sysdeps/x86/fpu/fenv_private.h (renamed from sysdeps/i386/fpu/fenv_private.h) | 8 | ||||
-rw-r--r-- | sysdeps/x86_64/fpu/math_private.h | 1 |
16 files changed, 838 insertions, 766 deletions
diff --git a/ChangeLog b/ChangeLog index ceb3ccc970..cdc9b8c207 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,43 @@ +2018-08-28 Joseph Myers <joseph@codesourcery.com> + + * sysdeps/aarch64/fpu/fenv_private.h: New file. Based on .... + * sysdeps/aarch64/fpu/math_private.h: ... this file. All contents + moved to fenv_private.h except for ... + (TOINT_INTRINSICS): Kept in math_private.h. + (roundtoint): Likewise. + (converttoint): Likewise. + * sysdeps/arm/fenv_private.h: Change multiple-include guard to + [ARM_FENV_PRIVATE_H]. Include next <fenv_private.h>. + * sysdeps/arm/math_private.h: Remove. + * sysdeps/generic/fenv_private.h: New file. Contents moved from + .... + * sysdeps/generic/math_private.h: ... this file. Include + <stdbool.h>. Do not include <fenv.h> or <get-rounding-mode.h>. + Include <fenv_private.h>. Remove functions and macros moved to + fenv_private.h. + * sysdeps/i386/fpu/math_private.h: Remove. + * sysdeps/mips/math_private.h: Move to .... + * sysdeps/mips/fpu/fenv_private.h: ... here. Change + multiple-include guard to [MIPS_FENV_PRIVATE_H]. Remove + [__mips_hard_float] conditional. Include next <fenv_private.h>. + * sysdeps/powerpc/fpu/fenv_private.h: Change multiple-include + guard to [POWERPC_FENV_PRIVATE_H]. Include next <fenv_private.h>. + * sysdeps/powerpc/fpu/math_private.h: Do not include + <fenv_private.h>. + * sysdeps/riscv/rvf/math_private.h: Move to .... + * sysdeps/riscv/rvf/fenv_private.h: ... here. Change + multiple-include guard to [RISCV_FENV_PRIVATE_H]. Include next + <fenv_private.h>. + * sysdeps/sparc/fpu/fenv_private.h: Change multiple-include guard + to [SPARC_FENV_PRIVATE_H]. Include next <fenv_private.h>. + * sysdeps/sparc/fpu/math_private.h: Remove. + * sysdeps/i386/fpu/fenv_private.h: Move to .... + * sysdeps/x86/fpu/fenv_private.h: ... here. Change + multiple-include guard to [X86_FENV_PRIVATE_H]. Include next + <fenv_private.h>. + * sysdeps/x86_64/fpu/math_private.h: Do not include + <sysdeps/i386/fpu/fenv_private.h>. + 2018-08-28 Florian Weimer <fweimer@redhat.com> [BZ #23578] diff --git a/sysdeps/aarch64/fpu/fenv_private.h b/sysdeps/aarch64/fpu/fenv_private.h new file mode 100644 index 0000000000..e4f2483480 --- /dev/null +++ b/sysdeps/aarch64/fpu/fenv_private.h @@ -0,0 +1,303 @@ +/* Private floating point rounding and exceptions handling. AArch64 version. + Copyright (C) 2014-2018 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + 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/>. */ + +#ifndef AARCH64_FENV_PRIVATE_H +#define AARCH64_FENV_PRIVATE_H 1 + +#include <fenv.h> +#include <fpu_control.h> + +static __always_inline void +libc_feholdexcept_aarch64 (fenv_t *envp) +{ + fpu_control_t fpcr; + fpu_control_t new_fpcr; + fpu_fpsr_t fpsr; + fpu_fpsr_t new_fpsr; + + _FPU_GETCW (fpcr); + _FPU_GETFPSR (fpsr); + envp->__fpcr = fpcr; + envp->__fpsr = fpsr; + + /* Clear exception flags and set all exceptions to non-stop. */ + new_fpcr = fpcr & ~(FE_ALL_EXCEPT << FE_EXCEPT_SHIFT); + new_fpsr = fpsr & ~FE_ALL_EXCEPT; + + if (__glibc_unlikely (new_fpcr != fpcr)) + _FPU_SETCW (new_fpcr); + + if (new_fpsr != fpsr) + _FPU_SETFPSR (new_fpsr); +} + +#define libc_feholdexcept libc_feholdexcept_aarch64 +#define libc_feholdexceptf libc_feholdexcept_aarch64 +#define libc_feholdexceptl libc_feholdexcept_aarch64 + +static __always_inline void +libc_fesetround_aarch64 (int round) +{ + fpu_control_t fpcr; + + _FPU_GETCW (fpcr); + + /* Check whether rounding modes are different. */ + round = (fpcr ^ round) & _FPU_FPCR_RM_MASK; + + /* Set new rounding mode if different. */ + if (__glibc_unlikely (round != 0)) + _FPU_SETCW (fpcr ^ round); +} + +#define libc_fesetround libc_fesetround_aarch64 +#define libc_fesetroundf libc_fesetround_aarch64 +#define libc_fesetroundl libc_fesetround_aarch64 + +static __always_inline void +libc_feholdexcept_setround_aarch64 (fenv_t *envp, int round) +{ + fpu_control_t fpcr; + fpu_control_t new_fpcr; + fpu_fpsr_t fpsr; + fpu_fpsr_t new_fpsr; + + _FPU_GETCW (fpcr); + _FPU_GETFPSR (fpsr); + envp->__fpcr = fpcr; + envp->__fpsr = fpsr; + + /* Clear exception flags, set all exceptions to non-stop, + and set new rounding mode. */ + new_fpcr = fpcr & ~((FE_ALL_EXCEPT << FE_EXCEPT_SHIFT) | _FPU_FPCR_RM_MASK); + new_fpcr |= round; + new_fpsr = fpsr & ~FE_ALL_EXCEPT; + + if (__glibc_unlikely (new_fpcr != fpcr)) + _FPU_SETCW (new_fpcr); + + if (new_fpsr != fpsr) + _FPU_SETFPSR (new_fpsr); +} + +#define libc_feholdexcept_setround libc_feholdexcept_setround_aarch64 +#define libc_feholdexcept_setroundf libc_feholdexcept_setround_aarch64 +#define libc_feholdexcept_setroundl libc_feholdexcept_setround_aarch64 + +static __always_inline int +libc_fetestexcept_aarch64 (int ex) +{ + fpu_fpsr_t fpsr; + + _FPU_GETFPSR (fpsr); + return fpsr & ex & FE_ALL_EXCEPT; +} + +#define libc_fetestexcept libc_fetestexcept_aarch64 +#define libc_fetestexceptf libc_fetestexcept_aarch64 +#define libc_fetestexceptl libc_fetestexcept_aarch64 + +static __always_inline void +libc_fesetenv_aarch64 (const fenv_t *envp) +{ + fpu_control_t fpcr; + fpu_control_t new_fpcr; + + _FPU_GETCW (fpcr); + new_fpcr = envp->__fpcr; + + if (__glibc_unlikely (fpcr != new_fpcr)) + _FPU_SETCW (new_fpcr); + + _FPU_SETFPSR (envp->__fpsr); +} + +#define libc_fesetenv libc_fesetenv_aarch64 +#define libc_fesetenvf libc_fesetenv_aarch64 +#define libc_fesetenvl libc_fesetenv_aarch64 +#define libc_feresetround_noex libc_fesetenv_aarch64 +#define libc_feresetround_noexf libc_fesetenv_aarch64 +#define libc_feresetround_noexl libc_fesetenv_aarch64 + +static __always_inline int +libc_feupdateenv_test_aarch64 (const fenv_t *envp, int ex) +{ + fpu_control_t fpcr; + fpu_control_t new_fpcr; + fpu_fpsr_t fpsr; + fpu_fpsr_t new_fpsr; + int excepts; + + _FPU_GETCW (fpcr); + _FPU_GETFPSR (fpsr); + + /* Merge current exception flags with the saved fenv. */ + excepts = fpsr & FE_ALL_EXCEPT; + new_fpcr = envp->__fpcr; + new_fpsr = envp->__fpsr | excepts; + + if (__glibc_unlikely (fpcr != new_fpcr)) + _FPU_SETCW (new_fpcr); + + if (fpsr != new_fpsr) + _FPU_SETFPSR (new_fpsr); + + /* Raise the exceptions if enabled in the new FP state. */ + if (__glibc_unlikely (excepts & (new_fpcr >> FE_EXCEPT_SHIFT))) + __feraiseexcept (excepts); + + return excepts & ex; +} + +#define libc_feupdateenv_test libc_feupdateenv_test_aarch64 +#define libc_feupdateenv_testf libc_feupdateenv_test_aarch64 +#define libc_feupdateenv_testl libc_feupdateenv_test_aarch64 + +static __always_inline void +libc_feupdateenv_aarch64 (const fenv_t *envp) +{ + libc_feupdateenv_test_aarch64 (envp, 0); +} + +#define libc_feupdateenv libc_feupdateenv_aarch64 +#define libc_feupdateenvf libc_feupdateenv_aarch64 +#define libc_feupdateenvl libc_feupdateenv_aarch64 + +static __always_inline void +libc_feholdsetround_aarch64 (fenv_t *envp, int round) +{ + fpu_control_t fpcr; + fpu_fpsr_t fpsr; + + _FPU_GETCW (fpcr); + _FPU_GETFPSR (fpsr); + envp->__fpcr = fpcr; + envp->__fpsr = fpsr; + + /* Check whether rounding modes are different. */ + round = (fpcr ^ round) & _FPU_FPCR_RM_MASK; + + /* Set new rounding mode if different. */ + if (__glibc_unlikely (round != 0)) + _FPU_SETCW (fpcr ^ round); +} + +#define libc_feholdsetround libc_feholdsetround_aarch64 +#define libc_feholdsetroundf libc_feholdsetround_aarch64 +#define libc_feholdsetroundl libc_feholdsetround_aarch64 + +static __always_inline void +libc_feresetround_aarch64 (fenv_t *envp) +{ + fpu_control_t fpcr; + int round; + + _FPU_GETCW (fpcr); + + /* Check whether rounding modes are different. */ + round = (envp->__fpcr ^ fpcr) & _FPU_FPCR_RM_MASK; + + /* Restore the rounding mode if it was changed. */ + if (__glibc_unlikely (round != 0)) + _FPU_SETCW (fpcr ^ round); +} + +#define libc_feresetround libc_feresetround_aarch64 +#define libc_feresetroundf libc_feresetround_aarch64 +#define libc_feresetroundl libc_feresetround_aarch64 + +/* We have support for rounding mode context. */ +#define HAVE_RM_CTX 1 + +static __always_inline void +libc_feholdsetround_aarch64_ctx (struct rm_ctx *ctx, int r) +{ + fpu_control_t fpcr; + int round; + + _FPU_GETCW (fpcr); + ctx->env.__fpcr = fpcr; + + /* Check whether rounding modes are different. */ + round = (fpcr ^ r) & _FPU_FPCR_RM_MASK; + ctx->updated_status = round != 0; + + /* Set the rounding mode if changed. */ + if (__glibc_unlikely (round != 0)) + _FPU_SETCW (fpcr ^ round); +} + +#define libc_feholdsetround_ctx libc_feholdsetround_aarch64_ctx +#define libc_feholdsetroundf_ctx libc_feholdsetround_aarch64_ctx +#define libc_feholdsetroundl_ctx libc_feholdsetround_aarch64_ctx + +static __always_inline void +libc_feresetround_aarch64_ctx (struct rm_ctx *ctx) +{ + /* Restore the rounding mode if updated. */ + if (__glibc_unlikely (ctx->updated_status)) + _FPU_SETCW (ctx->env.__fpcr); +} + +#define libc_feresetround_ctx libc_feresetround_aarch64_ctx +#define libc_feresetroundf_ctx libc_feresetround_aarch64_ctx +#define libc_feresetroundl_ctx libc_feresetround_aarch64_ctx + +static __always_inline void +libc_feholdsetround_noex_aarch64_ctx (struct rm_ctx *ctx, int r) +{ + fpu_control_t fpcr; + fpu_fpsr_t fpsr; + int round; + + _FPU_GETCW (fpcr); + _FPU_GETFPSR (fpsr); + ctx->env.__fpcr = fpcr; + ctx->env.__fpsr = fpsr; + + /* Check whether rounding modes are different. */ + round = (fpcr ^ r) & _FPU_FPCR_RM_MASK; + ctx->updated_status = round != 0; + + /* Set the rounding mode if changed. */ + if (__glibc_unlikely (round != 0)) + _FPU_SETCW (fpcr ^ round); +} + +#define libc_feholdsetround_noex_ctx libc_feholdsetround_noex_aarch64_ctx +#define libc_feholdsetround_noexf_ctx libc_feholdsetround_noex_aarch64_ctx +#define libc_feholdsetround_noexl_ctx libc_feholdsetround_noex_aarch64_ctx + +static __always_inline void +libc_feresetround_noex_aarch64_ctx (struct rm_ctx *ctx) +{ + /* Restore the rounding mode if updated. */ + if (__glibc_unlikely (ctx->updated_status)) + _FPU_SETCW (ctx->env.__fpcr); + + /* Write new FPSR to restore exception flags. */ + _FPU_SETFPSR (ctx->env.__fpsr); +} + +#define libc_feresetround_noex_ctx libc_feresetround_noex_aarch64_ctx +#define libc_feresetround_noexf_ctx libc_feresetround_noex_aarch64_ctx +#define libc_feresetround_noexl_ctx libc_feresetround_noex_aarch64_ctx + +#include_next <fenv_private.h> + +#endif diff --git a/sysdeps/aarch64/fpu/math_private.h b/sysdeps/aarch64/fpu/math_private.h index d2e0abc0b2..6740c1423f 100644 --- a/sysdeps/aarch64/fpu/math_private.h +++ b/sysdeps/aarch64/fpu/math_private.h @@ -1,5 +1,5 @@ -/* Private floating point rounding and exceptions handling. AArch64 version. - Copyright (C) 2014-2018 Free Software Foundation, Inc. +/* Configure optimized libm functions. AArch64 version. + Copyright (C) 2017-2018 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 @@ -19,287 +19,9 @@ #ifndef AARCH64_MATH_PRIVATE_H #define AARCH64_MATH_PRIVATE_H 1 -#include <fenv.h> -#include <fpu_control.h> #include <stdint.h> #include <math.h> -static __always_inline void -libc_feholdexcept_aarch64 (fenv_t *envp) -{ - fpu_control_t fpcr; - fpu_control_t new_fpcr; - fpu_fpsr_t fpsr; - fpu_fpsr_t new_fpsr; - - _FPU_GETCW (fpcr); - _FPU_GETFPSR (fpsr); - envp->__fpcr = fpcr; - envp->__fpsr = fpsr; - - /* Clear exception flags and set all exceptions to non-stop. */ - new_fpcr = fpcr & ~(FE_ALL_EXCEPT << FE_EXCEPT_SHIFT); - new_fpsr = fpsr & ~FE_ALL_EXCEPT; - - if (__glibc_unlikely (new_fpcr != fpcr)) - _FPU_SETCW (new_fpcr); - - if (new_fpsr != fpsr) - _FPU_SETFPSR (new_fpsr); -} - -#define libc_feholdexcept libc_feholdexcept_aarch64 -#define libc_feholdexceptf libc_feholdexcept_aarch64 -#define libc_feholdexceptl libc_feholdexcept_aarch64 - -static __always_inline void -libc_fesetround_aarch64 (int round) -{ - fpu_control_t fpcr; - - _FPU_GETCW (fpcr); - - /* Check whether rounding modes are different. */ - round = (fpcr ^ round) & _FPU_FPCR_RM_MASK; - - /* Set new rounding mode if different. */ - if (__glibc_unlikely (round != 0)) - _FPU_SETCW (fpcr ^ round); -} - -#define libc_fesetround libc_fesetround_aarch64 -#define libc_fesetroundf libc_fesetround_aarch64 -#define libc_fesetroundl libc_fesetround_aarch64 - -static __always_inline void -libc_feholdexcept_setround_aarch64 (fenv_t *envp, int round) -{ - fpu_control_t fpcr; - fpu_control_t new_fpcr; - fpu_fpsr_t fpsr; - fpu_fpsr_t new_fpsr; - - _FPU_GETCW (fpcr); - _FPU_GETFPSR (fpsr); - envp->__fpcr = fpcr; - envp->__fpsr = fpsr; - - /* Clear exception flags, set all exceptions to non-stop, - and set new rounding mode. */ - new_fpcr = fpcr & ~((FE_ALL_EXCEPT << FE_EXCEPT_SHIFT) | _FPU_FPCR_RM_MASK); - new_fpcr |= round; - new_fpsr = fpsr & ~FE_ALL_EXCEPT; - - if (__glibc_unlikely (new_fpcr != fpcr)) - _FPU_SETCW (new_fpcr); - - if (new_fpsr != fpsr) - _FPU_SETFPSR (new_fpsr); -} - -#define libc_feholdexcept_setround libc_feholdexcept_setround_aarch64 -#define libc_feholdexcept_setroundf libc_feholdexcept_setround_aarch64 -#define libc_feholdexcept_setroundl libc_feholdexcept_setround_aarch64 - -static __always_inline int -libc_fetestexcept_aarch64 (int ex) -{ - fpu_fpsr_t fpsr; - - _FPU_GETFPSR (fpsr); - return fpsr & ex & FE_ALL_EXCEPT; -} - -#define libc_fetestexcept libc_fetestexcept_aarch64 -#define libc_fetestexceptf libc_fetestexcept_aarch64 -#define libc_fetestexceptl libc_fetestexcept_aarch64 - -static __always_inline void -libc_fesetenv_aarch64 (const fenv_t *envp) -{ - fpu_control_t fpcr; - fpu_control_t new_fpcr; - - _FPU_GETCW (fpcr); - new_fpcr = envp->__fpcr; - - if (__glibc_unlikely (fpcr != new_fpcr)) - _FPU_SETCW (new_fpcr); - - _FPU_SETFPSR (envp->__fpsr); -} - -#define libc_fesetenv libc_fesetenv_aarch64 -#define libc_fesetenvf libc_fesetenv_aarch64 -#define libc_fesetenvl libc_fesetenv_aarch64 -#define libc_feresetround_noex libc_fesetenv_aarch64 -#define libc_feresetround_noexf libc_fesetenv_aarch64 -#define libc_feresetround_noexl libc_fesetenv_aarch64 - -static __always_inline int -libc_feupdateenv_test_aarch64 (const fenv_t *envp, int ex) -{ - fpu_control_t fpcr; - fpu_control_t new_fpcr; - fpu_fpsr_t fpsr; - fpu_fpsr_t new_fpsr; - int excepts; - - _FPU_GETCW (fpcr); - _FPU_GETFPSR (fpsr); - - /* Merge current exception flags with the saved fenv. */ - excepts = fpsr & FE_ALL_EXCEPT; - new_fpcr = envp->__fpcr; - new_fpsr = envp->__fpsr | excepts; - - if (__glibc_unlikely (fpcr != new_fpcr)) - _FPU_SETCW (new_fpcr); - - if (fpsr != new_fpsr) - _FPU_SETFPSR (new_fpsr); - - /* Raise the exceptions if enabled in the new FP state. */ - if (__glibc_unlikely (excepts & (new_fpcr >> FE_EXCEPT_SHIFT))) - __feraiseexcept (excepts); - - return excepts & ex; -} - -#define libc_feupdateenv_test libc_feupdateenv_test_aarch64 -#define libc_feupdateenv_testf libc_feupdateenv_test_aarch64 -#define libc_feupdateenv_testl libc_feupdateenv_test_aarch64 - -static __always_inline void -libc_feupdateenv_aarch64 (const fenv_t *envp) -{ - libc_feupdateenv_test_aarch64 (envp, 0); -} - -#define libc_feupdateenv libc_feupdateenv_aarch64 -#define libc_feupdateenvf libc_feupdateenv_aarch64 -#define libc_feupdateenvl libc_feupdateenv_aarch64 - -static __always_inline void -libc_feholdsetround_aarch64 (fenv_t *envp, int round) -{ - fpu_control_t fpcr; - fpu_fpsr_t fpsr; - - _FPU_GETCW (fpcr); - _FPU_GETFPSR (fpsr); - envp->__fpcr = fpcr; - envp->__fpsr = fpsr; - - /* Check whether rounding modes are different. */ - round = (fpcr ^ round) & _FPU_FPCR_RM_MASK; - - /* Set new rounding mode if different. */ - if (__glibc_unlikely (round != 0)) - _FPU_SETCW (fpcr ^ round); -} - -#define libc_feholdsetround libc_feholdsetround_aarch64 -#define libc_feholdsetroundf libc_feholdsetround_aarch64 -#define libc_feholdsetroundl libc_feholdsetround_aarch64 - -static __always_inline void -libc_feresetround_aarch64 (fenv_t *envp) -{ - fpu_control_t fpcr; - int round; - - _FPU_GETCW (fpcr); - - /* Check whether rounding modes are different. */ - round = (envp->__fpcr ^ fpcr) & _FPU_FPCR_RM_MASK; - - /* Restore the rounding mode if it was changed. */ - if (__glibc_unlikely (round != 0)) - _FPU_SETCW (fpcr ^ round); -} - -#define libc_feresetround libc_feresetround_aarch64 -#define libc_feresetroundf libc_feresetround_aarch64 -#define libc_feresetroundl libc_feresetround_aarch64 - -/* We have support for rounding mode context. */ -#define HAVE_RM_CTX 1 - -static __always_inline void -libc_feholdsetround_aarch64_ctx (struct rm_ctx *ctx, int r) -{ - fpu_control_t fpcr; - int round; - - _FPU_GETCW (fpcr); - ctx->env.__fpcr = fpcr; - - /* Check whether rounding modes are different. */ - round = (fpcr ^ r) & _FPU_FPCR_RM_MASK; - ctx->updated_status = round != 0; - - /* Set the rounding mode if changed. */ - if (__glibc_unlikely (round != 0)) - _FPU_SETCW (fpcr ^ round); -} - -#define libc_feholdsetround_ctx libc_feholdsetround_aarch64_ctx -#define libc_feholdsetroundf_ctx libc_feholdsetround_aarch64_ctx -#define libc_feholdsetroundl_ctx libc_feholdsetround_aarch64_ctx - -static __always_inline void -libc_feresetround_aarch64_ctx (struct rm_ctx *ctx) -{ - /* Restore the rounding mode if updated. */ - if (__glibc_unlikely (ctx->updated_status)) - _FPU_SETCW (ctx->env.__fpcr); -} - -#define libc_feresetround_ctx libc_feresetround_aarch64_ctx -#define libc_feresetroundf_ctx libc_feresetround_aarch64_ctx -#define libc_feresetroundl_ctx libc_feresetround_aarch64_ctx - -static __always_inline void -libc_feholdsetround_noex_aarch64_ctx (struct rm_ctx *ctx, int r) -{ - fpu_control_t fpcr; - fpu_fpsr_t fpsr; - int round; - - _FPU_GETCW (fpcr); - _FPU_GETFPSR (fpsr); - ctx->env.__fpcr = fpcr; - ctx->env.__fpsr = fpsr; - - /* Check whether rounding modes are different. */ - round = (fpcr ^ r) & _FPU_FPCR_RM_MASK; - ctx->updated_status = round != 0; - - /* Set the rounding mode if changed. */ - if (__glibc_unlikely (round != 0)) - _FPU_SETCW (fpcr ^ round); -} - -#define libc_feholdsetround_noex_ctx libc_feholdsetround_noex_aarch64_ctx -#define libc_feholdsetround_noexf_ctx libc_feholdsetround_noex_aarch64_ctx -#define libc_feholdsetround_noexl_ctx libc_feholdsetround_noex_aarch64_ctx - -static __always_inline void -libc_feresetround_noex_aarch64_ctx (struct rm_ctx *ctx) -{ - /* Restore the rounding mode if updated. */ - if (__glibc_unlikely (ctx->updated_status)) - _FPU_SETCW (ctx->env.__fpcr); - - /* Write new FPSR to restore exception flags. */ - _FPU_SETFPSR (ctx->env.__fpsr); -} - -#define libc_feresetround_noex_ctx libc_feresetround_noex_aarch64_ctx -#define libc_feresetround_noexf_ctx libc_feresetround_noex_aarch64_ctx -#define libc_feresetround_noexl_ctx libc_feresetround_noex_aarch64_ctx - /* Use inline round and lround instructions. */ #define TOINT_INTRINSICS 1 diff --git a/sysdeps/arm/fenv_private.h b/sysdeps/arm/fenv_private.h index 55157c8ae2..b96259dc34 100644 --- a/sysdeps/arm/fenv_private.h +++ b/sysdeps/arm/fenv_private.h @@ -16,8 +16,8 @@ License along with the GNU C Library. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef FENV_PRIVATE_H -#define FENV_PRIVATE_H 1 +#ifndef ARM_FENV_PRIVATE_H +#define ARM_FENV_PRIVATE_H 1 #include <fenv.h> #include <fpu_control.h> @@ -246,4 +246,6 @@ libc_fesetenv_vfp_ctx (struct rm_ctx *ctx) #endif -#endif /* FENV_PRIVATE_H */ +#include_next <fenv_private.h> + +#endif /* ARM_FENV_PRIVATE_H */ diff --git a/sysdeps/arm/math_private.h b/sysdeps/arm/math_private.h deleted file mode 100644 index c175b15601..0000000000 --- a/sysdeps/arm/math_private.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef ARM_MATH_PRIVATE_H -#define ARM_MATH_PRIVATE_H 1 - -#include "fenv_private.h" -#include_next <math_private.h> - -#endif diff --git a/sysdeps/generic/fenv_private.h b/sysdeps/generic/fenv_private.h new file mode 100644 index 0000000000..912d23108f --- /dev/null +++ b/sysdeps/generic/fenv_private.h @@ -0,0 +1,417 @@ +/* Optimized inline fenv.h functions for libm. Generic version. + Copyright (C) 2011-2018 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + 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/>. */ + +#ifndef _FENV_PRIVATE_H +#define _FENV_PRIVATE_H 1 + +#include <fenv.h> +#include <get-rounding-mode.h> + +/* The standards only specify one variant of the fenv.h interfaces. + But at least for some architectures we can be more efficient if we + know what operations are going to be performed. Therefore we + define additional interfaces. By default they refer to the normal + interfaces. */ + +static __always_inline void +default_libc_feholdexcept (fenv_t *e) +{ + (void) __feholdexcept (e); +} + +#ifndef libc_feholdexcept +# define libc_feholdexcept default_libc_feholdexcept +#endif +#ifndef libc_feholdexceptf +# define libc_feholdexceptf default_libc_feholdexcept +#endif +#ifndef libc_feholdexceptl +# define libc_feholdexceptl default_libc_feholdexcept +#endif + +static __always_inline void +default_libc_fesetround (int r) +{ + (void) __fesetround (r); +} + +#ifndef libc_fesetround +# define libc_fesetround default_libc_fesetround +#endif +#ifndef libc_fesetroundf +# define libc_fesetroundf default_libc_fesetround +#endif +#ifndef libc_fesetroundl +# define libc_fesetroundl default_libc_fesetround +#endif + +static __always_inline void +default_libc_feholdexcept_setround (fenv_t *e, int r) +{ + __feholdexcept (e); + __fesetround (r); +} + +#ifndef libc_feholdexcept_setround +# define libc_feholdexcept_setround default_libc_feholdexcept_setround +#endif +#ifndef libc_feholdexcept_setroundf +# define libc_feholdexcept_setroundf default_libc_feholdexcept_setround +#endif +#ifndef libc_feholdexcept_setroundl +# define libc_feholdexcept_setroundl default_libc_feholdexcept_setround +#endif + +#ifndef libc_feholdsetround_53bit +# define libc_feholdsetround_53bit libc_feholdsetround +#endif + +#ifndef libc_fetestexcept +# define libc_fetestexcept fetestexcept +#endif +#ifndef libc_fetestexceptf +# define libc_fetestexceptf fetestexcept +#endif +#ifndef libc_fetestexceptl +# define libc_fetestexceptl fetestexcept +#endif + +static __always_inline void +default_libc_fesetenv (fenv_t *e) +{ + (void) __fesetenv (e); +} + +#ifndef libc_fesetenv +# define libc_fesetenv default_libc_fesetenv +#endif +#ifndef libc_fesetenvf +# define libc_fesetenvf default_libc_fesetenv +#endif +#ifndef libc_fesetenvl +# define libc_fesetenvl default_libc_fesetenv +#endif + +static __always_inline void +default_libc_feupdateenv (fenv_t *e) +{ + (void) __feupdateenv (e); +} + +#ifndef libc_feupdateenv +# define libc_feupdateenv default_libc_feupdateenv +#endif +#ifndef libc_feupdateenvf +# define libc_feupdateenvf default_libc_feupdateenv +#endif +#ifndef libc_feupdateenvl +# define libc_feupdateenvl default_libc_feupdateenv +#endif + +#ifndef libc_feresetround_53bit +# define libc_feresetround_53bit libc_feresetround +#endif + +static __always_inline int +default_libc_feupdateenv_test (fenv_t *e, int ex) +{ + int ret = fetestexcept (ex); + __feupdateenv (e); + return ret; +} + +#ifndef libc_feupdateenv_test +# define libc_feupdateenv_test default_libc_feupdateenv_test +#endif +#ifndef libc_feupdateenv_testf +# define libc_feupdateenv_testf default_libc_feupdateenv_test +#endif +#ifndef libc_feupdateenv_testl +# define libc_feupdateenv_testl default_libc_feupdateenv_test +#endif + +/* Save and set the rounding mode. The use of fenv_t to store the old mode + allows a target-specific version of this function to avoid converting the + rounding mode from the fpu format. By default we have no choice but to + manipulate the entire env. */ + +#ifndef libc_feholdsetround +# define libc_feholdsetround libc_feholdexcept_setround +#endif +#ifndef libc_feholdsetroundf +# define libc_feholdsetroundf libc_feholdexcept_setroundf +#endif +#ifndef libc_feholdsetroundl +# define libc_feholdsetroundl libc_feholdexcept_setroundl +#endif + +/* ... and the reverse. */ + +#ifndef libc_feresetround +# define libc_feresetround libc_feupdateenv +#endif +#ifndef libc_feresetroundf +# define libc_feresetroundf libc_feupdateenvf +#endif +#ifndef libc_feresetroundl +# define libc_feresetroundl libc_feupdateenvl +#endif + +/* ... and a version that also discards exceptions. */ + +#ifndef libc_feresetround_noex +# define libc_feresetround_noex libc_fesetenv +#endif +#ifndef libc_feresetround_noexf +# define libc_feresetround_noexf libc_fesetenvf +#endif +#ifndef libc_feresetround_noexl +# define libc_feresetround_noexl libc_fesetenvl +#endif + +#ifndef HAVE_RM_CTX +# define HAVE_RM_CTX 0 +#endif + + +/* Default implementation using standard fenv functions. + Avoid unnecessary rounding mode changes by first checking the + current rounding mode. Note the use of __glibc_unlikely is + important for performance. */ + +static __always_inline void +default_libc_feholdsetround_ctx (struct rm_ctx *ctx, int round) +{ + ctx->updated_status = false; + + /* Update rounding mode only if different. */ + if (__glibc_unlikely (round != get_rounding_mode ())) + { + ctx->updated_status = true; + __fegetenv (&ctx->env); + __fesetround (round); + } +} + +static __always_inline void +default_libc_feresetround_ctx (struct rm_ctx *ctx) +{ + /* Restore the rounding mode if updated. */ + if (__glibc_unlikely (ctx->updated_status)) + __feupdateenv (&ctx->env); +} + +static __always_inline void +default_libc_feholdsetround_noex_ctx (struct rm_ctx *ctx, int round) +{ + /* Save exception flags and rounding mode, and disable exception + traps. */ + __feholdexcept (&ctx->env); + + /* Update rounding mode only if different. */ + if (__glibc_unlikely (round != get_rounding_mode ())) + __fesetround (round); +} + +static __always_inline void +default_libc_feresetround_noex_ctx (struct rm_ctx *ctx) +{ + /* Restore exception flags and rounding mode. */ + __fesetenv (&ctx->env); +} + +#if HAVE_RM_CTX +/* Set/Restore Rounding Modes only when necessary. If defined, these functions + set/restore floating point state only if the state needed within the lexical + block is different from the current state. This saves a lot of time when + the floating point unit is much slower than the fixed point units. */ + +# ifndef libc_feholdsetround_noex_ctx +# define libc_feholdsetround_noex_ctx libc_feholdsetround_ctx +# endif +# ifndef libc_feholdsetround_noexf_ctx +# define libc_feholdsetround_noexf_ctx libc_feholdsetroundf_ctx +# endif +# ifndef libc_feholdsetround_noexl_ctx +# define libc_feholdsetround_noexl_ctx libc_feholdsetroundl_ctx +# endif + +# ifndef libc_feresetround_noex_ctx +# define libc_feresetround_noex_ctx libc_fesetenv_ctx +# endif +# ifndef libc_feresetround_noexf_ctx +# define libc_feresetround_noexf_ctx libc_fesetenvf_ctx +# endif +# ifndef libc_feresetround_noexl_ctx +# define libc_feresetround_noexl_ctx libc_fesetenvl_ctx +# endif + +#else + +# define libc_feholdsetround_ctx default_libc_feholdsetround_ctx +# define libc_feresetround_ctx default_libc_feresetround_ctx +# define libc_feholdsetround_noex_ctx default_libc_feholdsetround_noex_ctx +# define libc_feresetround_noex_ctx default_libc_feresetround_noex_ctx + +# define libc_feholdsetroundf_ctx libc_feholdsetround_ctx +# define libc_feholdsetroundl_ctx libc_feholdsetround_ctx +# define libc_feresetroundf_ctx libc_feresetround_ctx +# define libc_feresetroundl_ctx libc_feresetround_ctx + +# define libc_feholdsetround_noexf_ctx libc_feholdsetround_noex_ctx +# define libc_feholdsetround_noexl_ctx libc_feholdsetround_noex_ctx +# define libc_feresetround_noexf_ctx libc_feresetround_noex_ctx +# define libc_feresetround_noexl_ctx libc_feresetround_noex_ctx + +#endif + +#ifndef libc_feholdsetround_53bit_ctx +# define libc_feholdsetround_53bit_ctx libc_feholdsetround_ctx +#endif +#ifndef libc_feresetround_53bit_ctx +# define libc_feresetround_53bit_ctx libc_feresetround_ctx +#endif + +#define SET_RESTORE_ROUND_GENERIC(RM,ROUNDFUNC,CLEANUPFUNC) \ + struct rm_ctx ctx __attribute__((cleanup (CLEANUPFUNC ## _ctx))); \ + ROUNDFUNC ## _ctx (&ctx, (RM)) + +/* Set the rounding mode within a lexical block. Restore the rounding mode to + the value at the start of the block. The exception mode must be preserved. + Exceptions raised within the block must be set in the exception flags. + Non-stop mode may be enabled inside the block. */ + +#define SET_RESTORE_ROUND(RM) \ + SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround, libc_feresetround) +#define SET_RESTORE_ROUNDF(RM) \ + SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundf, libc_feresetroundf) +#define SET_RESTORE_ROUNDL(RM) \ + SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundl, libc_feresetroundl) + +/* Set the rounding mode within a lexical block. Restore the rounding mode to + the value at the start of the block. The exception mode must be preserved. + Exceptions raised within the block must be discarded, and exception flags + are restored to the value at the start of the block. + Non-stop mode must be enabled inside the block. */ + +#define SET_RESTORE_ROUND_NOEX(RM) \ + SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noex, \ + libc_feresetround_noex) +#define SET_RESTORE_ROUND_NOEXF(RM) \ + SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noexf, \ + libc_feresetround_noexf) +#define SET_RESTORE_ROUND_NOEXL(RM) \ + SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noexl, \ + libc_feresetround_noexl) + +/* Like SET_RESTORE_ROUND, but also set rounding precision to 53 bits. */ +#define SET_RESTORE_ROUND_53BIT(RM) \ + SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_53bit, \ + libc_feresetround_53bit) + +/* When no floating-point exceptions are defined in <fenv.h>, make + feraiseexcept ignore its argument so that unconditional + feraiseexcept calls do not cause errors for undefined exceptions. + Define it to expand to a void expression so that any calls testing + the result of feraiseexcept do produce errors. */ +#if FE_ALL_EXCEPT == 0 +# define feraiseexcept(excepts) ((void) 0) +# define __feraiseexcept(excepts) ((void) 0) +#endif + +/* Similarly, most <fenv.h> functions have trivial implementations in + the absence of support for floating-point exceptions and rounding + modes. */ + +#if !FE_HAVE_ROUNDING_MODES +# if FE_ALL_EXCEPT == 0 +extern inline int +fegetenv (fenv_t *__e) +{ + return 0; +} + +extern inline int +__fegetenv (fenv_t *__e) +{ + return 0; +} + +extern inline int +feholdexcept (fenv_t *__e) +{ + return 0; +} + +extern inline int +__feholdexcept (fenv_t *__e) +{ + return 0; +} + +extern inline int +fesetenv (const fenv_t *__e) +{ + return 0; +} + +extern inline int +__fesetenv (const fenv_t *__e) +{ + return 0; +} + +extern inline int +feupdateenv (const fenv_t *__e) +{ + return 0; +} + +extern inline int +__feupdateenv (const fenv_t *__e) +{ + return 0; +} +# endif + +extern inline int +fegetround (void) +{ + return FE_TONEAREST; +} + +extern inline int +__fegetround (void) +{ + return FE_TONEAREST; +} + +extern inline int +fesetround (int __d) +{ + return 0; +} + +extern inline int +__fesetround (int __d) +{ + return 0; +} +#endif + +#endif /* fenv_private.h. */ diff --git a/sysdeps/generic/math_private.h b/sysdeps/generic/math_private.h index 1212abaf47..936e3af568 100644 --- a/sysdeps/generic/math_private.h +++ b/sysdeps/generic/math_private.h @@ -17,10 +17,9 @@ #define _MATH_PRIVATE_H_ #include <endian.h> +#include <stdbool.h> #include <stdint.h> #include <sys/types.h> -#include <fenv.h> -#include <get-rounding-mode.h> /* Gather machine dependent _Floatn support. */ #include <bits/floatn.h> @@ -262,396 +261,6 @@ extern double __mpsin (double __x, double __dx, bool __range_reduce); extern double __mpcos (double __x, double __dx, bool __range_reduce); extern void __docos (double __x, double __dx, double __v[]); -/* The standards only specify one variant of the fenv.h interfaces. - But at least for some architectures we can be more efficient if we - know what operations are going to be performed. Therefore we - define additional interfaces. By default they refer to the normal - interfaces. */ - -static __always_inline void -default_libc_feholdexcept (fenv_t *e) -{ - (void) __feholdexcept (e); -} - -#ifndef libc_feholdexcept -# define libc_feholdexcept default_libc_feholdexcept -#endif -#ifndef libc_feholdexceptf -# define libc_feholdexceptf default_libc_feholdexcept -#endif -#ifndef libc_feholdexceptl -# define libc_feholdexceptl default_libc_feholdexcept -#endif - -static __always_inline void -default_libc_fesetround (int r) -{ - (void) __fesetround (r); -} - -#ifndef libc_fesetround -# define libc_fesetround default_libc_fesetround -#endif -#ifndef libc_fesetroundf -# define libc_fesetroundf default_libc_fesetround -#endif -#ifndef libc_fesetroundl -# define libc_fesetroundl default_libc_fesetround -#endif - -static __always_inline void -default_libc_feholdexcept_setround (fenv_t *e, int r) -{ - __feholdexcept (e); - __fesetround (r); -} - -#ifndef libc_feholdexcept_setround -# define libc_feholdexcept_setround default_libc_feholdexcept_setround -#endif -#ifndef libc_feholdexcept_setroundf -# define libc_feholdexcept_setroundf default_libc_feholdexcept_setround -#endif -#ifndef libc_feholdexcept_setroundl -# define libc_feholdexcept_setroundl default_libc_feholdexcept_setround -#endif - -#ifndef libc_feholdsetround_53bit -# define libc_feholdsetround_53bit libc_feholdsetround -#endif - -#ifndef libc_fetestexcept -# define libc_fetestexcept fetestexcept -#endif -#ifndef libc_fetestexceptf -# define libc_fetestexceptf fetestexcept -#endif -#ifndef libc_fetestexceptl -# define libc_fetestexceptl fetestexcept -#endif - -static __always_inline void -default_libc_fesetenv (fenv_t *e) -{ - (void) __fesetenv (e); -} - -#ifndef libc_fesetenv -# define libc_fesetenv default_libc_fesetenv -#endif -#ifndef libc_fesetenvf -# define libc_fesetenvf default_libc_fesetenv -#endif -#ifndef libc_fesetenvl -# define libc_fesetenvl default_libc_fesetenv -#endif - -static __always_inline void -default_libc_feupdateenv (fenv_t *e) -{ - (void) __feupdateenv (e); -} - -#ifndef libc_feupdateenv -# define libc_feupdateenv default_libc_feupdateenv -#endif -#ifndef libc_feupdateenvf -# define libc_feupdateenvf default_libc_feupdateenv -#endif -#ifndef libc_feupdateenvl -# define libc_feupdateenvl default_libc_feupdateenv -#endif - -#ifndef libc_feresetround_53bit -# define libc_feresetround_53bit libc_feresetround -#endif - -static __always_inline int -default_libc_feupdateenv_test (fenv_t *e, int ex) -{ - int ret = fetestexcept (ex); - __feupdateenv (e); - return ret; -} - -#ifndef libc_feupdateenv_test -# define libc_feupdateenv_test default_libc_feupdateenv_test -#endif -#ifndef libc_feupdateenv_testf -# define libc_feupdateenv_testf default_libc_feupdateenv_test -#endif -#ifndef libc_feupdateenv_testl -# define libc_feupdateenv_testl default_libc_feupdateenv_test -#endif - -/* Save and set the rounding mode. The use of fenv_t to store the old mode - allows a target-specific version of this function to avoid converting the - rounding mode from the fpu format. By default we have no choice but to - manipulate the entire env. */ - -#ifndef libc_feholdsetround -# define libc_feholdsetround libc_feholdexcept_setround -#endif -#ifndef libc_feholdsetroundf -# define libc_feholdsetroundf libc_feholdexcept_setroundf -#endif -#ifndef libc_feholdsetroundl -# define libc_feholdsetroundl libc_feholdexcept_setroundl -#endif - -/* ... and the reverse. */ - -#ifndef libc_feresetround -# define libc_feresetround libc_feupdateenv -#endif -#ifndef libc_feresetroundf -# define libc_feresetroundf libc_feupdateenvf -#endif -#ifndef libc_feresetroundl -# define libc_feresetroundl libc_feupdateenvl -#endif - -/* ... and a version that also discards exceptions. */ - -#ifndef libc_feresetround_noex -# define libc_feresetround_noex libc_fesetenv -#endif -#ifndef libc_feresetround_noexf -# define libc_feresetround_noexf libc_fesetenvf -#endif -#ifndef libc_feresetround_noexl -# define libc_feresetround_noexl libc_fesetenvl -#endif - -#ifndef HAVE_RM_CTX -# define HAVE_RM_CTX 0 -#endif - - -/* Default implementation using standard fenv functions. - Avoid unnecessary rounding mode changes by first checking the - current rounding mode. Note the use of __glibc_unlikely is - important for performance. */ - -static __always_inline void -default_libc_feholdsetround_ctx (struct rm_ctx *ctx, int round) -{ - ctx->updated_status = false; - - /* Update rounding mode only if different. */ - if (__glibc_unlikely (round != get_rounding_mode ())) - { - ctx->updated_status = true; - __fegetenv (&ctx->env); - __fesetround (round); - } -} - -static __always_inline void -default_libc_feresetround_ctx (struct rm_ctx *ctx) -{ - /* Restore the rounding mode if updated. */ - if (__glibc_unlikely (ctx->updated_status)) - __feupdateenv (&ctx->env); -} - -static __always_inline void -default_libc_feholdsetround_noex_ctx (struct rm_ctx *ctx, int round) -{ - /* Save exception flags and rounding mode, and disable exception - traps. */ - __feholdexcept (&ctx->env); - - /* Update rounding mode only if different. */ - if (__glibc_unlikely (round != get_rounding_mode ())) - __fesetround (round); -} - -static __always_inline void -default_libc_feresetround_noex_ctx (struct rm_ctx *ctx) -{ - /* Restore exception flags and rounding mode. */ - __fesetenv (&ctx->env); -} - -#if HAVE_RM_CTX -/* Set/Restore Rounding Modes only when necessary. If defined, these functions - set/restore floating point state only if the state needed within the lexical - block is different from the current state. This saves a lot of time when - the floating point unit is much slower than the fixed point units. */ - -# ifndef libc_feholdsetround_noex_ctx -# define libc_feholdsetround_noex_ctx libc_feholdsetround_ctx -# endif -# ifndef libc_feholdsetround_noexf_ctx -# define libc_feholdsetround_noexf_ctx libc_feholdsetroundf_ctx -# endif -# ifndef libc_feholdsetround_noexl_ctx -# define libc_feholdsetround_noexl_ctx libc_feholdsetroundl_ctx -# endif - -# ifndef libc_feresetround_noex_ctx -# define libc_feresetround_noex_ctx libc_fesetenv_ctx -# endif -# ifndef libc_feresetround_noexf_ctx -# define libc_feresetround_noexf_ctx libc_fesetenvf_ctx -# endif -# ifndef libc_feresetround_noexl_ctx -# define libc_feresetround_noexl_ctx libc_fesetenvl_ctx -# endif - -#else - -# define libc_feholdsetround_ctx default_libc_feholdsetround_ctx -# define libc_feresetround_ctx default_libc_feresetround_ctx -# define libc_feholdsetround_noex_ctx default_libc_feholdsetround_noex_ctx -# define libc_feresetround_noex_ctx default_libc_feresetround_noex_ctx - -# define libc_feholdsetroundf_ctx libc_feholdsetround_ctx -# define libc_feholdsetroundl_ctx libc_feholdsetround_ctx -# define libc_feresetroundf_ctx libc_feresetround_ctx -# define libc_feresetroundl_ctx libc_feresetround_ctx - -# define libc_feholdsetround_noexf_ctx libc_feholdsetround_noex_ctx -# define libc_feholdsetround_noexl_ctx libc_feholdsetround_noex_ctx -# define libc_feresetround_noexf_ctx libc_feresetround_noex_ctx -# define libc_feresetround_noexl_ctx libc_feresetround_noex_ctx - -#endif - -#ifndef libc_feholdsetround_53bit_ctx -# define libc_feholdsetround_53bit_ctx libc_feholdsetround_ctx -#endif -#ifndef libc_feresetround_53bit_ctx -# define libc_feresetround_53bit_ctx libc_feresetround_ctx -#endif - -#define SET_RESTORE_ROUND_GENERIC(RM,ROUNDFUNC,CLEANUPFUNC) \ - struct rm_ctx ctx __attribute__((cleanup (CLEANUPFUNC ## _ctx))); \ - ROUNDFUNC ## _ctx (&ctx, (RM)) - -/* Set the rounding mode within a lexical block. Restore the rounding mode to - the value at the start of the block. The exception mode must be preserved. - Exceptions raised within the block must be set in the exception flags. - Non-stop mode may be enabled inside the block. */ - -#define SET_RESTORE_ROUND(RM) \ - SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround, libc_feresetround) -#define SET_RESTORE_ROUNDF(RM) \ - SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundf, libc_feresetroundf) -#define SET_RESTORE_ROUNDL(RM) \ - SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetroundl, libc_feresetroundl) - -/* Set the rounding mode within a lexical block. Restore the rounding mode to - the value at the start of the block. The exception mode must be preserved. - Exceptions raised within the block must be discarded, and exception flags - are restored to the value at the start of the block. - Non-stop mode must be enabled inside the block. */ - -#define SET_RESTORE_ROUND_NOEX(RM) \ - SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noex, \ - libc_feresetround_noex) -#define SET_RESTORE_ROUND_NOEXF(RM) \ - SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noexf, \ - libc_feresetround_noexf) -#define SET_RESTORE_ROUND_NOEXL(RM) \ - SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_noexl, \ - libc_feresetround_noexl) - -/* Like SET_RESTORE_ROUND, but also set rounding precision to 53 bits. */ -#define SET_RESTORE_ROUND_53BIT(RM) \ - SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_53bit, \ - libc_feresetround_53bit) - -/* When no floating-point exceptions are defined in <fenv.h>, make - feraiseexcept ignore its argument so that unconditional - feraiseexcept calls do not cause errors for undefined exceptions. - Define it to expand to a void expression so that any calls testing - the result of feraiseexcept do produce errors. */ -#if FE_ALL_EXCEPT == 0 -# define feraiseexcept(excepts) ((void) 0) -# define __feraiseexcept(excepts) ((void) 0) -#endif - -/* Similarly, most <fenv.h> functions have trivial implementations in - the absence of support for floating-point exceptions and rounding - modes. */ - -#if !FE_HAVE_ROUNDING_MODES -# if FE_ALL_EXCEPT == 0 -extern inline int -fegetenv (fenv_t *__e) -{ - return 0; -} - -extern inline int -__fegetenv (fenv_t *__e) -{ - return 0; -} - -extern inline int -feholdexcept (fenv_t *__e) -{ - return 0; -} - -extern inline int -__feholdexcept (fenv_t *__e) -{ - return 0; -} - -extern inline int -fesetenv (const fenv_t *__e) -{ - return 0; -} - -extern inline int -__fesetenv (const fenv_t *__e) -{ - return 0; -} - -extern inline int -feupdateenv (const fenv_t *__e) -{ - return 0; -} - -extern inline int -__feupdateenv (const fenv_t *__e) -{ - return 0; -} -# endif - -extern inline int -fegetround (void) -{ - return FE_TONEAREST; -} - -extern inline int -__fegetround (void) -{ - return FE_TONEAREST; -} - -extern inline int -fesetround (int __d) -{ - return 0; -} - -extern inline int -__fesetround (int __d) -{ - return 0; -} -#endif +#include <fenv_private.h> #endif /* _MATH_PRIVATE_H_ */ diff --git a/sysdeps/i386/fpu/math_private.h b/sysdeps/i386/fpu/math_private.h deleted file mode 100644 index 485214391f..0000000000 --- a/sysdeps/i386/fpu/math_private.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef I386_MATH_PRIVATE_H -#define I386_MATH_PRIVATE_H 1 - -#include "fenv_private.h" -#include_next <math_private.h> - -#endif diff --git a/sysdeps/mips/math_private.h b/sysdeps/mips/fpu/fenv_private.h index 01ae8b18fd..ae6f8eb6a8 100644 --- a/sysdeps/mips/math_private.h +++ b/sysdeps/mips/fpu/fenv_private.h @@ -16,22 +16,20 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ -#ifndef MIPS_MATH_PRIVATE_H -#define MIPS_MATH_PRIVATE_H 1 +#ifndef MIPS_FENV_PRIVATE_H +#define MIPS_FENV_PRIVATE_H 1 /* Inline functions to speed up the math library implementation. The - default versions of these routines are in generic/math_private.h + default versions of these routines are in generic/fenv_private.h and call fesetround, feholdexcept, etc. These routines use inlined code instead. */ -#ifdef __mips_hard_float +#include <fenv.h> +#include <fenv_libc.h> +#include <fpu_control.h> -# include <fenv.h> -# include <fenv_libc.h> -# include <fpu_control.h> - -# define _FPU_MASK_ALL (_FPU_MASK_V | _FPU_MASK_Z | _FPU_MASK_O \ - |_FPU_MASK_U | _FPU_MASK_I | FE_ALL_EXCEPT) +#define _FPU_MASK_ALL (_FPU_MASK_V | _FPU_MASK_Z | _FPU_MASK_O \ + |_FPU_MASK_U | _FPU_MASK_I | FE_ALL_EXCEPT) static __always_inline void libc_feholdexcept_mips (fenv_t *envp) @@ -46,9 +44,9 @@ libc_feholdexcept_mips (fenv_t *envp) cw &= ~(_FPU_MASK_ALL); _FPU_SETCW (cw); } -# define libc_feholdexcept libc_feholdexcept_mips -# define libc_feholdexceptf libc_feholdexcept_mips -# define libc_feholdexceptl libc_feholdexcept_mips +#define libc_feholdexcept libc_feholdexcept_mips +#define libc_feholdexceptf libc_feholdexcept_mips +#define libc_feholdexceptl libc_feholdexcept_mips static __always_inline void libc_fesetround_mips (int round) @@ -65,9 +63,9 @@ libc_fesetround_mips (int round) /* Set new state. */ _FPU_SETCW (cw); } -# define libc_fesetround libc_fesetround_mips -# define libc_fesetroundf libc_fesetround_mips -# define libc_fesetroundl libc_fesetround_mips +#define libc_fesetround libc_fesetround_mips +#define libc_fesetroundf libc_fesetround_mips +#define libc_fesetroundl libc_fesetround_mips static __always_inline void libc_feholdexcept_setround_mips (fenv_t *envp, int round) @@ -88,13 +86,13 @@ libc_feholdexcept_setround_mips (fenv_t *envp, int round) /* Set new state. */ _FPU_SETCW (cw); } -# define libc_feholdexcept_setround libc_feholdexcept_setround_mips -# define libc_feholdexcept_setroundf libc_feholdexcept_setround_mips -# define libc_feholdexcept_setroundl libc_feholdexcept_setround_mips +#define libc_feholdexcept_setround libc_feholdexcept_setround_mips +#define libc_feholdexcept_setroundf libc_feholdexcept_setround_mips +#define libc_feholdexcept_setroundl libc_feholdexcept_setround_mips -# define libc_feholdsetround libc_feholdexcept_setround_mips -# define libc_feholdsetroundf libc_feholdexcept_setround_mips -# define libc_feholdsetroundl libc_feholdexcept_setround_mips +#define libc_feholdsetround libc_feholdexcept_setround_mips +#define libc_feholdsetroundf libc_feholdexcept_setround_mips +#define libc_feholdsetroundl libc_feholdexcept_setround_mips static __always_inline void libc_fesetenv_mips (fenv_t *envp) @@ -106,9 +104,9 @@ libc_fesetenv_mips (fenv_t *envp) _FPU_SETCW (envp->__fp_control_register); } -# define libc_fesetenv libc_fesetenv_mips -# define libc_fesetenvf libc_fesetenv_mips -# define libc_fesetenvl libc_fesetenv_mips +#define libc_fesetenv libc_fesetenv_mips +#define libc_fesetenvf libc_fesetenv_mips +#define libc_fesetenvl libc_fesetenv_mips static __always_inline int libc_feupdateenv_test_mips (fenv_t *envp, int excepts) @@ -131,22 +129,22 @@ libc_feupdateenv_test_mips (fenv_t *envp, int excepts) return cw & excepts & FE_ALL_EXCEPT; } -# define libc_feupdateenv_test libc_feupdateenv_test_mips -# define libc_feupdateenv_testf libc_feupdateenv_test_mips -# define libc_feupdateenv_testl libc_feupdateenv_test_mips +#define libc_feupdateenv_test libc_feupdateenv_test_mips +#define libc_feupdateenv_testf libc_feupdateenv_test_mips +#define libc_feupdateenv_testl libc_feupdateenv_test_mips static __always_inline void libc_feupdateenv_mips (fenv_t *envp) { libc_feupdateenv_test_mips (envp, 0); } -# define libc_feupdateenv libc_feupdateenv_mips -# define libc_feupdateenvf libc_feupdateenv_mips -# define libc_feupdateenvl libc_feupdateenv_mips +#define libc_feupdateenv libc_feupdateenv_mips +#define libc_feupdateenvf libc_feupdateenv_mips +#define libc_feupdateenvl libc_feupdateenv_mips -# define libc_feresetround libc_feupdateenv_mips -# define libc_feresetroundf libc_feupdateenv_mips -# define libc_feresetroundl libc_feupdateenv_mips +#define libc_feresetround libc_feupdateenv_mips +#define libc_feresetroundf libc_feupdateenv_mips +#define libc_feresetroundl libc_feupdateenv_mips static __always_inline int libc_fetestexcept_mips (int excepts) @@ -158,12 +156,12 @@ libc_fetestexcept_mips (int excepts) return cw & excepts & FE_ALL_EXCEPT; } -# define libc_fetestexcept libc_fetestexcept_mips -# define libc_fetestexceptf libc_fetestexcept_mips -# define libc_fetestexceptl libc_fetestexcept_mips +#define libc_fetestexcept libc_fetestexcept_mips +#define libc_fetestexceptf libc_fetestexcept_mips +#define libc_fetestexceptl libc_fetestexcept_mips /* Enable support for rounding mode context. */ -# define HAVE_RM_CTX 1 +#define HAVE_RM_CTX 1 static __always_inline void libc_feholdexcept_setround_mips_ctx (struct rm_ctx *ctx, int round) @@ -188,18 +186,18 @@ libc_feholdexcept_setround_mips_ctx (struct rm_ctx *ctx, int round) else ctx->updated_status = false; } -# define libc_feholdexcept_setround_ctx libc_feholdexcept_setround_mips_ctx -# define libc_feholdexcept_setroundf_ctx libc_feholdexcept_setround_mips_ctx -# define libc_feholdexcept_setroundl_ctx libc_feholdexcept_setround_mips_ctx +#define libc_feholdexcept_setround_ctx libc_feholdexcept_setround_mips_ctx +#define libc_feholdexcept_setroundf_ctx libc_feholdexcept_setround_mips_ctx +#define libc_feholdexcept_setroundl_ctx libc_feholdexcept_setround_mips_ctx static __always_inline void libc_fesetenv_mips_ctx (struct rm_ctx *ctx) { libc_fesetenv_mips (&ctx->env); } -# define libc_fesetenv_ctx libc_fesetenv_mips_ctx -# define libc_fesetenvf_ctx libc_fesetenv_mips_ctx -# define libc_fesetenvl_ctx libc_fesetenv_mips_ctx +#define libc_fesetenv_ctx libc_fesetenv_mips_ctx +#define libc_fesetenvf_ctx libc_fesetenv_mips_ctx +#define libc_fesetenvl_ctx libc_fesetenv_mips_ctx static __always_inline void libc_feupdateenv_mips_ctx (struct rm_ctx *ctx) @@ -207,12 +205,12 @@ libc_feupdateenv_mips_ctx (struct rm_ctx *ctx) if (__glibc_unlikely (ctx->updated_status)) libc_feupdateenv_test_mips (&ctx->env, 0); } -# define libc_feupdateenv_ctx libc_feupdateenv_mips_ctx -# define libc_feupdateenvf_ctx libc_feupdateenv_mips_ctx -# define libc_feupdateenvl_ctx libc_feupdateenv_mips_ctx -# define libc_feresetround_ctx libc_feupdateenv_mips_ctx -# define libc_feresetroundf_ctx libc_feupdateenv_mips_ctx -# define libc_feresetroundl_ctx libc_feupdateenv_mips_ctx +#define libc_feupdateenv_ctx libc_feupdateenv_mips_ctx +#define libc_feupdateenvf_ctx libc_feupdateenv_mips_ctx +#define libc_feupdateenvl_ctx libc_feupdateenv_mips_ctx +#define libc_feresetround_ctx libc_feupdateenv_mips_ctx +#define libc_feresetroundf_ctx libc_feupdateenv_mips_ctx +#define libc_feresetroundl_ctx libc_feupdateenv_mips_ctx static __always_inline void libc_feholdsetround_mips_ctx (struct rm_ctx *ctx, int round) @@ -234,12 +232,10 @@ libc_feholdsetround_mips_ctx (struct rm_ctx *ctx, int round) else ctx->updated_status = false; } -# define libc_feholdsetround_ctx libc_feholdsetround_mips_ctx -# define libc_feholdsetroundf_ctx libc_feholdsetround_mips_ctx -# define libc_feholdsetroundl_ctx libc_feholdsetround_mips_ctx - -#endif +#define libc_feholdsetround_ctx libc_feholdsetround_mips_ctx +#define libc_feholdsetroundf_ctx libc_feholdsetround_mips_ctx +#define libc_feholdsetroundl_ctx libc_feholdsetround_mips_ctx -#include_next <math_private.h> +#include_next <fenv_private.h> #endif diff --git a/sysdeps/powerpc/fpu/fenv_private.h b/sysdeps/powerpc/fpu/fenv_private.h index 945ab98018..239c488ea1 100644 --- a/sysdeps/powerpc/fpu/fenv_private.h +++ b/sysdeps/powerpc/fpu/fenv_private.h @@ -16,8 +16,8 @@ License along with the GNU C Library. If not, see <http://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> @@ -225,4 +225,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 diff --git a/sysdeps/powerpc/fpu/math_private.h b/sysdeps/powerpc/fpu/math_private.h index e642d6c823..36fcb3c654 100644 --- a/sysdeps/powerpc/fpu/math_private.h +++ b/sysdeps/powerpc/fpu/math_private.h @@ -22,7 +22,6 @@ #include <sysdep.h> #include <ldsodefs.h> #include <dl-procinfo.h> -#include <fenv_private.h> #include_next <math_private.h> diff --git a/sysdeps/riscv/rvf/math_private.h b/sysdeps/riscv/rvf/fenv_private.h index ca587620cb..b5b9f36882 100644 --- a/sysdeps/riscv/rvf/math_private.h +++ b/sysdeps/riscv/rvf/fenv_private.h @@ -16,8 +16,8 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ -#ifndef RISCV_MATH_PRIVATE_H -#define RISCV_MATH_PRIVATE_H 1 +#ifndef RISCV_FENV_PRIVATE_H +#define RISCV_FENV_PRIVATE_H 1 #include <fenv.h> #include <fpu_control.h> @@ -156,6 +156,6 @@ libc_feresetround_riscv (fenv_t *envp) #define libc_feresetroundf libc_feresetround_riscv #define libc_feresetroundl libc_feresetround_riscv -#include_next <math_private.h> +#include_next <fenv_private.h> #endif diff --git a/sysdeps/sparc/fpu/fenv_private.h b/sysdeps/sparc/fpu/fenv_private.h index 29b5d123cf..dbd1001ccb 100644 --- a/sysdeps/sparc/fpu/fenv_private.h +++ b/sysdeps/sparc/fpu/fenv_private.h @@ -1,5 +1,5 @@ -#ifndef FENV_PRIVATE_H -#define FENV_PRIVATE_H 1 +#ifndef SPARC_FENV_PRIVATE_H +#define SPARC_FENV_PRIVATE_H 1 #include <fenv.h> @@ -179,4 +179,6 @@ libc_feholdsetround_sparc_ctx (struct rm_ctx *ctx, int round) #define libc_feholdsetroundf_ctx libc_feholdsetround_sparc_ctx #define libc_feholdsetroundl_ctx libc_feholdsetround_sparc_ctx -#endif /* FENV_PRIVATE_H */ +#include_next <fenv_private.h> + +#endif /* SPARC_FENV_PRIVATE_H */ diff --git a/sysdeps/sparc/fpu/math_private.h b/sysdeps/sparc/fpu/math_private.h deleted file mode 100644 index 27946cec7b..0000000000 --- a/sysdeps/sparc/fpu/math_private.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef SPARC_MATH_PRIVATE_H -#define SPARC_MATH_PRIVATE_H 1 - -#include "fenv_private.h" -#include_next <math_private.h> - -#endif /* SPARC_MATH_PRIVATE_H */ diff --git a/sysdeps/i386/fpu/fenv_private.h b/sysdeps/x86/fpu/fenv_private.h index 637dae5f05..4b081e015b 100644 --- a/sysdeps/i386/fpu/fenv_private.h +++ b/sysdeps/x86/fpu/fenv_private.h @@ -1,5 +1,5 @@ -#ifndef FENV_PRIVATE_H -#define FENV_PRIVATE_H 1 +#ifndef X86_FENV_PRIVATE_H +#define X86_FENV_PRIVATE_H 1 #include <bits/floatn.h> #include <fenv.h> @@ -492,4 +492,6 @@ libc_feupdateenv_387_ctx (struct rm_ctx *ctx) #undef __mxcsr -#endif /* FENV_PRIVATE_H */ +#include_next <fenv_private.h> + +#endif /* X86_FENV_PRIVATE_H */ diff --git a/sysdeps/x86_64/fpu/math_private.h b/sysdeps/x86_64/fpu/math_private.h index 13052893ef..fcc8537d40 100644 --- a/sysdeps/x86_64/fpu/math_private.h +++ b/sysdeps/x86_64/fpu/math_private.h @@ -45,7 +45,6 @@ f = f__; \ } while (0) -#include <sysdeps/i386/fpu/fenv_private.h> #include_next <math_private.h> #ifdef __SSE4_1__ |