]> Savannah Git Hosting - gnulib.git/commitdiff
fenv-exceptions-state-c99: Fix the x86_64 and i386 case.
authorBruno Haible <bruno@clisp.org>
Mon, 30 Oct 2023 15:26:46 +0000 (16:26 +0100)
committerBruno Haible <bruno@clisp.org>
Mon, 30 Oct 2023 16:00:54 +0000 (17:00 +0100)
* lib/fenv-except-state-set.c (fesetexceptflag): Make sure to restore
the exception trap bits in all cases.

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

index e0bf89a9e2cdf483d40c5c650ea9b6d06402fef6..0476828c50fc864fbd9106d870b551b55a9eff56 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2023-10-30  Bruno Haible  <bruno@clisp.org>
+
+       fenv-exceptions-state-c99: Fix the x86_64 and i386 case.
+       * lib/fenv-except-state-set.c (fesetexceptflag): Make sure to restore
+       the exception trap bits in all cases.
+
 2023-10-30  Bruno Haible  <bruno@clisp.org>
 
        fenv-exceptions-state-c23: Add tests.
index 6ba4d63a7d12e601996e902f00b3c93d63b32cc8..2035f61e2714126e432c0c1f29450f18f58d81f1 100644 (file)
@@ -72,33 +72,30 @@ fesetexceptflag (fexcept_t const *saved_flags, int exceptions)
       /* Modify the flags in the 387 unit, but only by clearing bits, not by
          setting bits.  */
       x86_387_fenv_t env;
-      unsigned short orig_status_word;
       __asm__ __volatile__ ("fnstenv %0" : "=m" (*&env));
-      orig_status_word = env.__status_word;
+      /* Note: fnstenv masks all floating-point exceptions until the fldenv
+         below.  */
       env.__status_word &= ~ (exceptions & ~desired_flags);
-      if (env.__status_word != orig_status_word)
-        __asm__ __volatile__ ("fldenv %0" : : "m" (*&env));
+      __asm__ __volatile__ ("fldenv %0" : : "m" (*&env));
     }
 #   if !(defined __x86_64__ || defined _M_X64)
   else
     {
       /* Modify the flags in the 387 unit.  */
       x86_387_fenv_t env;
-      unsigned short orig_status_word;
       __asm__ __volatile__ ("fnstenv %0" : "=m" (*&env));
-      orig_status_word = env.__status_word;
+      /* Note: fnstenv masks all floating-point exceptions until the fldenv
+         or fldcw below.  */
       env.__status_word ^= ((env.__status_word ^ desired_flags) & exceptions);
-      if (env.__status_word != orig_status_word)
+      if ((~env.__control_word) & env.__status_word & exceptions)
         {
-          if ((~env.__control_word) & env.__status_word & exceptions)
-            {
-              /* Setting the exception flags may trigger a trap (at the next
-                 floating-point instruction, but that does not matter).
-                 ISO C 23 § 7.6.4.5 does not allow it.  */
-              return -1;
-            }
-          __asm__ __volatile__ ("fldenv %0" : : "m" (*&env));
+          /* Setting the exception flags may trigger a trap (at the next
+             floating-point instruction, but that does not matter).
+             ISO C 23 § 7.6.4.5 does not allow it.  */
+          __asm__ __volatile__ ("fldcw %0" : : "m" (*&env.__control_word));
+          return -1;
         }
+      __asm__ __volatile__ ("fldenv %0" : : "m" (*&env));
     }
 #   endif
 #  endif