summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog113
-rw-r--r--NEWS5
-rw-r--r--bits/fenv.h8
-rw-r--r--manual/arith.texi33
-rw-r--r--math/Makefile6
-rw-r--r--math/Versions2
-rw-r--r--math/fegetmode.c27
-rw-r--r--math/fenv.h18
-rw-r--r--math/fesetmode.c27
-rw-r--r--math/test-femode-traps.c149
-rw-r--r--math/test-femode.c231
-rw-r--r--sysdeps/aarch64/bits/fenv.h8
-rw-r--r--sysdeps/alpha/fpu/bits/fenv.h8
-rw-r--r--sysdeps/arm/bits/fenv.h8
-rw-r--r--sysdeps/hppa/fpu/bits/fenv.h8
-rw-r--r--sysdeps/i386/fpu/fegetmode.c32
-rw-r--r--sysdeps/i386/fpu/fesetmode.c54
-rw-r--r--sysdeps/ia64/bits/fenv.h8
-rw-r--r--sysdeps/m68k/fpu/bits/fenv.h8
-rw-r--r--sysdeps/microblaze/bits/fenv.h8
-rw-r--r--sysdeps/mips/bits/fenv.h8
-rw-r--r--sysdeps/nacl/libm.abilist2
-rw-r--r--sysdeps/nios2/bits/fenv.h8
-rw-r--r--sysdeps/powerpc/Versions3
-rw-r--r--sysdeps/powerpc/bits/fenv.h9
-rw-r--r--sysdeps/powerpc/fpu/fenv_const.c4
-rw-r--r--sysdeps/powerpc/nofpu/fenv_const.c4
-rw-r--r--sysdeps/powerpc/powerpc32/e500/nofpu/fenv_const.c4
-rw-r--r--sysdeps/s390/fpu/bits/fenv.h8
-rw-r--r--sysdeps/sh/bits/fenv.h8
-rw-r--r--sysdeps/sparc/fpu/bits/fenv.h8
-rw-r--r--sysdeps/tile/bits/fenv.h8
-rw-r--r--sysdeps/unix/sysv/linux/aarch64/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/alpha/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/arm/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/hppa/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/i386/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/ia64/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/m68k/coldfire/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/m68k/m680x0/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/microblaze/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips32/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips64/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/nios2/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libm.abilist3
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libm.abilist3
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/libm-le.abilist3
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/libm.abilist3
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/sh/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc32/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc64/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/tile/tilepro/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/64/libm.abilist2
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/x32/libm.abilist2
-rw-r--r--sysdeps/x86/fpu/bits/fenv.h14
-rw-r--r--sysdeps/x86_64/fpu/fegetmode.c28
-rw-r--r--sysdeps/x86_64/fpu/fesetmode.c50
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;
+}