diff options
61 files changed, 978 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog index da1fcc9cef..5f06ead391 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,116 @@ +2016-09-07 Joseph Myers <joseph@codesourcery.com> + + * math/fegetmode.c: New file. + * math/fesetmode.c: Likewise. + * sysdeps/i386/fpu/fegetmode.c: Likewise. + * sysdeps/i386/fpu/fesetmode.c: Likewise. + * sysdeps/x86_64/fpu/fegetmode.c: Likewise. + * sysdeps/x86_64/fpu/fesetmode.c: Likewise. + * math/fenv.h: Update comment on inclusion of <bits/fenv.h>. + [__GLIBC_USE (IEC_60559_BFP_EXT)] (fegetmode): New function + declaration. + [__GLIBC_USE (IEC_60559_BFP_EXT)] (fesetmode): Likewise. + * bits/fenv.h [__GLIBC_USE (IEC_60559_BFP_EXT)] (femode_t): New + typedef. + [__GLIBC_USE (IEC_60559_BFP_EXT)] (FE_DFL_MODE): New macro. + * sysdeps/aarch64/bits/fenv.h [__GLIBC_USE (IEC_60559_BFP_EXT)] + (femode_t): New typedef. + [__GLIBC_USE (IEC_60559_BFP_EXT)] (FE_DFL_MODE): New macro. + * sysdeps/alpha/fpu/bits/fenv.h [__GLIBC_USE (IEC_60559_BFP_EXT)] + (femode_t): New typedef. + [__GLIBC_USE (IEC_60559_BFP_EXT)] (FE_DFL_MODE): New macro. + * sysdeps/arm/bits/fenv.h [__GLIBC_USE (IEC_60559_BFP_EXT)] + (femode_t): New typedef. + [__GLIBC_USE (IEC_60559_BFP_EXT)] (FE_DFL_MODE): New macro. + * sysdeps/hppa/fpu/bits/fenv.h [__GLIBC_USE (IEC_60559_BFP_EXT)] + (femode_t): New typedef. + [__GLIBC_USE (IEC_60559_BFP_EXT)] (FE_DFL_MODE): New macro. + * sysdeps/ia64/bits/fenv.h [__GLIBC_USE (IEC_60559_BFP_EXT)] + (femode_t): New typedef. + [__GLIBC_USE (IEC_60559_BFP_EXT)] (FE_DFL_MODE): New macro. + * sysdeps/m68k/fpu/bits/fenv.h [__GLIBC_USE (IEC_60559_BFP_EXT)] + (femode_t): New typedef. + [__GLIBC_USE (IEC_60559_BFP_EXT)] (FE_DFL_MODE): New macro. + * sysdeps/microblaze/bits/fenv.h [__GLIBC_USE (IEC_60559_BFP_EXT)] + (femode_t): New typedef. + [__GLIBC_USE (IEC_60559_BFP_EXT)] (FE_DFL_MODE): New macro. + * sysdeps/mips/bits/fenv.h [__GLIBC_USE (IEC_60559_BFP_EXT)] + (femode_t): New typedef. + [__GLIBC_USE (IEC_60559_BFP_EXT)] (FE_DFL_MODE): New macro. + * sysdeps/nios2/bits/fenv.h [__GLIBC_USE (IEC_60559_BFP_EXT)] + (femode_t): New typedef. + [__GLIBC_USE (IEC_60559_BFP_EXT)] (FE_DFL_MODE): New macro. + * sysdeps/powerpc/bits/fenv.h [__GLIBC_USE (IEC_60559_BFP_EXT)] + (femode_t): New typedef. + [__GLIBC_USE (IEC_60559_BFP_EXT)] (__fe_dfl_mode): New variable + declaration. + [__GLIBC_USE (IEC_60559_BFP_EXT)] (FE_DFL_MODE): New macro. + * sysdeps/s390/fpu/bits/fenv.h [__GLIBC_USE (IEC_60559_BFP_EXT)] + (femode_t): New typedef. + [__GLIBC_USE (IEC_60559_BFP_EXT)] (FE_DFL_MODE): New macro. + * sysdeps/sh/bits/fenv.h [__GLIBC_USE (IEC_60559_BFP_EXT)] + (femode_t): New typedef. + [__GLIBC_USE (IEC_60559_BFP_EXT)] (FE_DFL_MODE): New macro. + * sysdeps/sparc/fpu/bits/fenv.h [__GLIBC_USE (IEC_60559_BFP_EXT)] + (femode_t): New typedef. + [__GLIBC_USE (IEC_60559_BFP_EXT)] (FE_DFL_MODE): New macro. + * sysdeps/tile/bits/fenv.h [__GLIBC_USE (IEC_60559_BFP_EXT)] + (femode_t): New typedef. + [__GLIBC_USE (IEC_60559_BFP_EXT)] (FE_DFL_MODE): New macro. + * sysdeps/x86/fpu/bits/fenv.h [__GLIBC_USE (IEC_60559_BFP_EXT)] + (femode_t): New typedef. + [__GLIBC_USE (IEC_60559_BFP_EXT)] (FE_DFL_MODE): New macro. + * manual/arith.texi (FE_DFL_MODE): Document macro. + (fegetmode): Document function. + (fesetmode): Likewise. + * math/Versions (fegetmode): New libm symbol at version + GLIBC_2.25. + (fesetmode): Likewise. + * math/Makefile (libm-support): Add fegetmode and fesetmode. + (tests): Add test-femode and test-femode-traps. + * math/test-femode-traps.c: New file. + * math/test-femode.c: Likewise. + * sysdeps/powerpc/fpu/fenv_const.c (__fe_dfl_mode): Declare as + alias for __fe_dfl_env. + * sysdeps/powerpc/nofpu/fenv_const.c (__fe_dfl_mode): Likewise. + * sysdeps/powerpc/powerpc32/e500/nofpu/fenv_const.c + (__fe_dfl_mode): Likewise. + * sysdeps/powerpc/Versions (__fe_dfl_mode): New libm symbol at + version GLIBC_2.25. + * sysdeps/nacl/libm.abilist: Update. + * sysdeps/unix/sysv/linux/aarch64/libm.abilist: Likewise. + * sysdeps/unix/sysv/linux/alpha/libm.abilist: Likewise. + * sysdeps/unix/sysv/linux/arm/libm.abilist: Likewise. + * sysdeps/unix/sysv/linux/hppa/libm.abilist: Likewise. + * sysdeps/unix/sysv/linux/i386/libm.abilist: Likewise. + * sysdeps/unix/sysv/linux/ia64/libm.abilist: Likewise. + * sysdeps/unix/sysv/linux/m68k/coldfire/libm.abilist: Likewise. + * sysdeps/unix/sysv/linux/m68k/m680x0/libm.abilist: Likewise. + * sysdeps/unix/sysv/linux/microblaze/libm.abilist: Likewise. + * sysdeps/unix/sysv/linux/mips/mips32/libm.abilist: Likewise. + * sysdeps/unix/sysv/linux/mips/mips64/libm.abilist: Likewise. + * sysdeps/unix/sysv/linux/nios2/libm.abilist: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libm.abilist: + Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libm.abilist: + Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/libm-le.abilist: + Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/libm.abilist: + Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/libm.abilist: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/libm.abilist: Likewise. + * sysdeps/unix/sysv/linux/sh/libm.abilist: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/libm.abilist: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/libm.abilist: Likewise. + * sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libm.abilist: + Likewise. + * sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libm.abilist: + Likewise. + * sysdeps/unix/sysv/linux/tile/tilepro/libm.abilist: Likewise. + * sysdeps/unix/sysv/linux/x86_64/64/libm.abilist: Likewise. + * sysdeps/unix/sysv/linux/x86_64/x32/libm.abilist: Likewise. + 2016-09-06 H.J. Lu <hongjiu.lu@intel.com> [BZ #20495] diff --git a/NEWS b/NEWS index 369655f5a1..ba1ec715a9 100644 --- a/NEWS +++ b/NEWS @@ -32,8 +32,9 @@ Version 2.25 presently cannot avoid being compiled under _GNU_SOURCE, exacerbating the problem. -* The fesetexcept and fetestexceptflag functions from TS 18661-1:2014 are - added to libm. +* New <fenv.h> features from TS 18661-1:2014 are added to libm: the + fesetexcept, fetestexceptflag, fegetmode and fesetmode functions, + the femode_t type and the FE_DFL_MODE macro. * The <sys/quota.h> header now includes the <linux/quota.h> header. Support for the Linux quota interface which predates kernel version 2.4.22 has diff --git a/bits/fenv.h b/bits/fenv.h index f9b61d5e42..deeceeeec0 100644 --- a/bits/fenv.h +++ b/bits/fenv.h @@ -53,3 +53,11 @@ fenv_t; /* If the default argument is used we use this value. */ #define FE_DFL_ENV ((const fenv_t *) -1l) + +#if __GLIBC_USE (IEC_60559_BFP_EXT) +/* Type representing floating-point control modes. */ +typedef unsigned int femode_t; + +/* Default floating-point control modes. */ +# define FE_DFL_MODE ((const femode_t *) -1L) +#endif diff --git a/manual/arith.texi b/manual/arith.texi index 3a04bc2d62..23b93736ac 100644 --- a/manual/arith.texi +++ b/manual/arith.texi @@ -1127,6 +1127,39 @@ non-zero value otherwise. @end deftypefun @noindent +TS 18661-1:2014 defines additional functions to save and restore +floating-point control modes (such as the rounding mode and whether +traps are enabled) while leaving other status (such as raised flags) +unchanged. + +@vindex FE_DFL_MODE +The special macro @code{FE_DFL_MODE} may be passed to +@code{fesetmode}. It represents the floating-point control modes at +program start. + +@comment fenv.h +@comment ISO +@deftypefun int fegetmode (femode_t *@var{modep}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Store the floating-point control modes in the variable pointed to by +@var{modep}. + +The function returns zero in case the operation was successful, a +non-zero value otherwise. +@end deftypefun + +@comment fenv.h +@comment ISO +@deftypefun int fesetmode (const femode_t *@var{modep}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Set the floating-point control modes to those described by +@var{modep}. + +The function returns zero in case the operation was successful, a +non-zero value otherwise. +@end deftypefun + +@noindent To control for individual exceptions if raising them causes a trap to occur, you can use the following two functions. diff --git a/math/Makefile b/math/Makefile index 6a90a367ab..fc48960fb0 100644 --- a/math/Makefile +++ b/math/Makefile @@ -41,7 +41,8 @@ libm-support = s_lib_version s_matherr s_signgam \ fclrexcpt fgetexcptflg fraiseexcpt fsetexcptflg \ ftestexcept fegetround fesetround fegetenv feholdexcpt \ fesetenv feupdateenv t_exp fedisblxcpt feenablxcpt \ - fegetexcept fesetexcept fetestexceptflag + fegetexcept fesetexcept fetestexceptflag fegetmode \ + fesetmode # Wrappers for these functions generated per type using a file named # <func>_template.c and the appropriate math-type-macros-<TYPE>.h. @@ -152,7 +153,8 @@ tests = test-matherr test-fenv atest-exp atest-sincos atest-exp2 basic-test \ test-signgam-uint test-signgam-uint-init test-signgam-ullong \ test-signgam-ullong-init test-nan-overflow test-nan-payload \ test-fexcept test-fexcept-traps test-fesetexcept \ - test-fesetexcept-traps test-fetestexceptflag $(tests-static) + test-fesetexcept-traps test-fetestexceptflag test-femode \ + test-femode-traps $(tests-static) tests-static = test-fpucw-static test-fpucw-ieee-static \ test-signgam-uchar-static test-signgam-uchar-init-static \ test-signgam-uint-static test-signgam-uint-init-static \ diff --git a/math/Versions b/math/Versions index 1c1683fed4..a429221340 100644 --- a/math/Versions +++ b/math/Versions @@ -215,6 +215,6 @@ libm { nextdown; nextdownf; nextdownl; } GLIBC_2.25 { - fesetexcept; fetestexceptflag; + fesetexcept; fetestexceptflag; fegetmode; fesetmode; } } diff --git a/math/fegetmode.c b/math/fegetmode.c new file mode 100644 index 0000000000..25f299fc13 --- /dev/null +++ b/math/fegetmode.c @@ -0,0 +1,27 @@ +/* Store current floating-point control modes. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <fenv.h> + +int +fegetmode (femode_t *modep) +{ + /* Nothing to do. */ + return 0; +} +stub_warning (fegetmode) diff --git a/math/fenv.h b/math/fenv.h index 10d32db909..9006aa2fff 100644 --- a/math/fenv.h +++ b/math/fenv.h @@ -38,6 +38,12 @@ fexcept_t type for object representing the floating-point exception flags including status associated with the flags + femode_t type for object representing floating-point control modes + + FE_DFL_MODE macro of type pointer to const femode_t to be used as the + argument to fesetmode; in this case the default control + modes will be used + The following macros are defined iff the implementation supports this kind of exception. FE_INEXACT inexact result @@ -122,6 +128,18 @@ extern int fesetenv (const fenv_t *__envp) __THROW; extern int feupdateenv (const fenv_t *__envp) __THROW; +/* Control modes. */ + +#if __GLIBC_USE (IEC_60559_BFP_EXT) +/* Store the current floating-point control modes in the object + pointed to by MODEP. */ +extern int fegetmode (femode_t *__modep) __THROW; + +/* Establish the floating-point control modes represented by the + object pointed to by MODEP. */ +extern int fesetmode (const femode_t *__modep) __THROW; +#endif + /* Include optimization. */ #ifdef __OPTIMIZE__ # include <bits/fenvinline.h> diff --git a/math/fesetmode.c b/math/fesetmode.c new file mode 100644 index 0000000000..0d040e49a4 --- /dev/null +++ b/math/fesetmode.c @@ -0,0 +1,27 @@ +/* Install given floating-point control modes. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <fenv.h> + +int +fesetmode (const femode_t *modep) +{ + /* Nothing to do. */ + return 0; +} +stub_warning (fesetmode) diff --git a/math/test-femode-traps.c b/math/test-femode-traps.c new file mode 100644 index 0000000000..dd22765831 --- /dev/null +++ b/math/test-femode-traps.c @@ -0,0 +1,149 @@ +/* Test femode_t functions: test handling of exception traps. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <stdio.h> +#include <math-tests.h> + +static int +test_ee (int exc1, int exc2) +{ + int result = 0; + printf ("testing %x %x\n", (unsigned int) exc1, (unsigned int) exc2); + + fedisableexcept (FE_ALL_EXCEPT); + int ret = feenableexcept (exc1); + if (ret == -1) + { + if (EXCEPTION_ENABLE_SUPPORTED (exc1)) + { + puts ("first feenableexcept failed unexpectedly"); + result = 1; + } + else + puts ("first feenableexcept failed, cannot test"); + return result; + } + femode_t saved; + ret = fegetmode (&saved); + if (ret != 0) + { + puts ("fegetmode failed"); + result = 1; + return result; + } + fedisableexcept (FE_ALL_EXCEPT); + ret = feenableexcept (exc2); + if (ret == -1) + { + if (EXCEPTION_ENABLE_SUPPORTED (exc2)) + { + puts ("second feenableexcept failed unexpectedly"); + result = 1; + } + else + puts ("second feenableexcept failed, cannot test"); + return result; + } + ret = fesetmode (&saved); + if (ret != 0) + { + puts ("fesetmode failed"); + result = 1; + return result; + } + /* Verify that the set of enabled traps was restored. */ + ret = fegetexcept (); + if (ret != exc1) + { + printf ("restored enabled traps %x not %x\n", (unsigned int) ret, + (unsigned int) exc1); + result = 1; + } + /* Likewise, with default modes. */ + ret = fesetmode (FE_DFL_MODE); + if (ret != 0) + { + puts ("fesetmode (FE_DFL_MODE) failed"); + result = 1; + return result; + } + ret = fegetexcept (); + if (ret != 0) + { + printf ("FE_DFL_MODE enabled traps %x not 0\n", (unsigned int) ret); + result = 1; + } + + return result; +} + +static int +test_e (int exc1) +{ + int result = 0; + + result |= test_ee (exc1, 0); + result |= test_ee (exc1, FE_ALL_EXCEPT); +#ifdef FE_DIVBYZERO + result |= test_ee (exc1, FE_DIVBYZERO); +#endif +#ifdef FE_INEXACT + result |= test_ee (exc1, FE_INEXACT); +#endif +#ifdef FE_INVALID + result |= test_ee (exc1, FE_INVALID); +#endif +#ifdef FE_OVERFLOW + result |= test_ee (exc1, FE_OVERFLOW); +#endif +#ifdef FE_UNDERFLOW + result |= test_ee (exc1, FE_UNDERFLOW); +#endif + + return result; +} + +static int +do_test (void) +{ + int result = 0; + + result |= test_e (0); + result |= test_e (FE_ALL_EXCEPT); +#ifdef FE_DIVBYZERO + result |= test_e (FE_DIVBYZERO); +#endif +#ifdef FE_INEXACT + result |= test_e (FE_INEXACT); +#endif +#ifdef FE_INVALID + result |= test_e (FE_INVALID); +#endif +#ifdef FE_OVERFLOW + result |= test_e (FE_OVERFLOW); +#endif +#ifdef FE_UNDERFLOW + result |= test_e (FE_UNDERFLOW); +#endif + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/math/test-femode.c b/math/test-femode.c new file mode 100644 index 0000000000..1e80f32225 --- /dev/null +++ b/math/test-femode.c @@ -0,0 +1,231 @@ +/* Test femode_t functions. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <stdio.h> +#include <math-tests.h> + +static int +test_mmee (int mode1, int mode2, int exc1, int exc2) +{ + int result = 0; + printf ("testing %x %x %x %x\n", (unsigned int) mode1, (unsigned int) mode2, + (unsigned int) exc1, (unsigned int) exc2); + + feclearexcept (FE_ALL_EXCEPT); + int ret = fesetround (mode1); + if (ret != 0) + { + if (ROUNDING_TESTS (float, mode1)) + { + puts ("first fesetround failed unexpectedly"); + result = 1; + } + else + puts ("first fesetround failed, cannot test"); + return result; + } + ret = fesetexcept (exc1); + if (ret != 0) + { + if (EXCEPTION_TESTS (float) || exc1 == 0) + { + puts ("first fesetexcept failed unexpectedly"); + result = 1; + } + else + puts ("first fesetexcept failed, cannot test"); + return result; + } + femode_t saved; + ret = fegetmode (&saved); + if (ret != 0) + { + puts ("fegetmode failed"); + result = 1; + return result; + } + feclearexcept (FE_ALL_EXCEPT); + ret = fesetround (mode2); + if (ret != 0) + { + if (ROUNDING_TESTS (float, mode2)) + { + puts ("second fesetround failed unexpectedly"); + result = 1; + } + else + puts ("second fesetround failed, cannot test"); + return result; + } + ret = fesetexcept (exc2); + if (ret != 0) + { + if (EXCEPTION_TESTS (float) || exc2 == 0) + { + puts ("second fesetexcept failed unexpectedly"); + result = 1; + } + else + puts ("second fesetexcept failed, cannot test"); + return result; + } + ret = fesetmode (&saved); + if (ret != 0) + { + puts ("fesetmode failed"); + result = 1; + return result; + } + /* Verify that the rounding mode was restored but the exception + flags remain unchanged. */ + ret = fegetround (); + if (ret != mode1) + { + printf ("restored rounding mode %x not %x\n", (unsigned int) ret, + (unsigned int) mode1); + result = 1; + } + ret = fetestexcept (FE_ALL_EXCEPT); + if (ret != exc2) + { + printf ("exceptions %x not %x\n", (unsigned int) ret, + (unsigned int) exc2); + result = 1; + } + /* Likewise, with default modes. */ + ret = fesetmode (FE_DFL_MODE); + if (ret != 0) + { + puts ("fesetmode (FE_DFL_MODE) failed"); + result = 1; + return result; + } + ret = fegetround (); + if (ret != FE_TONEAREST) + { + printf ("FE_DFL_MODE rounding mode %x not %x\n", (unsigned int) ret, + (unsigned int) FE_TONEAREST); + result = 1; + } + ret = fetestexcept (FE_ALL_EXCEPT); + if (ret != exc2) + { + printf ("FE_DFL_MODE exceptions %x not %x\n", (unsigned int) ret, + (unsigned int) exc2); + result = 1; + } + return result; +} + +static int +test_mme (int mode1, int mode2, int exc1) +{ + int result = 0; + + result |= test_mmee (mode1, mode2, exc1, 0); + result |= test_mmee (mode1, mode2, exc1, FE_ALL_EXCEPT); +#ifdef FE_DIVBYZERO + result |= test_mmee (mode1, mode2, exc1, FE_DIVBYZERO); +#endif +#ifdef FE_INEXACT + result |= test_mmee (mode1, mode2, exc1, FE_INEXACT); +#endif +#ifdef FE_INVALID + result |= test_mmee (mode1, mode2, exc1, FE_INVALID); +#endif +#ifdef FE_OVERFLOW + result |= test_mmee (mode1, mode2, exc1, FE_OVERFLOW); +#endif +#ifdef FE_UNDERFLOW + result |= test_mmee (mode1, mode2, exc1, FE_UNDERFLOW); +#endif + + return result; +} + +static int +test_mm (int mode1, int mode2) +{ + int result = 0; + + result |= test_mme (mode1, mode2, 0); + result |= test_mme (mode1, mode2, FE_ALL_EXCEPT); +#ifdef FE_DIVBYZERO + result |= test_mme (mode1, mode2, FE_DIVBYZERO); +#endif +#ifdef FE_INEXACT + result |= test_mme (mode1, mode2, FE_INEXACT); +#endif +#ifdef FE_INVALID + result |= test_mme (mode1, mode2, FE_INVALID); +#endif +#ifdef FE_OVERFLOW + result |= test_mme (mode1, mode2, FE_OVERFLOW); +#endif +#ifdef FE_UNDERFLOW + result |= test_mme (mode1, mode2, FE_UNDERFLOW); +#endif + + return result; +} + +static int +test_m (int mode1) +{ + int result = 0; + +#ifdef FE_DOWNWARD + result |= test_mm (mode1, FE_DOWNWARD); +#endif +#ifdef FE_TONEAREST + result |= test_mm (mode1, FE_TONEAREST); +#endif +#ifdef FE_TOWARDZERO + result |= test_mm (mode1, FE_TOWARDZERO); +#endif +#ifdef FE_UPWARD + result |= test_mm (mode1, FE_UPWARD); +#endif + + return result; +} + +static int +do_test (void) +{ + int result = 0; + +#ifdef FE_DOWNWARD + result |= test_m (FE_DOWNWARD); +#endif +#ifdef FE_TONEAREST + result |= test_m (FE_TONEAREST); +#endif +#ifdef FE_TOWARDZERO + result |= test_m (FE_TOWARDZERO); +#endif +#ifdef FE_UPWARD + result |= test_m (FE_UPWARD); +#endif + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/sysdeps/aarch64/bits/fenv.h b/sysdeps/aarch64/bits/fenv.h index aced0d33b2..9df57a1bbf 100644 --- a/sysdeps/aarch64/bits/fenv.h +++ b/sysdeps/aarch64/bits/fenv.h @@ -72,3 +72,11 @@ fenv_t; /* Floating-point environment where none of the exceptions are masked. */ # define FE_NOMASK_ENV ((const fenv_t *) -2) #endif + +#if __GLIBC_USE (IEC_60559_BFP_EXT) +/* Type representing floating-point control modes. */ +typedef unsigned int femode_t; + +/* Default floating-point control modes. */ +# define FE_DFL_MODE ((const femode_t *) -1L) +#endif diff --git a/sysdeps/alpha/fpu/bits/fenv.h b/sysdeps/alpha/fpu/bits/fenv.h index b7da4a0eae..0688898ce7 100644 --- a/sysdeps/alpha/fpu/bits/fenv.h +++ b/sysdeps/alpha/fpu/bits/fenv.h @@ -131,3 +131,11 @@ typedef unsigned long int fenv_t; /* The system calls to talk to the kernel's FP code. */ extern unsigned long int __ieee_get_fp_control (void) __THROW; extern void __ieee_set_fp_control (unsigned long int __value) __THROW; + +#if __GLIBC_USE (IEC_60559_BFP_EXT) +/* Type representing floating-point control modes. */ +typedef unsigned long int femode_t; + +/* Default floating-point control modes. */ +# define FE_DFL_MODE ((const femode_t *) 0x8800000000000000UL) +#endif diff --git a/sysdeps/arm/bits/fenv.h b/sysdeps/arm/bits/fenv.h index 8e89fc1819..c82fecb48f 100644 --- a/sysdeps/arm/bits/fenv.h +++ b/sysdeps/arm/bits/fenv.h @@ -80,3 +80,11 @@ fenv_t; /* Floating-point environment where none of the exceptions are masked. */ # define FE_NOMASK_ENV ((const fenv_t *) -2) #endif + +#if __GLIBC_USE (IEC_60559_BFP_EXT) +/* Type representing floating-point control modes. */ +typedef unsigned int femode_t; + +/* Default floating-point control modes. */ +# define FE_DFL_MODE ((const femode_t *) -1L) +#endif diff --git a/sysdeps/hppa/fpu/bits/fenv.h b/sysdeps/hppa/fpu/bits/fenv.h index cae9daeb04..e35e3553f9 100644 --- a/sysdeps/hppa/fpu/bits/fenv.h +++ b/sysdeps/hppa/fpu/bits/fenv.h @@ -89,3 +89,11 @@ typedef struct /* Floating-point environment where none of the exceptions are masked. */ # define FE_NOMASK_ENV ((const fenv_t *) -2) #endif + +#if __GLIBC_USE (IEC_60559_BFP_EXT) +/* Type representing floating-point control modes. */ +typedef unsigned int femode_t; + +/* Default floating-point control modes. */ +# define FE_DFL_MODE ((const femode_t *) -1L) +#endif diff --git a/sysdeps/i386/fpu/fegetmode.c b/sysdeps/i386/fpu/fegetmode.c new file mode 100644 index 0000000000..06d4d84768 --- /dev/null +++ b/sysdeps/i386/fpu/fegetmode.c @@ -0,0 +1,32 @@ +/* Store current floating-point control modes. i386 version. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> +#include <unistd.h> +#include <ldsodefs.h> +#include <dl-procinfo.h> + +int +fegetmode (femode_t *modep) +{ + _FPU_GETCW (modep->__control_word); + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + __asm__ ("stmxcsr %0" : "=m" (modep->__mxcsr)); + return 0; +} diff --git a/sysdeps/i386/fpu/fesetmode.c b/sysdeps/i386/fpu/fesetmode.c new file mode 100644 index 0000000000..cca5a1ad0c --- /dev/null +++ b/sysdeps/i386/fpu/fesetmode.c @@ -0,0 +1,54 @@ +/* Install given floating-point control modes. i386 version. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> +#include <unistd.h> +#include <ldsodefs.h> +#include <dl-procinfo.h> + +/* All exceptions, including the x86-specific "denormal operand" + exception. */ +#define FE_ALL_EXCEPT_X86 (FE_ALL_EXCEPT | __FE_DENORM) + +int +fesetmode (const femode_t *modep) +{ + fpu_control_t cw; + if (modep == FE_DFL_MODE) + cw = _FPU_DEFAULT; + else + cw = modep->__control_word; + _FPU_SETCW (cw); + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + { + unsigned int mxcsr; + __asm__ ("stmxcsr %0" : "=m" (mxcsr)); + /* Preserve SSE exception flags but restore other state in + MXCSR. */ + mxcsr &= FE_ALL_EXCEPT_X86; + if (modep == FE_DFL_MODE) + /* Default MXCSR state has all bits zero except for those + masking exceptions. */ + mxcsr |= FE_ALL_EXCEPT_X86 << 7; + else + mxcsr |= modep->__mxcsr & ~FE_ALL_EXCEPT_X86; + __asm__ ("ldmxcsr %0" : : "m" (mxcsr)); + } + return 0; +} diff --git a/sysdeps/ia64/bits/fenv.h b/sysdeps/ia64/bits/fenv.h index 9bb20de27b..5945380889 100644 --- a/sysdeps/ia64/bits/fenv.h +++ b/sysdeps/ia64/bits/fenv.h @@ -94,3 +94,11 @@ typedef unsigned long int fenv_t; s0, s2, and s3. */ # define FE_NONIEEE_ENV ((const fenv_t *) 0xc009a04d0270037fUL) #endif + +#if __GLIBC_USE (IEC_60559_BFP_EXT) +/* Type representing floating-point control modes. */ +typedef unsigned long int femode_t; + +/* Default floating-point control modes. */ +# define FE_DFL_MODE ((const femode_t *) 0xc009804c0270033fUL) +#endif diff --git a/sysdeps/m68k/fpu/bits/fenv.h b/sysdeps/m68k/fpu/bits/fenv.h index 2228861624..b8e52b290e 100644 --- a/sysdeps/m68k/fpu/bits/fenv.h +++ b/sysdeps/m68k/fpu/bits/fenv.h @@ -85,3 +85,11 @@ fenv_t; /* Floating-point environment where none of the exceptions are masked. */ # define FE_NOMASK_ENV ((const fenv_t *) -2) #endif + +#if __GLIBC_USE (IEC_60559_BFP_EXT) +/* Type representing floating-point control modes. */ +typedef unsigned int femode_t; + +/* Default floating-point control modes. */ +# define FE_DFL_MODE ((const femode_t *) -1L) +#endif diff --git a/sysdeps/microblaze/bits/fenv.h b/sysdeps/microblaze/bits/fenv.h index 3891f4a186..0d2ab2bc58 100644 --- a/sysdeps/microblaze/bits/fenv.h +++ b/sysdeps/microblaze/bits/fenv.h @@ -40,3 +40,11 @@ typedef unsigned int fenv_t; /* If the default argument is used we use this value. */ #define FE_DFL_ENV ((const fenv_t *) -1l) + +#if __GLIBC_USE (IEC_60559_BFP_EXT) +/* Type representing floating-point control modes. */ +typedef unsigned int femode_t; + +/* Default floating-point control modes. */ +# define FE_DFL_MODE ((const femode_t *) -1L) +#endif diff --git a/sysdeps/mips/bits/fenv.h b/sysdeps/mips/bits/fenv.h index f829bd3807..6341ee279e 100644 --- a/sysdeps/mips/bits/fenv.h +++ b/sysdeps/mips/bits/fenv.h @@ -83,3 +83,11 @@ fenv_t; /* Floating-point environment where none of the exception is masked. */ # define FE_NOMASK_ENV ((const fenv_t *) -2) #endif + +#if __GLIBC_USE (IEC_60559_BFP_EXT) +/* Type representing floating-point control modes. */ +typedef unsigned int femode_t; + +/* Default floating-point control modes. */ +# define FE_DFL_MODE ((const femode_t *) -1L) +#endif diff --git a/sysdeps/nacl/libm.abilist b/sysdeps/nacl/libm.abilist index 28897730fa..85ee684a1a 100644 --- a/sysdeps/nacl/libm.abilist +++ b/sysdeps/nacl/libm.abilist @@ -380,5 +380,7 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F diff --git a/sysdeps/nios2/bits/fenv.h b/sysdeps/nios2/bits/fenv.h index 9d046217c8..8ac3831ed9 100644 --- a/sysdeps/nios2/bits/fenv.h +++ b/sysdeps/nios2/bits/fenv.h @@ -42,3 +42,11 @@ typedef unsigned int fenv_t; /* If the default argument is used we use this value. */ #define FE_DFL_ENV ((const fenv_t *) -1) + +#if __GLIBC_USE (IEC_60559_BFP_EXT) +/* Type representing floating-point control modes. */ +typedef unsigned int femode_t; + +/* Default floating-point control modes. */ +# define FE_DFL_MODE ((const femode_t *) -1L) +#endif diff --git a/sysdeps/powerpc/Versions b/sysdeps/powerpc/Versions index b959ea49fe..95849668f2 100644 --- a/sysdeps/powerpc/Versions +++ b/sysdeps/powerpc/Versions @@ -3,6 +3,9 @@ libm { # symbols used in macros from sysdeps/powerpc/bits/fenv.h __fe_dfl_env; __fe_enabled_env; __fe_nonieee_env; __fe_nomask_env; } + GLIBC_2.25 { + __fe_dfl_mode; + } } libc { diff --git a/sysdeps/powerpc/bits/fenv.h b/sysdeps/powerpc/bits/fenv.h index d2a6d34a99..8d2bf3d163 100644 --- a/sysdeps/powerpc/bits/fenv.h +++ b/sysdeps/powerpc/bits/fenv.h @@ -169,3 +169,12 @@ extern const fenv_t __fe_nonieee_env; # define FE_MASK_ENV FE_DFL_ENV #endif + +#if __GLIBC_USE (IEC_60559_BFP_EXT) +/* Type representing floating-point control modes. */ +typedef double femode_t; + +/* Default floating-point control modes. */ +extern const femode_t __fe_dfl_mode; +# define FE_DFL_MODE (&__fe_dfl_mode) +#endif diff --git a/sysdeps/powerpc/fpu/fenv_const.c b/sysdeps/powerpc/fpu/fenv_const.c index b061daf578..93a4375430 100644 --- a/sysdeps/powerpc/fpu/fenv_const.c +++ b/sysdeps/powerpc/fpu/fenv_const.c @@ -23,6 +23,10 @@ const unsigned long long __fe_dfl_env __attribute__ ((aligned (8))) = 0xfff8000000000000ULL; +/* The same representation is used for femode_t. */ +extern const unsigned long long __fe_dfl_mode + __attribute__ ((aligned (8), alias ("__fe_dfl_env"))); + /* Floating-point environment where none of the exceptions are masked. */ const unsigned long long __fe_enabled_env __attribute__ ((aligned (8))) = 0xfff80000000000f8ULL; diff --git a/sysdeps/powerpc/nofpu/fenv_const.c b/sysdeps/powerpc/nofpu/fenv_const.c index ebf5c68fc5..ce1da3c197 100644 --- a/sysdeps/powerpc/nofpu/fenv_const.c +++ b/sysdeps/powerpc/nofpu/fenv_const.c @@ -25,6 +25,10 @@ const unsigned long long __fe_dfl_env __attribute__ ((aligned (8))) = 0x000000003e000000ULL; +/* The same representation is used for femode_t. */ +extern const unsigned long long __fe_dfl_mode + __attribute__ ((aligned (8), alias ("__fe_dfl_env"))); + /* Floating-point environment where none of the exceptions are masked. */ const unsigned long long __fe_enabled_env __attribute__ ((aligned (8))) = 0x0000000000000000ULL; diff --git a/sysdeps/powerpc/powerpc32/e500/nofpu/fenv_const.c b/sysdeps/powerpc/powerpc32/e500/nofpu/fenv_const.c index 11e24ca182..eab47c8c0f 100644 --- a/sysdeps/powerpc/powerpc32/e500/nofpu/fenv_const.c +++ b/sysdeps/powerpc/powerpc32/e500/nofpu/fenv_const.c @@ -28,6 +28,10 @@ const unsigned long long __fe_dfl_env __attribute__ ((aligned (8))) = 0x3cULL; +/* The same representation is used for femode_t. */ +extern const unsigned long long __fe_dfl_mode + __attribute__ ((aligned (8), alias ("__fe_dfl_env"))); + /* Floating-point environment where none of the exceptions are masked. */ const unsigned long long __fe_enabled_env __attribute__ ((aligned (8))) = (((unsigned long long) (PR_FP_EXC_DIV diff --git a/sysdeps/s390/fpu/bits/fenv.h b/sysdeps/s390/fpu/bits/fenv.h index 6de74b9939..d33f5d921d 100644 --- a/sysdeps/s390/fpu/bits/fenv.h +++ b/sysdeps/s390/fpu/bits/fenv.h @@ -90,3 +90,11 @@ typedef struct /* Floating-point environment where none of the exceptions are masked. */ # define FE_NOMASK_ENV ((const fenv_t *) -2) #endif + +#if __GLIBC_USE (IEC_60559_BFP_EXT) +/* Type representing floating-point control modes. */ +typedef unsigned int femode_t; + +/* Default floating-point control modes. */ +# define FE_DFL_MODE ((const femode_t *) -1L) +#endif diff --git a/sysdeps/sh/bits/fenv.h b/sysdeps/sh/bits/fenv.h index 254c50fb97..200b53899b 100644 --- a/sysdeps/sh/bits/fenv.h +++ b/sysdeps/sh/bits/fenv.h @@ -74,3 +74,11 @@ fenv_t; /* If the default argument is used we use this value. */ #define FE_DFL_ENV ((const fenv_t *) -1) + +#if __GLIBC_USE (IEC_60559_BFP_EXT) +/* Type representing floating-point control modes. */ +typedef unsigned int femode_t; + +/* Default floating-point control modes. */ +# define FE_DFL_MODE ((const femode_t *) -1L) +#endif diff --git a/sysdeps/sparc/fpu/bits/fenv.h b/sysdeps/sparc/fpu/bits/fenv.h index 29328f714f..37c82ff5eb 100644 --- a/sysdeps/sparc/fpu/bits/fenv.h +++ b/sysdeps/sparc/fpu/bits/fenv.h @@ -91,3 +91,11 @@ typedef unsigned long int fenv_t; # define __fenv_stfsr(X) __asm__ __volatile__ ("st %%fsr,%0" : "=m" (X)) # define __fenv_ldfsr(X) __asm__ __volatile__ ("ld %0,%%fsr" : : "m" (X)) #endif + +#if __GLIBC_USE (IEC_60559_BFP_EXT) +/* Type representing floating-point control modes. */ +typedef unsigned long int femode_t; + +/* Default floating-point control modes. */ +# define FE_DFL_MODE ((const femode_t *) -1L) +#endif diff --git a/sysdeps/tile/bits/fenv.h b/sysdeps/tile/bits/fenv.h index a87a39fc28..eee9e011cc 100644 --- a/sysdeps/tile/bits/fenv.h +++ b/sysdeps/tile/bits/fenv.h @@ -43,3 +43,11 @@ typedef unsigned int fenv_t; /* If the default argument is used we use this value. */ #define FE_DFL_ENV ((const fenv_t *) -1l) + +#if __GLIBC_USE (IEC_60559_BFP_EXT) +/* Type representing floating-point control modes. */ +typedef unsigned int femode_t; + +/* Default floating-point control modes. */ +# define FE_DFL_MODE ((const femode_t *) -1L) +#endif diff --git a/sysdeps/unix/sysv/linux/aarch64/libm.abilist b/sysdeps/unix/sysv/linux/aarch64/libm.abilist index 1f475cd5c1..aee63a105c 100644 --- a/sysdeps/unix/sysv/linux/aarch64/libm.abilist +++ b/sysdeps/unix/sysv/linux/aarch64/libm.abilist @@ -411,5 +411,7 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F diff --git a/sysdeps/unix/sysv/linux/alpha/libm.abilist b/sysdeps/unix/sysv/linux/alpha/libm.abilist index 11b76e9a10..339b896ac7 100644 --- a/sysdeps/unix/sysv/linux/alpha/libm.abilist +++ b/sysdeps/unix/sysv/linux/alpha/libm.abilist @@ -421,7 +421,9 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F GLIBC_2.3.4 GLIBC_2.3.4 A GLIBC_2.3.4 __c1_cabsf F diff --git a/sysdeps/unix/sysv/linux/arm/libm.abilist b/sysdeps/unix/sysv/linux/arm/libm.abilist index 1fc1804bd5..f7b824413b 100644 --- a/sysdeps/unix/sysv/linux/arm/libm.abilist +++ b/sysdeps/unix/sysv/linux/arm/libm.abilist @@ -69,7 +69,9 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F GLIBC_2.4 GLIBC_2.4 A GLIBC_2.4 _LIB_VERSION D 0x4 diff --git a/sysdeps/unix/sysv/linux/hppa/libm.abilist b/sysdeps/unix/sysv/linux/hppa/libm.abilist index ed734881dd..576b514a53 100644 --- a/sysdeps/unix/sysv/linux/hppa/libm.abilist +++ b/sysdeps/unix/sysv/linux/hppa/libm.abilist @@ -381,7 +381,9 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F GLIBC_2.4 GLIBC_2.4 A GLIBC_2.4 exp2l F diff --git a/sysdeps/unix/sysv/linux/i386/libm.abilist b/sysdeps/unix/sysv/linux/i386/libm.abilist index 3a6dcaf064..63b8da9985 100644 --- a/sysdeps/unix/sysv/linux/i386/libm.abilist +++ b/sysdeps/unix/sysv/linux/i386/libm.abilist @@ -423,6 +423,8 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F GLIBC_2.4 GLIBC_2.4 A diff --git a/sysdeps/unix/sysv/linux/ia64/libm.abilist b/sysdeps/unix/sysv/linux/ia64/libm.abilist index ec9916b52e..611a84ff57 100644 --- a/sysdeps/unix/sysv/linux/ia64/libm.abilist +++ b/sysdeps/unix/sysv/linux/ia64/libm.abilist @@ -352,6 +352,8 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F GLIBC_2.4 GLIBC_2.4 A diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libm.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libm.abilist index 1fc1804bd5..f7b824413b 100644 --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libm.abilist +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libm.abilist @@ -69,7 +69,9 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F GLIBC_2.4 GLIBC_2.4 A GLIBC_2.4 _LIB_VERSION D 0x4 diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libm.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libm.abilist index 32931f1677..77f9c7bed7 100644 --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libm.abilist +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libm.abilist @@ -421,6 +421,8 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F GLIBC_2.4 GLIBC_2.4 A diff --git a/sysdeps/unix/sysv/linux/microblaze/libm.abilist b/sysdeps/unix/sysv/linux/microblaze/libm.abilist index cab693a4e4..c59437fe73 100644 --- a/sysdeps/unix/sysv/linux/microblaze/libm.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/libm.abilist @@ -380,5 +380,7 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F diff --git a/sysdeps/unix/sysv/linux/mips/mips32/libm.abilist b/sysdeps/unix/sysv/linux/mips/mips32/libm.abilist index 20a80ccbf2..31d6f9eb70 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/libm.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/libm.abilist @@ -382,7 +382,9 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F GLIBC_2.4 GLIBC_2.4 A GLIBC_2.4 exp2l F diff --git a/sysdeps/unix/sysv/linux/mips/mips64/libm.abilist b/sysdeps/unix/sysv/linux/mips/mips64/libm.abilist index 02379f78bf..83e031125b 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/libm.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/libm.abilist @@ -413,6 +413,8 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F GLIBC_2.4 GLIBC_2.4 A diff --git a/sysdeps/unix/sysv/linux/nios2/libm.abilist b/sysdeps/unix/sysv/linux/nios2/libm.abilist index b4b377ba19..151574d670 100644 --- a/sysdeps/unix/sysv/linux/nios2/libm.abilist +++ b/sysdeps/unix/sysv/linux/nios2/libm.abilist @@ -380,5 +380,7 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libm.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libm.abilist index 7eea14aded..456f47e912 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libm.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libm.abilist @@ -422,7 +422,10 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 __fe_dfl_mode D 0x8 +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F GLIBC_2.4 GLIBC_2.4 A GLIBC_2.4 __clog10l F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libm.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libm.abilist index 5eb2e9bb40..b2e4a73fd6 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libm.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libm.abilist @@ -421,7 +421,10 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 __fe_dfl_mode D 0x8 +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F GLIBC_2.4 GLIBC_2.4 A GLIBC_2.4 __clog10l F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libm-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libm-le.abilist index 36b8e77d47..907d8b7936 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libm-le.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libm-le.abilist @@ -416,5 +416,8 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 __fe_dfl_mode D 0x8 +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libm.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libm.abilist index 2efd4ebb33..307423dc80 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libm.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libm.abilist @@ -97,7 +97,10 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 __fe_dfl_mode D 0x8 +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 _LIB_VERSION D 0x4 diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libm.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libm.abilist index 62f75baa36..377cea952a 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-32/libm.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libm.abilist @@ -411,7 +411,9 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F GLIBC_2.4 GLIBC_2.4 A GLIBC_2.4 __clog10l F diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libm.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libm.abilist index c41344a9ff..dafbff15a6 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-64/libm.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libm.abilist @@ -409,7 +409,9 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F GLIBC_2.4 GLIBC_2.4 A GLIBC_2.4 __clog10l F diff --git a/sysdeps/unix/sysv/linux/sh/libm.abilist b/sysdeps/unix/sysv/linux/sh/libm.abilist index 3baecfb400..a38baceb8f 100644 --- a/sysdeps/unix/sysv/linux/sh/libm.abilist +++ b/sysdeps/unix/sysv/linux/sh/libm.abilist @@ -381,7 +381,9 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F GLIBC_2.4 GLIBC_2.4 A GLIBC_2.4 exp2l F diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libm.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libm.abilist index dd5390c313..27166beb55 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libm.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libm.abilist @@ -414,7 +414,9 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F GLIBC_2.4 GLIBC_2.4 A GLIBC_2.4 __clog10l F diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libm.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libm.abilist index 394c29b9b5..46f7973465 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libm.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libm.abilist @@ -412,6 +412,8 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F GLIBC_2.4 GLIBC_2.4 A diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libm.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libm.abilist index d66c886ca5..ec6f0b3600 100644 --- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libm.abilist +++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libm.abilist @@ -381,5 +381,7 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libm.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libm.abilist index d66c886ca5..ec6f0b3600 100644 --- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libm.abilist +++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libm.abilist @@ -381,5 +381,7 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libm.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libm.abilist index d66c886ca5..ec6f0b3600 100644 --- a/sysdeps/unix/sysv/linux/tile/tilepro/libm.abilist +++ b/sysdeps/unix/sysv/linux/tile/tilepro/libm.abilist @@ -381,5 +381,7 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libm.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libm.abilist index dd79dc4626..65e5baed84 100644 --- a/sysdeps/unix/sysv/linux/x86_64/64/libm.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/64/libm.abilist @@ -412,6 +412,8 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F GLIBC_2.4 GLIBC_2.4 A diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libm.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libm.abilist index 45abb4fa71..ff520cb084 100644 --- a/sysdeps/unix/sysv/linux/x86_64/x32/libm.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libm.abilist @@ -411,5 +411,7 @@ GLIBC_2.24 nextup F GLIBC_2.24 nextupf F GLIBC_2.24 nextupl F GLIBC_2.25 GLIBC_2.25 A +GLIBC_2.25 fegetmode F GLIBC_2.25 fesetexcept F +GLIBC_2.25 fesetmode F GLIBC_2.25 fetestexceptflag F diff --git a/sysdeps/x86/fpu/bits/fenv.h b/sysdeps/x86/fpu/bits/fenv.h index 8c8503bd7e..688407281c 100644 --- a/sysdeps/x86/fpu/bits/fenv.h +++ b/sysdeps/x86/fpu/bits/fenv.h @@ -101,6 +101,20 @@ fenv_t; # define FE_NOMASK_ENV ((const fenv_t *) -2) #endif +#if __GLIBC_USE (IEC_60559_BFP_EXT) +/* Type representing floating-point control modes. */ +typedef struct + { + unsigned short int __control_word; + unsigned short int __glibc_reserved; + unsigned int __mxcsr; + } +femode_t; + +/* Default floating-point control modes. */ +# define FE_DFL_MODE ((const femode_t *) -1L) +#endif + #ifdef __USE_EXTERN_INLINES __BEGIN_DECLS diff --git a/sysdeps/x86_64/fpu/fegetmode.c b/sysdeps/x86_64/fpu/fegetmode.c new file mode 100644 index 0000000000..f4a179d36b --- /dev/null +++ b/sysdeps/x86_64/fpu/fegetmode.c @@ -0,0 +1,28 @@ +/* Store current floating-point control modes. x86_64 version. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetmode (femode_t *modep) +{ + _FPU_GETCW (modep->__control_word); + __asm__ ("stmxcsr %0" : "=m" (modep->__mxcsr)); + return 0; +} diff --git a/sysdeps/x86_64/fpu/fesetmode.c b/sysdeps/x86_64/fpu/fesetmode.c new file mode 100644 index 0000000000..19173f91cb --- /dev/null +++ b/sysdeps/x86_64/fpu/fesetmode.c @@ -0,0 +1,50 @@ +/* Install given floating-point control modes. x86_64 version. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +/* All exceptions, including the x86-specific "denormal operand" + exception. */ +#define FE_ALL_EXCEPT_X86 (FE_ALL_EXCEPT | __FE_DENORM) + +int +fesetmode (const femode_t *modep) +{ + fpu_control_t cw; + unsigned int mxcsr; + __asm__ ("stmxcsr %0" : "=m" (mxcsr)); + /* Preserve SSE exception flags but restore other state in + MXCSR. */ + mxcsr &= FE_ALL_EXCEPT_X86; + if (modep == FE_DFL_MODE) + { + cw = _FPU_DEFAULT; + /* Default MXCSR state has all bits zero except for those + masking exceptions. */ + mxcsr |= FE_ALL_EXCEPT_X86 << 7; + } + else + { + cw = modep->__control_word; + mxcsr |= modep->__mxcsr & ~FE_ALL_EXCEPT_X86; + } + _FPU_SETCW (cw); + __asm__ ("ldmxcsr %0" : : "m" (mxcsr)); + return 0; +} |