]> Savannah Git Hosting - gnulib.git/commitdiff
fenv-exceptions-state-c99: Fix test failures with Oracle cc 12.6.
authorBruno Haible <bruno@clisp.org>
Fri, 29 Mar 2024 02:50:44 +0000 (03:50 +0100)
committerBruno Haible <bruno@clisp.org>
Mon, 8 Apr 2024 10:23:13 +0000 (12:23 +0200)
* lib/fenv-except-state-set.c (mask387cw): New function.
(fesetexceptflag): Use it on glibc.

ChangeLog
lib/fenv-except-state-set.c

index d0c0368861b5fe521ae6edabff958f7094454da3..e3db00a92622a1f842eb85ab27ed2527ace81d94 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2024-03-28  Bruno Haible  <bruno@clisp.org>
+
+       fenv-exceptions-state-c99: Fix test failures with Oracle cc 12.6.
+       * lib/fenv-except-state-set.c (mask387cw): New function.
+       (fesetexceptflag): Use it on glibc.
+
 2024-03-28  Bruno Haible  <bruno@clisp.org>
 
        mcel tests: Fix test failure with Oracle cc 12.6.
index 8ca6818cbe7ddfd5411fef56ddb16027add17643..cafad201e34e41c5e3aa755152b45b4d5e0aee18 100644 (file)
@@ -441,15 +441,16 @@ fesetexceptflag (fexcept_t const *saved_flags, int exceptions)
 /* The compiler does not support __asm__ statements or equivalent
    intrinsics.  */
 
-# if defined __sun && ((defined __x86_64__ || defined _M_X64) || (defined __i386 || defined _M_IX86)) && defined __SUNPRO_C
-/* Solaris/i386, Solaris/x86_64.  */
+# if (defined __sun || __GLIBC__ >= 2) && ((defined __x86_64__ || defined _M_X64) || (defined __i386 || defined _M_IX86)) && defined __SUNPRO_C
+/* Solaris/i386, Solaris/x86_64, glibc/i386, glibc/x86_64, with SunPRO C.  */
 
-/* On these platforms, fpsetsticky cannot be used here, because it may generate
-   traps (since fpsetsticky calls _putsw, which modifies the control word of the
-   387 unit).  Instead, we need to modify only the flags in the SSE unit.  */
+/* On these Solaris platforms, fpsetsticky cannot be used here, because it may
+   generate traps (since fpsetsticky calls _putsw, which modifies the control
+   word of the 387 unit).  Instead, we need to modify only the flags in the SSE
+   unit.  */
 
-/* Accessors for the mxcsr register.  Fortunately, the Solaris cc supports a
-   poor form of 'asm'.  */
+/* Accessors for the mxcsr register.  Fortunately, the SunPRO C compiler
+   supports a poor form of 'asm'.  */
 
 static void
 getssecw (unsigned int *mxcsr_p)
@@ -477,6 +478,26 @@ setssecw (unsigned int const *mxcsr_p)
 #  endif
 }
 
+#  if __GLIBC__ >= 2
+/* Clears flags in the 387 unit.  */
+static void
+mask387cw (unsigned short mask)
+{
+#   if defined __x86_64__ || defined _M_X64
+  asm ("fnstenv -32(%rsp)");
+  asm ("andw %di,-28(%rsp)");
+  asm ("fldenv -32(%rsp)");
+#   else
+  /* The compiler generates a stack frame.  Therefore the first argument is in
+     8(%ebp), not in 4(%esp).  */
+  asm ("movl 8(%ebp),%eax");
+  asm ("fnstenv -32(%esp)");
+  asm ("andw %ax,-28(%esp)");
+  asm ("fldenv -32(%esp)");
+#   endif
+}
+#  endif
+
 int
 fesetexceptflag (fexcept_t const *saved_flags, int exceptions)
 {
@@ -490,6 +511,12 @@ fesetexceptflag (fexcept_t const *saved_flags, int exceptions)
   if (mxcsr != orig_mxcsr)
     setssecw (&mxcsr);
 
+#  if __GLIBC__ >= 2
+  /* Modify the flags in the 387 unit, but only by clearing bits, not by
+     setting bits.  */
+  mask387cw (~ (exceptions & ~desired_flags));
+#  endif
+
   return 0;
 }