From ff6b24501f70da7d6375d6f5929262b9509db39e Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Tue, 28 Aug 2018 20:48:49 +0000 Subject: 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 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 . 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 , 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 . * sysdeps/arm/math_private.h: Remove. * sysdeps/generic/fenv_private.h: New file. Contents moved from .... * sysdeps/generic/math_private.h: ... this file. Include . Do not include or . Include . 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 . * sysdeps/powerpc/fpu/fenv_private.h: Change multiple-include guard to [POWERPC_FENV_PRIVATE_H]. Include next . * sysdeps/powerpc/fpu/math_private.h: Do not include . * 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 . * sysdeps/sparc/fpu/fenv_private.h: Change multiple-include guard to [SPARC_FENV_PRIVATE_H]. Include next . * 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 . * sysdeps/x86_64/fpu/math_private.h: Do not include . --- sysdeps/aarch64/fpu/fenv_private.h | 303 ++++++++++++++++++++++ sysdeps/aarch64/fpu/math_private.h | 282 +-------------------- sysdeps/arm/fenv_private.h | 8 +- sysdeps/arm/math_private.h | 7 - sysdeps/generic/fenv_private.h | 417 +++++++++++++++++++++++++++++++ sysdeps/generic/math_private.h | 395 +---------------------------- sysdeps/i386/fpu/fenv_private.h | 495 ------------------------------------ sysdeps/i386/fpu/math_private.h | 7 - sysdeps/mips/fpu/fenv_private.h | 241 ++++++++++++++++++ sysdeps/mips/math_private.h | 245 ------------------ sysdeps/powerpc/fpu/fenv_private.h | 6 +- sysdeps/powerpc/fpu/math_private.h | 1 - sysdeps/riscv/rvf/fenv_private.h | 161 ++++++++++++ sysdeps/riscv/rvf/math_private.h | 161 ------------ sysdeps/sparc/fpu/fenv_private.h | 8 +- sysdeps/sparc/fpu/math_private.h | 7 - sysdeps/x86/fpu/fenv_private.h | 497 +++++++++++++++++++++++++++++++++++++ sysdeps/x86_64/fpu/math_private.h | 1 - 18 files changed, 1637 insertions(+), 1605 deletions(-) create mode 100644 sysdeps/aarch64/fpu/fenv_private.h delete mode 100644 sysdeps/arm/math_private.h create mode 100644 sysdeps/generic/fenv_private.h delete mode 100644 sysdeps/i386/fpu/fenv_private.h delete mode 100644 sysdeps/i386/fpu/math_private.h create mode 100644 sysdeps/mips/fpu/fenv_private.h delete mode 100644 sysdeps/mips/math_private.h create mode 100644 sysdeps/riscv/rvf/fenv_private.h delete mode 100644 sysdeps/riscv/rvf/math_private.h delete mode 100644 sysdeps/sparc/fpu/math_private.h create mode 100644 sysdeps/x86/fpu/fenv_private.h (limited to 'sysdeps') 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 + . */ + +#ifndef AARCH64_FENV_PRIVATE_H +#define AARCH64_FENV_PRIVATE_H 1 + +#include +#include + +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 + +#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 -#include #include #include -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 . */ -#ifndef FENV_PRIVATE_H -#define FENV_PRIVATE_H 1 +#ifndef ARM_FENV_PRIVATE_H +#define ARM_FENV_PRIVATE_H 1 #include #include @@ -246,4 +246,6 @@ libc_fesetenv_vfp_ctx (struct rm_ctx *ctx) #endif -#endif /* FENV_PRIVATE_H */ +#include_next + +#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 - -#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 + . */ + +#ifndef _FENV_PRIVATE_H +#define _FENV_PRIVATE_H 1 + +#include +#include + +/* 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 , 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 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 +#include #include #include -#include -#include /* Gather machine dependent _Floatn support. */ #include @@ -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 , 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 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 #endif /* _MATH_PRIVATE_H_ */ diff --git a/sysdeps/i386/fpu/fenv_private.h b/sysdeps/i386/fpu/fenv_private.h deleted file mode 100644 index 637dae5f05..0000000000 --- a/sysdeps/i386/fpu/fenv_private.h +++ /dev/null @@ -1,495 +0,0 @@ -#ifndef FENV_PRIVATE_H -#define FENV_PRIVATE_H 1 - -#include -#include -#include - -/* This file is used by both the 32- and 64-bit ports. The 64-bit port - has a field in the fenv_t for the mxcsr; the 32-bit port does not. - Instead, we (ab)use the only 32-bit field extant in the struct. */ -#ifndef __x86_64__ -# define __mxcsr __eip -#endif - - -/* All of these functions are private to libm, and are all used in pairs - to save+change the fp state and restore the original state. Thus we - need not care for both the 387 and the sse unit, only the one we're - actually using. */ - -#if defined __AVX__ || defined SSE2AVX -# define STMXCSR "vstmxcsr" -# define LDMXCSR "vldmxcsr" -#else -# define STMXCSR "stmxcsr" -# define LDMXCSR "ldmxcsr" -#endif - -static __always_inline void -libc_feholdexcept_sse (fenv_t *e) -{ - unsigned int mxcsr; - asm (STMXCSR " %0" : "=m" (*&mxcsr)); - e->__mxcsr = mxcsr; - mxcsr = (mxcsr | 0x1f80) & ~0x3f; - asm volatile (LDMXCSR " %0" : : "m" (*&mxcsr)); -} - -static __always_inline void -libc_feholdexcept_387 (fenv_t *e) -{ - /* Recall that fnstenv has a side-effect of masking exceptions. - Clobber all of the fp registers so that the TOS field is 0. */ - asm volatile ("fnstenv %0; fnclex" - : "=m"(*e) - : : "st", "st(1)", "st(2)", "st(3)", - "st(4)", "st(5)", "st(6)", "st(7)"); -} - -static __always_inline void -libc_fesetround_sse (int r) -{ - unsigned int mxcsr; - asm (STMXCSR " %0" : "=m" (*&mxcsr)); - mxcsr = (mxcsr & ~0x6000) | (r << 3); - asm volatile (LDMXCSR " %0" : : "m" (*&mxcsr)); -} - -static __always_inline void -libc_fesetround_387 (int r) -{ - fpu_control_t cw; - _FPU_GETCW (cw); - cw = (cw & ~0xc00) | r; - _FPU_SETCW (cw); -} - -static __always_inline void -libc_feholdexcept_setround_sse (fenv_t *e, int r) -{ - unsigned int mxcsr; - asm (STMXCSR " %0" : "=m" (*&mxcsr)); - e->__mxcsr = mxcsr; - mxcsr = ((mxcsr | 0x1f80) & ~0x603f) | (r << 3); - asm volatile (LDMXCSR " %0" : : "m" (*&mxcsr)); -} - -/* Set both rounding mode and precision. A convenience function for use - by libc_feholdexcept_setround and libc_feholdexcept_setround_53bit. */ -static __always_inline void -libc_feholdexcept_setround_387_prec (fenv_t *e, int r) -{ - libc_feholdexcept_387 (e); - - fpu_control_t cw = e->__control_word; - cw &= ~(_FPU_RC_ZERO | _FPU_EXTENDED); - cw |= r | 0x3f; - _FPU_SETCW (cw); -} - -static __always_inline void -libc_feholdexcept_setround_387 (fenv_t *e, int r) -{ - libc_feholdexcept_setround_387_prec (e, r | _FPU_EXTENDED); -} - -static __always_inline void -libc_feholdexcept_setround_387_53bit (fenv_t *e, int r) -{ - libc_feholdexcept_setround_387_prec (e, r | _FPU_DOUBLE); -} - -static __always_inline int -libc_fetestexcept_sse (int e) -{ - unsigned int mxcsr; - asm volatile (STMXCSR " %0" : "=m" (*&mxcsr)); - return mxcsr & e & FE_ALL_EXCEPT; -} - -static __always_inline int -libc_fetestexcept_387 (int ex) -{ - fexcept_t temp; - asm volatile ("fnstsw %0" : "=a" (temp)); - return temp & ex & FE_ALL_EXCEPT; -} - -static __always_inline void -libc_fesetenv_sse (fenv_t *e) -{ - asm volatile (LDMXCSR " %0" : : "m" (e->__mxcsr)); -} - -static __always_inline void -libc_fesetenv_387 (fenv_t *e) -{ - /* Clobber all fp registers so that the TOS value we saved earlier is - compatible with the current state of the compiler. */ - asm volatile ("fldenv %0" - : : "m" (*e) - : "st", "st(1)", "st(2)", "st(3)", - "st(4)", "st(5)", "st(6)", "st(7)"); -} - -static __always_inline int -libc_feupdateenv_test_sse (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 (__glibc_unlikely (~(old_mxcsr >> 7) & cur_ex)) - __feraiseexcept (cur_ex); - - /* Test for exceptions raised since the hold. */ - return cur_ex & ex; -} - -static __always_inline int -libc_feupdateenv_test_387 (fenv_t *e, int ex) -{ - fexcept_t cur_ex; - - /* Save current exceptions. */ - asm volatile ("fnstsw %0" : "=a" (cur_ex)); - cur_ex &= FE_ALL_EXCEPT; - - /* Reload original environment. */ - libc_fesetenv_387 (e); - - /* Merge current exceptions. */ - __feraiseexcept (cur_ex); - - /* Test for exceptions raised since the hold. */ - return cur_ex & ex; -} - -static __always_inline void -libc_feupdateenv_sse (fenv_t *e) -{ - libc_feupdateenv_test_sse (e, 0); -} - -static __always_inline void -libc_feupdateenv_387 (fenv_t *e) -{ - libc_feupdateenv_test_387 (e, 0); -} - -static __always_inline void -libc_feholdsetround_sse (fenv_t *e, int r) -{ - unsigned int mxcsr; - asm (STMXCSR " %0" : "=m" (*&mxcsr)); - e->__mxcsr = mxcsr; - mxcsr = (mxcsr & ~0x6000) | (r << 3); - asm volatile (LDMXCSR " %0" : : "m" (*&mxcsr)); -} - -static __always_inline void -libc_feholdsetround_387_prec (fenv_t *e, int r) -{ - fpu_control_t cw; - - _FPU_GETCW (cw); - e->__control_word = cw; - cw &= ~(_FPU_RC_ZERO | _FPU_EXTENDED); - cw |= r; - _FPU_SETCW (cw); -} - -static __always_inline void -libc_feholdsetround_387 (fenv_t *e, int r) -{ - libc_feholdsetround_387_prec (e, r | _FPU_EXTENDED); -} - -static __always_inline void -libc_feholdsetround_387_53bit (fenv_t *e, int r) -{ - libc_feholdsetround_387_prec (e, r | _FPU_DOUBLE); -} - -static __always_inline void -libc_feresetround_sse (fenv_t *e) -{ - unsigned int mxcsr; - asm (STMXCSR " %0" : "=m" (*&mxcsr)); - mxcsr = (mxcsr & ~0x6000) | (e->__mxcsr & 0x6000); - asm volatile (LDMXCSR " %0" : : "m" (*&mxcsr)); -} - -static __always_inline void -libc_feresetround_387 (fenv_t *e) -{ - _FPU_SETCW (e->__control_word); -} - -#ifdef __SSE_MATH__ -# define libc_feholdexceptf libc_feholdexcept_sse -# define libc_fesetroundf libc_fesetround_sse -# define libc_feholdexcept_setroundf libc_feholdexcept_setround_sse -# define libc_fetestexceptf libc_fetestexcept_sse -# define libc_fesetenvf libc_fesetenv_sse -# define libc_feupdateenv_testf libc_feupdateenv_test_sse -# define libc_feupdateenvf libc_feupdateenv_sse -# define libc_feholdsetroundf libc_feholdsetround_sse -# define libc_feresetroundf libc_feresetround_sse -#else -# define libc_feholdexceptf libc_feholdexcept_387 -# define libc_fesetroundf libc_fesetround_387 -# define libc_feholdexcept_setroundf libc_feholdexcept_setround_387 -# define libc_fetestexceptf libc_fetestexcept_387 -# define libc_fesetenvf libc_fesetenv_387 -# define libc_feupdateenv_testf libc_feupdateenv_test_387 -# define libc_feupdateenvf libc_feupdateenv_387 -# define libc_feholdsetroundf libc_feholdsetround_387 -# define libc_feresetroundf libc_feresetround_387 -#endif /* __SSE_MATH__ */ - -#ifdef __SSE2_MATH__ -# define libc_feholdexcept libc_feholdexcept_sse -# define libc_fesetround libc_fesetround_sse -# define libc_feholdexcept_setround libc_feholdexcept_setround_sse -# define libc_fetestexcept libc_fetestexcept_sse -# define libc_fesetenv libc_fesetenv_sse -# define libc_feupdateenv_test libc_feupdateenv_test_sse -# define libc_feupdateenv libc_feupdateenv_sse -# define libc_feholdsetround libc_feholdsetround_sse -# define libc_feresetround libc_feresetround_sse -#else -# define libc_feholdexcept libc_feholdexcept_387 -# define libc_fesetround libc_fesetround_387 -# define libc_feholdexcept_setround libc_feholdexcept_setround_387 -# define libc_fetestexcept libc_fetestexcept_387 -# define libc_fesetenv libc_fesetenv_387 -# define libc_feupdateenv_test libc_feupdateenv_test_387 -# define libc_feupdateenv libc_feupdateenv_387 -# define libc_feholdsetround libc_feholdsetround_387 -# define libc_feresetround libc_feresetround_387 -#endif /* __SSE2_MATH__ */ - -#define libc_feholdexceptl libc_feholdexcept_387 -#define libc_fesetroundl libc_fesetround_387 -#define libc_feholdexcept_setroundl libc_feholdexcept_setround_387 -#define libc_fetestexceptl libc_fetestexcept_387 -#define libc_fesetenvl libc_fesetenv_387 -#define libc_feupdateenv_testl libc_feupdateenv_test_387 -#define libc_feupdateenvl libc_feupdateenv_387 -#define libc_feholdsetroundl libc_feholdsetround_387 -#define libc_feresetroundl libc_feresetround_387 - -#ifndef __SSE2_MATH__ -# define libc_feholdexcept_setround_53bit libc_feholdexcept_setround_387_53bit -# define libc_feholdsetround_53bit libc_feholdsetround_387_53bit -#endif - -#ifdef __x86_64__ -/* The SSE rounding mode is used by soft-fp (libgcc and glibc) on - x86_64, so that must be set for float128 computations. */ -# define SET_RESTORE_ROUNDF128(RM) \ - SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_sse, libc_feresetround_sse) -# define libc_feholdexcept_setroundf128 libc_feholdexcept_setround_sse -# define libc_feupdateenv_testf128 libc_feupdateenv_test_sse -#else -/* The 387 rounding mode is used by soft-fp for 32-bit, but whether - 387 or SSE exceptions are used depends on whether libgcc was built - for SSE math, which is not known when glibc is being built. */ -# define libc_feholdexcept_setroundf128 default_libc_feholdexcept_setround -# define libc_feupdateenv_testf128 default_libc_feupdateenv_test -#endif - -/* We have support for rounding mode context. */ -#define HAVE_RM_CTX 1 - -static __always_inline void -libc_feholdexcept_setround_sse_ctx (struct rm_ctx *ctx, int r) -{ - unsigned int mxcsr, new_mxcsr; - asm (STMXCSR " %0" : "=m" (*&mxcsr)); - new_mxcsr = ((mxcsr | 0x1f80) & ~0x603f) | (r << 3); - - ctx->env.__mxcsr = mxcsr; - if (__glibc_unlikely (mxcsr != new_mxcsr)) - { - asm volatile (LDMXCSR " %0" : : "m" (*&new_mxcsr)); - ctx->updated_status = true; - } - else - ctx->updated_status = false; -} - -/* Unconditional since we want to overwrite any exceptions that occurred in the - context. This is also why all fehold* functions unconditionally write into - ctx->env. */ -static __always_inline void -libc_fesetenv_sse_ctx (struct rm_ctx *ctx) -{ - libc_fesetenv_sse (&ctx->env); -} - -static __always_inline void -libc_feupdateenv_sse_ctx (struct rm_ctx *ctx) -{ - if (__glibc_unlikely (ctx->updated_status)) - libc_feupdateenv_test_sse (&ctx->env, 0); -} - -static __always_inline void -libc_feholdexcept_setround_387_prec_ctx (struct rm_ctx *ctx, int r) -{ - libc_feholdexcept_387 (&ctx->env); - - fpu_control_t cw = ctx->env.__control_word; - fpu_control_t old_cw = cw; - cw &= ~(_FPU_RC_ZERO | _FPU_EXTENDED); - cw |= r | 0x3f; - - if (__glibc_unlikely (old_cw != cw)) - { - _FPU_SETCW (cw); - ctx->updated_status = true; - } - else - ctx->updated_status = false; -} - -static __always_inline void -libc_feholdexcept_setround_387_ctx (struct rm_ctx *ctx, int r) -{ - libc_feholdexcept_setround_387_prec_ctx (ctx, r | _FPU_EXTENDED); -} - -static __always_inline void -libc_feholdexcept_setround_387_53bit_ctx (struct rm_ctx *ctx, int r) -{ - libc_feholdexcept_setround_387_prec_ctx (ctx, r | _FPU_DOUBLE); -} - -static __always_inline void -libc_feholdsetround_387_prec_ctx (struct rm_ctx *ctx, int r) -{ - fpu_control_t cw, new_cw; - - _FPU_GETCW (cw); - new_cw = cw; - new_cw &= ~(_FPU_RC_ZERO | _FPU_EXTENDED); - new_cw |= r; - - ctx->env.__control_word = cw; - if (__glibc_unlikely (new_cw != cw)) - { - _FPU_SETCW (new_cw); - ctx->updated_status = true; - } - else - ctx->updated_status = false; -} - -static __always_inline void -libc_feholdsetround_387_ctx (struct rm_ctx *ctx, int r) -{ - libc_feholdsetround_387_prec_ctx (ctx, r | _FPU_EXTENDED); -} - -static __always_inline void -libc_feholdsetround_387_53bit_ctx (struct rm_ctx *ctx, int r) -{ - libc_feholdsetround_387_prec_ctx (ctx, r | _FPU_DOUBLE); -} - -static __always_inline void -libc_feholdsetround_sse_ctx (struct rm_ctx *ctx, int r) -{ - unsigned int mxcsr, new_mxcsr; - - asm (STMXCSR " %0" : "=m" (*&mxcsr)); - new_mxcsr = (mxcsr & ~0x6000) | (r << 3); - - ctx->env.__mxcsr = mxcsr; - if (__glibc_unlikely (new_mxcsr != mxcsr)) - { - asm volatile (LDMXCSR " %0" : : "m" (*&new_mxcsr)); - ctx->updated_status = true; - } - else - ctx->updated_status = false; -} - -static __always_inline void -libc_feresetround_sse_ctx (struct rm_ctx *ctx) -{ - if (__glibc_unlikely (ctx->updated_status)) - libc_feresetround_sse (&ctx->env); -} - -static __always_inline void -libc_feresetround_387_ctx (struct rm_ctx *ctx) -{ - if (__glibc_unlikely (ctx->updated_status)) - _FPU_SETCW (ctx->env.__control_word); -} - -static __always_inline void -libc_feupdateenv_387_ctx (struct rm_ctx *ctx) -{ - if (__glibc_unlikely (ctx->updated_status)) - libc_feupdateenv_test_387 (&ctx->env, 0); -} - -#ifdef __SSE_MATH__ -# define libc_feholdexcept_setroundf_ctx libc_feholdexcept_setround_sse_ctx -# define libc_fesetenvf_ctx libc_fesetenv_sse_ctx -# define libc_feupdateenvf_ctx libc_feupdateenv_sse_ctx -# define libc_feholdsetroundf_ctx libc_feholdsetround_sse_ctx -# define libc_feresetroundf_ctx libc_feresetround_sse_ctx -#else -# define libc_feholdexcept_setroundf_ctx libc_feholdexcept_setround_387_ctx -# define libc_feupdateenvf_ctx libc_feupdateenv_387_ctx -# define libc_feholdsetroundf_ctx libc_feholdsetround_387_ctx -# define libc_feresetroundf_ctx libc_feresetround_387_ctx -#endif /* __SSE_MATH__ */ - -#ifdef __SSE2_MATH__ -# if defined (__x86_64__) || !defined (MATH_SET_BOTH_ROUNDING_MODES) -# define libc_feholdexcept_setround_ctx libc_feholdexcept_setround_sse_ctx -# define libc_fesetenv_ctx libc_fesetenv_sse_ctx -# define libc_feupdateenv_ctx libc_feupdateenv_sse_ctx -# define libc_feholdsetround_ctx libc_feholdsetround_sse_ctx -# define libc_feresetround_ctx libc_feresetround_sse_ctx -# else -# define libc_feholdexcept_setround_ctx default_libc_feholdexcept_setround_ctx -# define libc_fesetenv_ctx default_libc_fesetenv_ctx -# define libc_feupdateenv_ctx default_libc_feupdateenv_ctx -# define libc_feholdsetround_ctx default_libc_feholdsetround_ctx -# define libc_feresetround_ctx default_libc_feresetround_ctx -# endif -#else -# define libc_feholdexcept_setround_ctx libc_feholdexcept_setround_387_ctx -# define libc_feupdateenv_ctx libc_feupdateenv_387_ctx -# define libc_feholdsetround_ctx libc_feholdsetround_387_ctx -# define libc_feresetround_ctx libc_feresetround_387_ctx -#endif /* __SSE2_MATH__ */ - -#define libc_feholdexcept_setroundl_ctx libc_feholdexcept_setround_387_ctx -#define libc_feupdateenvl_ctx libc_feupdateenv_387_ctx -#define libc_feholdsetroundl_ctx libc_feholdsetround_387_ctx -#define libc_feresetroundl_ctx libc_feresetround_387_ctx - -#ifndef __SSE2_MATH__ -# define libc_feholdsetround_53bit_ctx libc_feholdsetround_387_53bit_ctx -# define libc_feresetround_53bit_ctx libc_feresetround_387_ctx -#endif - -#undef __mxcsr - -#endif /* FENV_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 - -#endif diff --git a/sysdeps/mips/fpu/fenv_private.h b/sysdeps/mips/fpu/fenv_private.h new file mode 100644 index 0000000000..ae6f8eb6a8 --- /dev/null +++ b/sysdeps/mips/fpu/fenv_private.h @@ -0,0 +1,241 @@ +/* Internal math stuff. MIPS version. + Copyright (C) 2013-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 + . */ + +#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/fenv_private.h + and call fesetround, feholdexcept, etc. These routines use inlined + code instead. */ + +#include +#include +#include + +#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) +{ + fpu_control_t cw; + + /* Save the current state. */ + _FPU_GETCW (cw); + envp->__fp_control_register = cw; + + /* Clear all exception enable bits and flags. */ + 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 + +static __always_inline void +libc_fesetround_mips (int round) +{ + fpu_control_t cw; + + /* Get current state. */ + _FPU_GETCW (cw); + + /* Set rounding bits. */ + cw &= ~_FPU_RC_MASK; + cw |= 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 + +static __always_inline void +libc_feholdexcept_setround_mips (fenv_t *envp, int round) +{ + fpu_control_t cw; + + /* Save the current state. */ + _FPU_GETCW (cw); + envp->__fp_control_register = cw; + + /* Clear all exception enable bits and flags. */ + cw &= ~(_FPU_MASK_ALL); + + /* Set rounding bits. */ + cw &= ~_FPU_RC_MASK; + cw |= 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_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) +{ + fpu_control_t cw __attribute__ ((unused)); + + /* Read current state to flush fpu pipeline. */ + _FPU_GETCW (cw); + + _FPU_SETCW (envp->__fp_control_register); +} +#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) +{ + /* int ret = fetestexcept (excepts); feupdateenv (envp); return ret; */ + int cw, temp; + + /* Get current control word. */ + _FPU_GETCW (cw); + + /* Set flag bits (which are accumulative), and *also* set the + cause bits. The setting of the cause bits is what actually causes + the hardware to generate the exception, if the corresponding enable + bit is set as well. */ + temp = cw & FE_ALL_EXCEPT; + temp |= envp->__fp_control_register | (temp << CAUSE_SHIFT); + + /* Set new state. */ + _FPU_SETCW (temp); + + 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 + +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_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) +{ + int cw; + + /* Get current control word. */ + _FPU_GETCW (cw); + + return cw & excepts & FE_ALL_EXCEPT; +} +#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 + +static __always_inline void +libc_feholdexcept_setround_mips_ctx (struct rm_ctx *ctx, int round) +{ + fpu_control_t old, new; + + /* Save the current state. */ + _FPU_GETCW (old); + ctx->env.__fp_control_register = old; + + /* Clear all exception enable bits and flags. */ + new = old & ~(_FPU_MASK_ALL); + + /* Set rounding bits. */ + new = (new & ~_FPU_RC_MASK) | round; + + if (__glibc_unlikely (new != old)) + { + _FPU_SETCW (new); + ctx->updated_status = true; + } + 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 + +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 + +static __always_inline void +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 + +static __always_inline void +libc_feholdsetround_mips_ctx (struct rm_ctx *ctx, int round) +{ + fpu_control_t old, new; + + /* Save the current state. */ + _FPU_GETCW (old); + ctx->env.__fp_control_register = old; + + /* Set rounding bits. */ + new = (old & ~_FPU_RC_MASK) | round; + + if (__glibc_unlikely (new != old)) + { + _FPU_SETCW (new); + ctx->updated_status = true; + } + 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 + +#include_next + +#endif diff --git a/sysdeps/mips/math_private.h b/sysdeps/mips/math_private.h deleted file mode 100644 index 01ae8b18fd..0000000000 --- a/sysdeps/mips/math_private.h +++ /dev/null @@ -1,245 +0,0 @@ -/* Internal math stuff. MIPS version. - Copyright (C) 2013-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 - . */ - -#ifndef MIPS_MATH_PRIVATE_H -#define MIPS_MATH_PRIVATE_H 1 - -/* Inline functions to speed up the math library implementation. The - default versions of these routines are in generic/math_private.h - and call fesetround, feholdexcept, etc. These routines use inlined - code instead. */ - -#ifdef __mips_hard_float - -# include -# include -# include - -# 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) -{ - fpu_control_t cw; - - /* Save the current state. */ - _FPU_GETCW (cw); - envp->__fp_control_register = cw; - - /* Clear all exception enable bits and flags. */ - 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 - -static __always_inline void -libc_fesetround_mips (int round) -{ - fpu_control_t cw; - - /* Get current state. */ - _FPU_GETCW (cw); - - /* Set rounding bits. */ - cw &= ~_FPU_RC_MASK; - cw |= 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 - -static __always_inline void -libc_feholdexcept_setround_mips (fenv_t *envp, int round) -{ - fpu_control_t cw; - - /* Save the current state. */ - _FPU_GETCW (cw); - envp->__fp_control_register = cw; - - /* Clear all exception enable bits and flags. */ - cw &= ~(_FPU_MASK_ALL); - - /* Set rounding bits. */ - cw &= ~_FPU_RC_MASK; - cw |= 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_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) -{ - fpu_control_t cw __attribute__ ((unused)); - - /* Read current state to flush fpu pipeline. */ - _FPU_GETCW (cw); - - _FPU_SETCW (envp->__fp_control_register); -} -# 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) -{ - /* int ret = fetestexcept (excepts); feupdateenv (envp); return ret; */ - int cw, temp; - - /* Get current control word. */ - _FPU_GETCW (cw); - - /* Set flag bits (which are accumulative), and *also* set the - cause bits. The setting of the cause bits is what actually causes - the hardware to generate the exception, if the corresponding enable - bit is set as well. */ - temp = cw & FE_ALL_EXCEPT; - temp |= envp->__fp_control_register | (temp << CAUSE_SHIFT); - - /* Set new state. */ - _FPU_SETCW (temp); - - 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 - -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_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) -{ - int cw; - - /* Get current control word. */ - _FPU_GETCW (cw); - - return cw & excepts & FE_ALL_EXCEPT; -} -# 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 - -static __always_inline void -libc_feholdexcept_setround_mips_ctx (struct rm_ctx *ctx, int round) -{ - fpu_control_t old, new; - - /* Save the current state. */ - _FPU_GETCW (old); - ctx->env.__fp_control_register = old; - - /* Clear all exception enable bits and flags. */ - new = old & ~(_FPU_MASK_ALL); - - /* Set rounding bits. */ - new = (new & ~_FPU_RC_MASK) | round; - - if (__glibc_unlikely (new != old)) - { - _FPU_SETCW (new); - ctx->updated_status = true; - } - 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 - -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 - -static __always_inline void -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 - -static __always_inline void -libc_feholdsetround_mips_ctx (struct rm_ctx *ctx, int round) -{ - fpu_control_t old, new; - - /* Save the current state. */ - _FPU_GETCW (old); - ctx->env.__fp_control_register = old; - - /* Set rounding bits. */ - new = (old & ~_FPU_RC_MASK) | round; - - if (__glibc_unlikely (new != old)) - { - _FPU_SETCW (new); - ctx->updated_status = true; - } - 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 - -#include_next - -#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 . */ -#ifndef FENV_PRIVATE_H -#define FENV_PRIVATE_H 1 +#ifndef POWERPC_FENV_PRIVATE_H +#define POWERPC_FENV_PRIVATE_H 1 #include #include @@ -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 + #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 #include #include -#include #include_next diff --git a/sysdeps/riscv/rvf/fenv_private.h b/sysdeps/riscv/rvf/fenv_private.h new file mode 100644 index 0000000000..b5b9f36882 --- /dev/null +++ b/sysdeps/riscv/rvf/fenv_private.h @@ -0,0 +1,161 @@ +/* Private floating point rounding and exceptions handling. RISC-V 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 + . */ + +#ifndef RISCV_FENV_PRIVATE_H +#define RISCV_FENV_PRIVATE_H 1 + +#include +#include +#include + +static __always_inline int +riscv_getround (void) +{ + return get_rounding_mode (); +} + +static __always_inline void +riscv_setround (int rm) +{ + asm volatile ("fsrm %z0" : : "rJ" (rm)); +} + +static __always_inline int +riscv_getflags (void) +{ + int flags; + asm volatile ("frflags %0" : "=r" (flags)); + return flags; +} + +static __always_inline void +riscv_setflags (int flags) +{ + asm volatile ("fsflags %z0" : : "rJ" (flags)); +} + +static __always_inline void +libc_feholdexcept_riscv (fenv_t *envp) +{ + asm volatile ("csrrc %0, fcsr, %1" : "=r" (*envp) : "i" (FE_ALL_EXCEPT)); +} + +#define libc_feholdexcept libc_feholdexcept_riscv +#define libc_feholdexceptf libc_feholdexcept_riscv +#define libc_feholdexceptl libc_feholdexcept_riscv + +static __always_inline void +libc_fesetround_riscv (int round) +{ + riscv_setround (round); +} + +#define libc_fesetround libc_fesetround_riscv +#define libc_fesetroundf libc_fesetround_riscv +#define libc_fesetroundl libc_fesetround_riscv + +static __always_inline void +libc_feholdexcept_setround_riscv (fenv_t *envp, int round) +{ + libc_feholdexcept_riscv (envp); + libc_fesetround_riscv (round); +} + +#define libc_feholdexcept_setround libc_feholdexcept_setround_riscv +#define libc_feholdexcept_setroundf libc_feholdexcept_setround_riscv +#define libc_feholdexcept_setroundl libc_feholdexcept_setround_riscv + +static __always_inline int +libc_fetestexcept_riscv (int ex) +{ + return riscv_getflags () & ex; +} + +#define libc_fetestexcept libc_fetestexcept_riscv +#define libc_fetestexceptf libc_fetestexcept_riscv +#define libc_fetestexceptl libc_fetestexcept_riscv + +static __always_inline void +libc_fesetenv_riscv (const fenv_t *envp) +{ + long int env = (long int) envp - (long int) FE_DFL_ENV; + if (env != 0) + env = *envp; + + _FPU_SETCW (env); +} + +#define libc_fesetenv libc_fesetenv_riscv +#define libc_fesetenvf libc_fesetenv_riscv +#define libc_fesetenvl libc_fesetenv_riscv +#define libc_feresetround_noex libc_fesetenv_riscv +#define libc_feresetround_noexf libc_fesetenv_riscv +#define libc_feresetround_noexl libc_fesetenv_riscv + +static __always_inline int +libc_feupdateenv_test_riscv (const fenv_t *envp, int ex) +{ + fenv_t env = *envp; + int flags = riscv_getflags (); + asm volatile ("csrw fcsr, %z0" : : "rJ" (env | flags)); + return flags & ex; +} + +#define libc_feupdateenv_test libc_feupdateenv_test_riscv +#define libc_feupdateenv_testf libc_feupdateenv_test_riscv +#define libc_feupdateenv_testl libc_feupdateenv_test_riscv + +static __always_inline void +libc_feupdateenv_riscv (const fenv_t *envp) +{ + _FPU_SETCW (*envp | riscv_getflags ()); +} + +#define libc_feupdateenv libc_feupdateenv_riscv +#define libc_feupdateenvf libc_feupdateenv_riscv +#define libc_feupdateenvl libc_feupdateenv_riscv + +static __always_inline void +libc_feholdsetround_riscv (fenv_t *envp, int round) +{ + /* Note this implementation makes an improperly-formatted fenv_t and + so should only be used in conjunction with libc_feresetround. */ + int old_round; + asm volatile ("csrrw %0, frm, %z1" : "=r" (old_round) : "rJ" (round)); + *envp = old_round; +} + +#define libc_feholdsetround libc_feholdsetround_riscv +#define libc_feholdsetroundf libc_feholdsetround_riscv +#define libc_feholdsetroundl libc_feholdsetround_riscv + +static __always_inline void +libc_feresetround_riscv (fenv_t *envp) +{ + /* Note this implementation takes an improperly-formatted fenv_t and + so should only be used in conjunction with libc_feholdsetround. */ + riscv_setround (*envp); +} + +#define libc_feresetround libc_feresetround_riscv +#define libc_feresetroundf libc_feresetround_riscv +#define libc_feresetroundl libc_feresetround_riscv + +#include_next + +#endif diff --git a/sysdeps/riscv/rvf/math_private.h b/sysdeps/riscv/rvf/math_private.h deleted file mode 100644 index ca587620cb..0000000000 --- a/sysdeps/riscv/rvf/math_private.h +++ /dev/null @@ -1,161 +0,0 @@ -/* Private floating point rounding and exceptions handling. RISC-V 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 - . */ - -#ifndef RISCV_MATH_PRIVATE_H -#define RISCV_MATH_PRIVATE_H 1 - -#include -#include -#include - -static __always_inline int -riscv_getround (void) -{ - return get_rounding_mode (); -} - -static __always_inline void -riscv_setround (int rm) -{ - asm volatile ("fsrm %z0" : : "rJ" (rm)); -} - -static __always_inline int -riscv_getflags (void) -{ - int flags; - asm volatile ("frflags %0" : "=r" (flags)); - return flags; -} - -static __always_inline void -riscv_setflags (int flags) -{ - asm volatile ("fsflags %z0" : : "rJ" (flags)); -} - -static __always_inline void -libc_feholdexcept_riscv (fenv_t *envp) -{ - asm volatile ("csrrc %0, fcsr, %1" : "=r" (*envp) : "i" (FE_ALL_EXCEPT)); -} - -#define libc_feholdexcept libc_feholdexcept_riscv -#define libc_feholdexceptf libc_feholdexcept_riscv -#define libc_feholdexceptl libc_feholdexcept_riscv - -static __always_inline void -libc_fesetround_riscv (int round) -{ - riscv_setround (round); -} - -#define libc_fesetround libc_fesetround_riscv -#define libc_fesetroundf libc_fesetround_riscv -#define libc_fesetroundl libc_fesetround_riscv - -static __always_inline void -libc_feholdexcept_setround_riscv (fenv_t *envp, int round) -{ - libc_feholdexcept_riscv (envp); - libc_fesetround_riscv (round); -} - -#define libc_feholdexcept_setround libc_feholdexcept_setround_riscv -#define libc_feholdexcept_setroundf libc_feholdexcept_setround_riscv -#define libc_feholdexcept_setroundl libc_feholdexcept_setround_riscv - -static __always_inline int -libc_fetestexcept_riscv (int ex) -{ - return riscv_getflags () & ex; -} - -#define libc_fetestexcept libc_fetestexcept_riscv -#define libc_fetestexceptf libc_fetestexcept_riscv -#define libc_fetestexceptl libc_fetestexcept_riscv - -static __always_inline void -libc_fesetenv_riscv (const fenv_t *envp) -{ - long int env = (long int) envp - (long int) FE_DFL_ENV; - if (env != 0) - env = *envp; - - _FPU_SETCW (env); -} - -#define libc_fesetenv libc_fesetenv_riscv -#define libc_fesetenvf libc_fesetenv_riscv -#define libc_fesetenvl libc_fesetenv_riscv -#define libc_feresetround_noex libc_fesetenv_riscv -#define libc_feresetround_noexf libc_fesetenv_riscv -#define libc_feresetround_noexl libc_fesetenv_riscv - -static __always_inline int -libc_feupdateenv_test_riscv (const fenv_t *envp, int ex) -{ - fenv_t env = *envp; - int flags = riscv_getflags (); - asm volatile ("csrw fcsr, %z0" : : "rJ" (env | flags)); - return flags & ex; -} - -#define libc_feupdateenv_test libc_feupdateenv_test_riscv -#define libc_feupdateenv_testf libc_feupdateenv_test_riscv -#define libc_feupdateenv_testl libc_feupdateenv_test_riscv - -static __always_inline void -libc_feupdateenv_riscv (const fenv_t *envp) -{ - _FPU_SETCW (*envp | riscv_getflags ()); -} - -#define libc_feupdateenv libc_feupdateenv_riscv -#define libc_feupdateenvf libc_feupdateenv_riscv -#define libc_feupdateenvl libc_feupdateenv_riscv - -static __always_inline void -libc_feholdsetround_riscv (fenv_t *envp, int round) -{ - /* Note this implementation makes an improperly-formatted fenv_t and - so should only be used in conjunction with libc_feresetround. */ - int old_round; - asm volatile ("csrrw %0, frm, %z1" : "=r" (old_round) : "rJ" (round)); - *envp = old_round; -} - -#define libc_feholdsetround libc_feholdsetround_riscv -#define libc_feholdsetroundf libc_feholdsetround_riscv -#define libc_feholdsetroundl libc_feholdsetround_riscv - -static __always_inline void -libc_feresetround_riscv (fenv_t *envp) -{ - /* Note this implementation takes an improperly-formatted fenv_t and - so should only be used in conjunction with libc_feholdsetround. */ - riscv_setround (*envp); -} - -#define libc_feresetround libc_feresetround_riscv -#define libc_feresetroundf libc_feresetround_riscv -#define libc_feresetroundl libc_feresetround_riscv - -#include_next - -#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 @@ -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 + +#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 - -#endif /* SPARC_MATH_PRIVATE_H */ diff --git a/sysdeps/x86/fpu/fenv_private.h b/sysdeps/x86/fpu/fenv_private.h new file mode 100644 index 0000000000..4b081e015b --- /dev/null +++ b/sysdeps/x86/fpu/fenv_private.h @@ -0,0 +1,497 @@ +#ifndef X86_FENV_PRIVATE_H +#define X86_FENV_PRIVATE_H 1 + +#include +#include +#include + +/* This file is used by both the 32- and 64-bit ports. The 64-bit port + has a field in the fenv_t for the mxcsr; the 32-bit port does not. + Instead, we (ab)use the only 32-bit field extant in the struct. */ +#ifndef __x86_64__ +# define __mxcsr __eip +#endif + + +/* All of these functions are private to libm, and are all used in pairs + to save+change the fp state and restore the original state. Thus we + need not care for both the 387 and the sse unit, only the one we're + actually using. */ + +#if defined __AVX__ || defined SSE2AVX +# define STMXCSR "vstmxcsr" +# define LDMXCSR "vldmxcsr" +#else +# define STMXCSR "stmxcsr" +# define LDMXCSR "ldmxcsr" +#endif + +static __always_inline void +libc_feholdexcept_sse (fenv_t *e) +{ + unsigned int mxcsr; + asm (STMXCSR " %0" : "=m" (*&mxcsr)); + e->__mxcsr = mxcsr; + mxcsr = (mxcsr | 0x1f80) & ~0x3f; + asm volatile (LDMXCSR " %0" : : "m" (*&mxcsr)); +} + +static __always_inline void +libc_feholdexcept_387 (fenv_t *e) +{ + /* Recall that fnstenv has a side-effect of masking exceptions. + Clobber all of the fp registers so that the TOS field is 0. */ + asm volatile ("fnstenv %0; fnclex" + : "=m"(*e) + : : "st", "st(1)", "st(2)", "st(3)", + "st(4)", "st(5)", "st(6)", "st(7)"); +} + +static __always_inline void +libc_fesetround_sse (int r) +{ + unsigned int mxcsr; + asm (STMXCSR " %0" : "=m" (*&mxcsr)); + mxcsr = (mxcsr & ~0x6000) | (r << 3); + asm volatile (LDMXCSR " %0" : : "m" (*&mxcsr)); +} + +static __always_inline void +libc_fesetround_387 (int r) +{ + fpu_control_t cw; + _FPU_GETCW (cw); + cw = (cw & ~0xc00) | r; + _FPU_SETCW (cw); +} + +static __always_inline void +libc_feholdexcept_setround_sse (fenv_t *e, int r) +{ + unsigned int mxcsr; + asm (STMXCSR " %0" : "=m" (*&mxcsr)); + e->__mxcsr = mxcsr; + mxcsr = ((mxcsr | 0x1f80) & ~0x603f) | (r << 3); + asm volatile (LDMXCSR " %0" : : "m" (*&mxcsr)); +} + +/* Set both rounding mode and precision. A convenience function for use + by libc_feholdexcept_setround and libc_feholdexcept_setround_53bit. */ +static __always_inline void +libc_feholdexcept_setround_387_prec (fenv_t *e, int r) +{ + libc_feholdexcept_387 (e); + + fpu_control_t cw = e->__control_word; + cw &= ~(_FPU_RC_ZERO | _FPU_EXTENDED); + cw |= r | 0x3f; + _FPU_SETCW (cw); +} + +static __always_inline void +libc_feholdexcept_setround_387 (fenv_t *e, int r) +{ + libc_feholdexcept_setround_387_prec (e, r | _FPU_EXTENDED); +} + +static __always_inline void +libc_feholdexcept_setround_387_53bit (fenv_t *e, int r) +{ + libc_feholdexcept_setround_387_prec (e, r | _FPU_DOUBLE); +} + +static __always_inline int +libc_fetestexcept_sse (int e) +{ + unsigned int mxcsr; + asm volatile (STMXCSR " %0" : "=m" (*&mxcsr)); + return mxcsr & e & FE_ALL_EXCEPT; +} + +static __always_inline int +libc_fetestexcept_387 (int ex) +{ + fexcept_t temp; + asm volatile ("fnstsw %0" : "=a" (temp)); + return temp & ex & FE_ALL_EXCEPT; +} + +static __always_inline void +libc_fesetenv_sse (fenv_t *e) +{ + asm volatile (LDMXCSR " %0" : : "m" (e->__mxcsr)); +} + +static __always_inline void +libc_fesetenv_387 (fenv_t *e) +{ + /* Clobber all fp registers so that the TOS value we saved earlier is + compatible with the current state of the compiler. */ + asm volatile ("fldenv %0" + : : "m" (*e) + : "st", "st(1)", "st(2)", "st(3)", + "st(4)", "st(5)", "st(6)", "st(7)"); +} + +static __always_inline int +libc_feupdateenv_test_sse (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 (__glibc_unlikely (~(old_mxcsr >> 7) & cur_ex)) + __feraiseexcept (cur_ex); + + /* Test for exceptions raised since the hold. */ + return cur_ex & ex; +} + +static __always_inline int +libc_feupdateenv_test_387 (fenv_t *e, int ex) +{ + fexcept_t cur_ex; + + /* Save current exceptions. */ + asm volatile ("fnstsw %0" : "=a" (cur_ex)); + cur_ex &= FE_ALL_EXCEPT; + + /* Reload original environment. */ + libc_fesetenv_387 (e); + + /* Merge current exceptions. */ + __feraiseexcept (cur_ex); + + /* Test for exceptions raised since the hold. */ + return cur_ex & ex; +} + +static __always_inline void +libc_feupdateenv_sse (fenv_t *e) +{ + libc_feupdateenv_test_sse (e, 0); +} + +static __always_inline void +libc_feupdateenv_387 (fenv_t *e) +{ + libc_feupdateenv_test_387 (e, 0); +} + +static __always_inline void +libc_feholdsetround_sse (fenv_t *e, int r) +{ + unsigned int mxcsr; + asm (STMXCSR " %0" : "=m" (*&mxcsr)); + e->__mxcsr = mxcsr; + mxcsr = (mxcsr & ~0x6000) | (r << 3); + asm volatile (LDMXCSR " %0" : : "m" (*&mxcsr)); +} + +static __always_inline void +libc_feholdsetround_387_prec (fenv_t *e, int r) +{ + fpu_control_t cw; + + _FPU_GETCW (cw); + e->__control_word = cw; + cw &= ~(_FPU_RC_ZERO | _FPU_EXTENDED); + cw |= r; + _FPU_SETCW (cw); +} + +static __always_inline void +libc_feholdsetround_387 (fenv_t *e, int r) +{ + libc_feholdsetround_387_prec (e, r | _FPU_EXTENDED); +} + +static __always_inline void +libc_feholdsetround_387_53bit (fenv_t *e, int r) +{ + libc_feholdsetround_387_prec (e, r | _FPU_DOUBLE); +} + +static __always_inline void +libc_feresetround_sse (fenv_t *e) +{ + unsigned int mxcsr; + asm (STMXCSR " %0" : "=m" (*&mxcsr)); + mxcsr = (mxcsr & ~0x6000) | (e->__mxcsr & 0x6000); + asm volatile (LDMXCSR " %0" : : "m" (*&mxcsr)); +} + +static __always_inline void +libc_feresetround_387 (fenv_t *e) +{ + _FPU_SETCW (e->__control_word); +} + +#ifdef __SSE_MATH__ +# define libc_feholdexceptf libc_feholdexcept_sse +# define libc_fesetroundf libc_fesetround_sse +# define libc_feholdexcept_setroundf libc_feholdexcept_setround_sse +# define libc_fetestexceptf libc_fetestexcept_sse +# define libc_fesetenvf libc_fesetenv_sse +# define libc_feupdateenv_testf libc_feupdateenv_test_sse +# define libc_feupdateenvf libc_feupdateenv_sse +# define libc_feholdsetroundf libc_feholdsetround_sse +# define libc_feresetroundf libc_feresetround_sse +#else +# define libc_feholdexceptf libc_feholdexcept_387 +# define libc_fesetroundf libc_fesetround_387 +# define libc_feholdexcept_setroundf libc_feholdexcept_setround_387 +# define libc_fetestexceptf libc_fetestexcept_387 +# define libc_fesetenvf libc_fesetenv_387 +# define libc_feupdateenv_testf libc_feupdateenv_test_387 +# define libc_feupdateenvf libc_feupdateenv_387 +# define libc_feholdsetroundf libc_feholdsetround_387 +# define libc_feresetroundf libc_feresetround_387 +#endif /* __SSE_MATH__ */ + +#ifdef __SSE2_MATH__ +# define libc_feholdexcept libc_feholdexcept_sse +# define libc_fesetround libc_fesetround_sse +# define libc_feholdexcept_setround libc_feholdexcept_setround_sse +# define libc_fetestexcept libc_fetestexcept_sse +# define libc_fesetenv libc_fesetenv_sse +# define libc_feupdateenv_test libc_feupdateenv_test_sse +# define libc_feupdateenv libc_feupdateenv_sse +# define libc_feholdsetround libc_feholdsetround_sse +# define libc_feresetround libc_feresetround_sse +#else +# define libc_feholdexcept libc_feholdexcept_387 +# define libc_fesetround libc_fesetround_387 +# define libc_feholdexcept_setround libc_feholdexcept_setround_387 +# define libc_fetestexcept libc_fetestexcept_387 +# define libc_fesetenv libc_fesetenv_387 +# define libc_feupdateenv_test libc_feupdateenv_test_387 +# define libc_feupdateenv libc_feupdateenv_387 +# define libc_feholdsetround libc_feholdsetround_387 +# define libc_feresetround libc_feresetround_387 +#endif /* __SSE2_MATH__ */ + +#define libc_feholdexceptl libc_feholdexcept_387 +#define libc_fesetroundl libc_fesetround_387 +#define libc_feholdexcept_setroundl libc_feholdexcept_setround_387 +#define libc_fetestexceptl libc_fetestexcept_387 +#define libc_fesetenvl libc_fesetenv_387 +#define libc_feupdateenv_testl libc_feupdateenv_test_387 +#define libc_feupdateenvl libc_feupdateenv_387 +#define libc_feholdsetroundl libc_feholdsetround_387 +#define libc_feresetroundl libc_feresetround_387 + +#ifndef __SSE2_MATH__ +# define libc_feholdexcept_setround_53bit libc_feholdexcept_setround_387_53bit +# define libc_feholdsetround_53bit libc_feholdsetround_387_53bit +#endif + +#ifdef __x86_64__ +/* The SSE rounding mode is used by soft-fp (libgcc and glibc) on + x86_64, so that must be set for float128 computations. */ +# define SET_RESTORE_ROUNDF128(RM) \ + SET_RESTORE_ROUND_GENERIC (RM, libc_feholdsetround_sse, libc_feresetround_sse) +# define libc_feholdexcept_setroundf128 libc_feholdexcept_setround_sse +# define libc_feupdateenv_testf128 libc_feupdateenv_test_sse +#else +/* The 387 rounding mode is used by soft-fp for 32-bit, but whether + 387 or SSE exceptions are used depends on whether libgcc was built + for SSE math, which is not known when glibc is being built. */ +# define libc_feholdexcept_setroundf128 default_libc_feholdexcept_setround +# define libc_feupdateenv_testf128 default_libc_feupdateenv_test +#endif + +/* We have support for rounding mode context. */ +#define HAVE_RM_CTX 1 + +static __always_inline void +libc_feholdexcept_setround_sse_ctx (struct rm_ctx *ctx, int r) +{ + unsigned int mxcsr, new_mxcsr; + asm (STMXCSR " %0" : "=m" (*&mxcsr)); + new_mxcsr = ((mxcsr | 0x1f80) & ~0x603f) | (r << 3); + + ctx->env.__mxcsr = mxcsr; + if (__glibc_unlikely (mxcsr != new_mxcsr)) + { + asm volatile (LDMXCSR " %0" : : "m" (*&new_mxcsr)); + ctx->updated_status = true; + } + else + ctx->updated_status = false; +} + +/* Unconditional since we want to overwrite any exceptions that occurred in the + context. This is also why all fehold* functions unconditionally write into + ctx->env. */ +static __always_inline void +libc_fesetenv_sse_ctx (struct rm_ctx *ctx) +{ + libc_fesetenv_sse (&ctx->env); +} + +static __always_inline void +libc_feupdateenv_sse_ctx (struct rm_ctx *ctx) +{ + if (__glibc_unlikely (ctx->updated_status)) + libc_feupdateenv_test_sse (&ctx->env, 0); +} + +static __always_inline void +libc_feholdexcept_setround_387_prec_ctx (struct rm_ctx *ctx, int r) +{ + libc_feholdexcept_387 (&ctx->env); + + fpu_control_t cw = ctx->env.__control_word; + fpu_control_t old_cw = cw; + cw &= ~(_FPU_RC_ZERO | _FPU_EXTENDED); + cw |= r | 0x3f; + + if (__glibc_unlikely (old_cw != cw)) + { + _FPU_SETCW (cw); + ctx->updated_status = true; + } + else + ctx->updated_status = false; +} + +static __always_inline void +libc_feholdexcept_setround_387_ctx (struct rm_ctx *ctx, int r) +{ + libc_feholdexcept_setround_387_prec_ctx (ctx, r | _FPU_EXTENDED); +} + +static __always_inline void +libc_feholdexcept_setround_387_53bit_ctx (struct rm_ctx *ctx, int r) +{ + libc_feholdexcept_setround_387_prec_ctx (ctx, r | _FPU_DOUBLE); +} + +static __always_inline void +libc_feholdsetround_387_prec_ctx (struct rm_ctx *ctx, int r) +{ + fpu_control_t cw, new_cw; + + _FPU_GETCW (cw); + new_cw = cw; + new_cw &= ~(_FPU_RC_ZERO | _FPU_EXTENDED); + new_cw |= r; + + ctx->env.__control_word = cw; + if (__glibc_unlikely (new_cw != cw)) + { + _FPU_SETCW (new_cw); + ctx->updated_status = true; + } + else + ctx->updated_status = false; +} + +static __always_inline void +libc_feholdsetround_387_ctx (struct rm_ctx *ctx, int r) +{ + libc_feholdsetround_387_prec_ctx (ctx, r | _FPU_EXTENDED); +} + +static __always_inline void +libc_feholdsetround_387_53bit_ctx (struct rm_ctx *ctx, int r) +{ + libc_feholdsetround_387_prec_ctx (ctx, r | _FPU_DOUBLE); +} + +static __always_inline void +libc_feholdsetround_sse_ctx (struct rm_ctx *ctx, int r) +{ + unsigned int mxcsr, new_mxcsr; + + asm (STMXCSR " %0" : "=m" (*&mxcsr)); + new_mxcsr = (mxcsr & ~0x6000) | (r << 3); + + ctx->env.__mxcsr = mxcsr; + if (__glibc_unlikely (new_mxcsr != mxcsr)) + { + asm volatile (LDMXCSR " %0" : : "m" (*&new_mxcsr)); + ctx->updated_status = true; + } + else + ctx->updated_status = false; +} + +static __always_inline void +libc_feresetround_sse_ctx (struct rm_ctx *ctx) +{ + if (__glibc_unlikely (ctx->updated_status)) + libc_feresetround_sse (&ctx->env); +} + +static __always_inline void +libc_feresetround_387_ctx (struct rm_ctx *ctx) +{ + if (__glibc_unlikely (ctx->updated_status)) + _FPU_SETCW (ctx->env.__control_word); +} + +static __always_inline void +libc_feupdateenv_387_ctx (struct rm_ctx *ctx) +{ + if (__glibc_unlikely (ctx->updated_status)) + libc_feupdateenv_test_387 (&ctx->env, 0); +} + +#ifdef __SSE_MATH__ +# define libc_feholdexcept_setroundf_ctx libc_feholdexcept_setround_sse_ctx +# define libc_fesetenvf_ctx libc_fesetenv_sse_ctx +# define libc_feupdateenvf_ctx libc_feupdateenv_sse_ctx +# define libc_feholdsetroundf_ctx libc_feholdsetround_sse_ctx +# define libc_feresetroundf_ctx libc_feresetround_sse_ctx +#else +# define libc_feholdexcept_setroundf_ctx libc_feholdexcept_setround_387_ctx +# define libc_feupdateenvf_ctx libc_feupdateenv_387_ctx +# define libc_feholdsetroundf_ctx libc_feholdsetround_387_ctx +# define libc_feresetroundf_ctx libc_feresetround_387_ctx +#endif /* __SSE_MATH__ */ + +#ifdef __SSE2_MATH__ +# if defined (__x86_64__) || !defined (MATH_SET_BOTH_ROUNDING_MODES) +# define libc_feholdexcept_setround_ctx libc_feholdexcept_setround_sse_ctx +# define libc_fesetenv_ctx libc_fesetenv_sse_ctx +# define libc_feupdateenv_ctx libc_feupdateenv_sse_ctx +# define libc_feholdsetround_ctx libc_feholdsetround_sse_ctx +# define libc_feresetround_ctx libc_feresetround_sse_ctx +# else +# define libc_feholdexcept_setround_ctx default_libc_feholdexcept_setround_ctx +# define libc_fesetenv_ctx default_libc_fesetenv_ctx +# define libc_feupdateenv_ctx default_libc_feupdateenv_ctx +# define libc_feholdsetround_ctx default_libc_feholdsetround_ctx +# define libc_feresetround_ctx default_libc_feresetround_ctx +# endif +#else +# define libc_feholdexcept_setround_ctx libc_feholdexcept_setround_387_ctx +# define libc_feupdateenv_ctx libc_feupdateenv_387_ctx +# define libc_feholdsetround_ctx libc_feholdsetround_387_ctx +# define libc_feresetround_ctx libc_feresetround_387_ctx +#endif /* __SSE2_MATH__ */ + +#define libc_feholdexcept_setroundl_ctx libc_feholdexcept_setround_387_ctx +#define libc_feupdateenvl_ctx libc_feupdateenv_387_ctx +#define libc_feholdsetroundl_ctx libc_feholdsetround_387_ctx +#define libc_feresetroundl_ctx libc_feresetround_387_ctx + +#ifndef __SSE2_MATH__ +# define libc_feholdsetround_53bit_ctx libc_feholdsetround_387_53bit_ctx +# define libc_feresetround_53bit_ctx libc_feresetround_387_ctx +#endif + +#undef __mxcsr + +#include_next + +#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 #include_next #ifdef __SSE4_1__ -- cgit 1.4.1