i686: Do not raise exception traps on fesetexcept (BZ 30989)
[glibc.git] / sysdeps / i386 / fpu / fesetexcept.c
blob58f577d93d64906455fc254bdbbfc45377bb17cc
1 /* Set given exception flags. i386 version.
2 Copyright (C) 2016-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 #include <fenv.h>
20 #include <ldsodefs.h>
22 int
23 fesetexcept (int excepts)
25 /* The flags can be set in the 387 unit or in the SSE unit. To set a flag,
26 it is sufficient to do it in the SSE unit, because that is guaranteed to
27 not trap. However, on i386 CPUs that have only a 387 unit, set the flags
28 in the 387, as long as this cannot trap. */
30 excepts &= FE_ALL_EXCEPT;
32 if (CPU_FEATURE_USABLE (SSE))
34 /* Get the control word of the SSE unit. */
35 unsigned int mxcsr;
36 __asm__ ("stmxcsr %0" : "=m" (*&mxcsr));
38 /* Set relevant flags. */
39 mxcsr |= excepts;
41 /* Put the new data in effect. */
42 __asm__ ("ldmxcsr %0" : : "m" (*&mxcsr));
44 else
46 fenv_t temp;
48 /* Note: fnstenv masks all floating-point exceptions until the fldenv
49 or fldcw below. */
50 __asm__ ("fnstenv %0" : "=m" (*&temp));
52 /* Set relevant flags. */
53 temp.__status_word |= excepts;
55 if ((~temp.__control_word) & excepts)
57 /* Setting the exception flags may trigger a trap (at the next
58 floating-point instruction, but that does not matter).
59 ISO C23 (7.6.4.4) does not allow it. */
60 __asm__ volatile ("fldcw %0" : : "m" (*&temp.__control_word));
61 return -1;
64 /* Store the new status word (along with the rest of the environment). */
65 __asm__ ("fldenv %0" : : "m" (*&temp));
68 return 0;