From 9c82dee623c1dca092d050d6e2289e9e7e07a687 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Mon, 30 Oct 2023 16:26:46 +0100 Subject: [PATCH 1/8] 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. --- ChangeLog | 6 ++++++ lib/fenv-except-state-set.c | 27 ++++++++++++--------------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index e0bf89a9e2..0476828c50 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2023-10-30 Bruno Haible + + 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 fenv-exceptions-state-c23: Add tests. diff --git a/lib/fenv-except-state-set.c b/lib/fenv-except-state-set.c index 6ba4d63a7d..2035f61e27 100644 --- a/lib/fenv-except-state-set.c +++ b/lib/fenv-except-state-set.c @@ -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 -- 2.34.1