1 /* Functions for turning floating-point exceptions into traps (signals).
2 Copyright (C) 1997-2024 Free Software Foundation, Inc.
4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
9 This file is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Based on glibc/sysdeps/<cpu>/{feenablxcpt.c,fedisblxcpt.c,fegetexcept.c}
18 together with glibc/sysdeps/<cpu>/{fpu_control.h,fenv_private.h,fenv_libc.h}. */
25 #include "fenv-private.h"
27 #if defined __GNUC__ || defined __clang__ || defined _MSC_VER
29 # if (defined __x86_64__ || defined _M_X64) || (defined __i386 || defined _M_IX86)
32 feenableexcept (int exceptions
)
34 exceptions
&= FE_ALL_EXCEPT
;
38 exceptions
= exceptions_to_x86hardware (exceptions
);
40 /* Enable the traps only in the SSE unit. */
41 unsigned int mxcsr
, orig_mxcsr
;
42 _FPU_GETSSECW (orig_mxcsr
);
43 mxcsr
= orig_mxcsr
& ~(exceptions
<< 7);
44 if (mxcsr
!= orig_mxcsr
)
45 _FPU_SETSSECW (mxcsr
);
47 unsigned int trapbits
= 0x3f & ~(orig_mxcsr
>> 7);
48 return x86hardware_to_exceptions (trapbits
);
52 /* Enable the traps in the 387 unit. */
53 unsigned short fctrl
, orig_fctrl
;
54 _FPU_GETCW (orig_fctrl
);
55 fctrl
= orig_fctrl
& ~exceptions
;
56 if (fctrl
!= orig_fctrl
)
61 /* Enable the traps in the SSE unit as well. */
62 unsigned int mxcsr
, orig_mxcsr
;
63 _FPU_GETSSECW (orig_mxcsr
);
64 mxcsr
= orig_mxcsr
& ~(exceptions
<< 7);
65 if (mxcsr
!= orig_mxcsr
)
66 _FPU_SETSSECW (mxcsr
);
69 return FE_ALL_EXCEPT
& ~orig_fctrl
;
75 fedisableexcept (int exceptions
)
77 exceptions
&= FE_ALL_EXCEPT
;
81 exceptions
= exceptions_to_x86hardware (exceptions
);
83 /* Disable the traps only in the SSE unit. */
84 unsigned int mxcsr
, orig_mxcsr
;
85 _FPU_GETSSECW (orig_mxcsr
);
86 mxcsr
= orig_mxcsr
| (exceptions
<< 7);
87 if (mxcsr
!= orig_mxcsr
)
88 _FPU_SETSSECW (mxcsr
);
90 unsigned int trapbits
= 0x3f & ~(orig_mxcsr
>> 7);
91 return x86hardware_to_exceptions (trapbits
);
95 /* Disable the traps in the 387 unit. */
96 unsigned short fctrl
, orig_fctrl
;
97 _FPU_GETCW (orig_fctrl
);
98 fctrl
= orig_fctrl
| exceptions
;
99 if (fctrl
!= orig_fctrl
)
104 /* Disable the traps in the SSE unit as well. */
105 unsigned int mxcsr
, orig_mxcsr
;
106 _FPU_GETSSECW (orig_mxcsr
);
107 mxcsr
= orig_mxcsr
| (exceptions
<< 7);
108 if (mxcsr
!= orig_mxcsr
)
109 _FPU_SETSSECW (mxcsr
);
112 return FE_ALL_EXCEPT
& ~orig_fctrl
;
120 # if defined _MSC_VER
121 /* Look at the trap bits in the SSE unit. */
123 _FPU_GETSSECW (mxcsr
);
124 unsigned int trapbits
= 0x3f & ~(mxcsr
>> 7);
125 return x86hardware_to_exceptions (trapbits
);
127 /* Look at the trap bits in the 387 unit. */
128 unsigned short fctrl
;
130 return FE_ALL_EXCEPT
& ~fctrl
;
134 # elif defined __aarch64__ /* arm64 */
137 feenableexcept (int exceptions
)
139 exceptions
&= FE_ALL_EXCEPT
;
141 unsigned long fpcr
, orig_fpcr
;
142 _FPU_GETCW (orig_fpcr
);
143 fpcr
= orig_fpcr
| (exceptions
<< 8);
144 if (fpcr
!= orig_fpcr
)
147 /* Test whether fpcr was actually changed as desired. */
148 unsigned long new_fpcr
;
149 _FPU_GETCW (new_fpcr
);
150 if (new_fpcr
!= fpcr
)
154 return FE_ALL_EXCEPT
& (orig_fpcr
>> 8);
158 fedisableexcept (int exceptions
)
160 exceptions
&= FE_ALL_EXCEPT
;
162 unsigned long fpcr
, orig_fpcr
;
163 _FPU_GETCW (orig_fpcr
);
164 fpcr
= orig_fpcr
& ~(exceptions
<< 8);
165 if (fpcr
!= orig_fpcr
)
168 /* Testing whether fpcr was actually changed as desired is not needed
169 here, since we only cleared some bits. */
172 return FE_ALL_EXCEPT
& (orig_fpcr
>> 8);
180 return FE_ALL_EXCEPT
& (fpcr
>> 8);
183 # elif defined __arm__
186 feenableexcept (int exceptions
)
188 exceptions
&= FE_ALL_EXCEPT
;
195 unsigned int fpscr
, orig_fpscr
;
196 _FPU_GETCW (orig_fpscr
);
197 fpscr
= orig_fpscr
| (exceptions
<< 8);
198 if (fpscr
!= orig_fpscr
)
201 /* Test whether fpscr was actually changed as desired. */
202 unsigned int new_fpscr
;
203 _FPU_GETCW (new_fpscr
);
204 if (new_fpscr
!= fpscr
)
208 return FE_ALL_EXCEPT
& (orig_fpscr
>> 8);
213 fedisableexcept (int exceptions
)
215 exceptions
&= FE_ALL_EXCEPT
;
220 unsigned int fpscr
, orig_fpscr
;
221 _FPU_GETCW (orig_fpscr
);
222 fpscr
= orig_fpscr
& ~(exceptions
<< 8);
223 if (fpscr
!= orig_fpscr
)
226 /* Testing whether fpscr was actually changed as desired is not needed
227 here, since we only cleared some bits. */
230 return FE_ALL_EXCEPT
& (orig_fpscr
>> 8);
242 return FE_ALL_EXCEPT
& (fpscr
>> 8);
246 # elif defined __alpha
249 feenableexcept (int exceptions
)
251 exceptions
&= FE_ALL_EXCEPT
;
253 unsigned long swcr
, orig_swcr
;
254 orig_swcr
= __ieee_get_fp_control ();
255 swcr
= orig_swcr
| ((unsigned long) exceptions
>> 16);
256 if (swcr
!= orig_swcr
)
257 __ieee_set_fp_control (swcr
);
259 return FE_ALL_EXCEPT
& (orig_swcr
<< 16);
263 fedisableexcept (int exceptions
)
265 exceptions
&= FE_ALL_EXCEPT
;
267 unsigned long swcr
, orig_swcr
;
268 orig_swcr
= __ieee_get_fp_control ();
269 swcr
= orig_swcr
& ~((unsigned long) exceptions
>> 16);
270 if (swcr
!= orig_swcr
)
271 __ieee_set_fp_control (swcr
);
273 return FE_ALL_EXCEPT
& (orig_swcr
<< 16);
279 unsigned long swcr
= __ieee_get_fp_control ();
280 return FE_ALL_EXCEPT
& (swcr
<< 16);
283 # elif defined __hppa
286 feenableexcept (int exceptions
)
288 exceptions
&= FE_ALL_EXCEPT
;
290 union { unsigned long long fpreg
; unsigned int halfreg
[2]; } s
;
291 /* Get the current status word. */
292 __asm__
__volatile__ ("fstd %%fr0,0(%1)" : "=m" (s
.fpreg
) : "r" (&s
.fpreg
) : "%r0");
293 unsigned int old_halfreg0
= s
.halfreg
[0];
294 /* Set all the relevant bits. */
295 s
.halfreg
[0] |= (unsigned int) exceptions
;
296 if (s
.halfreg
[0] != old_halfreg0
)
298 /* Store the new status word. */
299 __asm__
__volatile__ ("fldd 0(%0),%%fr0" : : "r" (&s
.fpreg
), "m" (s
.fpreg
) : "%r0");
302 return FE_ALL_EXCEPT
& old_halfreg0
;
306 fedisableexcept (int exceptions
)
308 exceptions
&= FE_ALL_EXCEPT
;
310 union { unsigned long long fpreg
; unsigned int halfreg
[2]; } s
;
311 /* Get the current status word. */
312 __asm__
__volatile__ ("fstd %%fr0,0(%1)" : "=m" (s
.fpreg
) : "r" (&s
.fpreg
) : "%r0");
313 unsigned int old_halfreg0
= s
.halfreg
[0];
314 /* Clear all the relevant bits. */
315 s
.halfreg
[0] &= ~ (unsigned int) exceptions
;
316 if (s
.halfreg
[0] != old_halfreg0
)
318 /* Store the new status word. */
319 __asm__
__volatile__ ("fldd 0(%0),%%fr0" : : "r" (&s
.fpreg
), "m" (s
.fpreg
) : "%r0");
322 return FE_ALL_EXCEPT
& old_halfreg0
;
328 union { unsigned long long fpreg
; unsigned int halfreg
[2]; } s
;
329 /* Get the current status word. */
330 __asm__
__volatile__ ("fstd %%fr0,0(%1)" : "=m" (s
.fpreg
) : "r" (&s
.fpreg
) : "%r0");
332 return FE_ALL_EXCEPT
& s
.halfreg
[0];
335 # elif defined __ia64__
338 feenableexcept (int exceptions
)
340 exceptions
&= FE_ALL_EXCEPT
;
342 unsigned long fpsr
, orig_fpsr
;
343 _FPU_GETCW (orig_fpsr
);
344 fpsr
= orig_fpsr
& ~ (unsigned long) exceptions
;
345 if (fpsr
!= orig_fpsr
)
348 return FE_ALL_EXCEPT
& ~orig_fpsr
;
352 fedisableexcept (int exceptions
)
354 exceptions
&= FE_ALL_EXCEPT
;
356 unsigned long fpsr
, orig_fpsr
;
357 _FPU_GETCW (orig_fpsr
);
358 fpsr
= orig_fpsr
| (unsigned long) exceptions
;
359 if (fpsr
!= orig_fpsr
)
362 return FE_ALL_EXCEPT
& ~orig_fpsr
;
370 return FE_ALL_EXCEPT
& ~fpsr
;
373 # elif defined __m68k__
376 feenableexcept (int exceptions
)
378 exceptions
&= FE_ALL_EXCEPT
;
380 unsigned int fpcr
, orig_fpcr
;
381 _FPU_GETCW (orig_fpcr
);
382 fpcr
= orig_fpcr
| ((exceptions
<< 6) | (exceptions
& FE_INVALID
? 0xc000 : 0));
383 if (fpcr
!= orig_fpcr
)
386 return FE_ALL_EXCEPT
& (orig_fpcr
>> 6);
390 fedisableexcept (int exceptions
)
392 exceptions
&= FE_ALL_EXCEPT
;
394 unsigned int fpcr
, orig_fpcr
;
395 _FPU_GETCW (orig_fpcr
);
396 fpcr
= orig_fpcr
& ~ ((exceptions
<< 6) | (exceptions
& FE_INVALID
? 0xc000 : 0));
397 if (fpcr
!= orig_fpcr
)
400 return FE_ALL_EXCEPT
& (orig_fpcr
>> 6);
408 return FE_ALL_EXCEPT
& (fpcr
>> 6);
411 # elif defined __mips__
414 feenableexcept (int exceptions
)
416 exceptions
&= FE_ALL_EXCEPT
;
418 unsigned int fcsr
, orig_fcsr
;
419 _FPU_GETCW (orig_fcsr
);
420 fcsr
= orig_fcsr
| (exceptions
<< 5);
421 if (fcsr
!= orig_fcsr
)
424 return FE_ALL_EXCEPT
& (orig_fcsr
>> 5);
428 fedisableexcept (int exceptions
)
430 exceptions
&= FE_ALL_EXCEPT
;
432 unsigned int fcsr
, orig_fcsr
;
433 _FPU_GETCW (orig_fcsr
);
434 fcsr
= orig_fcsr
& ~ (exceptions
<< 5);
435 if (fcsr
!= orig_fcsr
)
438 return FE_ALL_EXCEPT
& (orig_fcsr
>> 5);
446 return FE_ALL_EXCEPT
& (fcsr
>> 5);
449 # elif defined __loongarch__
452 feenableexcept (int exceptions
)
454 exceptions
&= FE_ALL_EXCEPT
;
456 unsigned int fcsr
, orig_fcsr
;
457 _FPU_GETCW (orig_fcsr
);
458 fcsr
= orig_fcsr
| (exceptions
>> 16);
459 if (fcsr
!= orig_fcsr
)
462 return FE_ALL_EXCEPT
& (orig_fcsr
<< 16);
466 fedisableexcept (int exceptions
)
468 exceptions
&= FE_ALL_EXCEPT
;
470 unsigned int fcsr
, orig_fcsr
;
471 _FPU_GETCW (orig_fcsr
);
472 fcsr
= orig_fcsr
& ~ (exceptions
>> 16);
473 if (fcsr
!= orig_fcsr
)
476 return FE_ALL_EXCEPT
& (orig_fcsr
<< 16);
484 return FE_ALL_EXCEPT
& (fcsr
<< 16);
487 # elif defined __powerpc__
489 # if defined __linux__
490 # include <sys/prctl.h>
496 feenableexcept (int exceptions
)
498 exceptions
&= FE_ALL_EXCEPT
;
500 union { unsigned long long u
; double f
; } memenv
, orig_memenv
;
501 _FPU_GETCW_AS_DOUBLE (memenv
.f
);
502 orig_memenv
= memenv
;
504 memenv
.u
|= ((unsigned int) exceptions
>> 22);
506 if (!(memenv
.u
== orig_memenv
.u
))
508 if ((orig_memenv
.u
& 0x000000f8) == 0 && (memenv
.u
& 0x000000f8) != 0)
510 /* Put the thread into precise trapping mode. */
511 # if defined __linux__ || defined __NetBSD__
512 prctl (PR_SET_FPEXC
, PR_FP_EXC_PRECISE
);
514 /* Documentation: <https://www.ibm.com/docs/en/aix/7.3?topic=f-fp-trap-subroutine> */
515 fp_trap (FP_TRAP_SYNC
);
519 _FPU_SETCW_AS_DOUBLE (memenv
.f
);
522 return FE_ALL_EXCEPT
& ((unsigned int) orig_memenv
.u
<< 22);
526 fedisableexcept (int exceptions
)
528 exceptions
&= FE_ALL_EXCEPT
;
530 union { unsigned long long u
; double f
; } memenv
, orig_memenv
;
531 _FPU_GETCW_AS_DOUBLE (memenv
.f
);
532 orig_memenv
= memenv
;
534 memenv
.u
&= ~ ((unsigned int) exceptions
>> 22);
536 if (!(memenv
.u
== orig_memenv
.u
))
538 _FPU_SETCW_AS_DOUBLE (memenv
.f
);
540 if ((orig_memenv
.u
& 0x000000f8) != 0 && (memenv
.u
& 0x000000f8) == 0)
542 /* Put the thread into no-trapping mode. */
543 # if defined __linux__ || defined __NetBSD__
544 prctl (PR_SET_FPEXC
, PR_FP_EXC_DISABLED
);
546 /* Documentation: <https://www.ibm.com/docs/en/aix/7.3?topic=f-fp-trap-subroutine> */
547 fp_trap (FP_TRAP_OFF
);
552 return FE_ALL_EXCEPT
& ((unsigned int) orig_memenv
.u
<< 22);
558 union { unsigned long long u
; double f
; } memenv
;
559 _FPU_GETCW_AS_DOUBLE (memenv
.f
);
561 return FE_ALL_EXCEPT
& ((unsigned int) memenv
.u
<< 22);
564 # elif defined __riscv
567 feenableexcept (int exceptions
)
569 exceptions
&= FE_ALL_EXCEPT
;
577 fedisableexcept (int exceptions
)
588 # elif defined __s390__ || defined __s390x__
591 feenableexcept (int exceptions
)
593 exceptions
&= FE_ALL_EXCEPT
;
595 unsigned int fpc
, orig_fpc
;
596 _FPU_GETCW (orig_fpc
);
597 # if FE_INEXACT == 8 /* glibc compatible FE_* values */
598 fpc
= orig_fpc
| ((unsigned int) exceptions
<< 24);
599 # else /* musl libc compatible FE_* values */
600 fpc
= orig_fpc
| ((unsigned int) exceptions
<< 8);
605 # if FE_INEXACT == 8 /* glibc compatible FE_* values */
606 return FE_ALL_EXCEPT
& (orig_fpc
>> 24);
607 # else /* musl libc compatible FE_* values */
608 return FE_ALL_EXCEPT
& (orig_fpc
>> 8);
613 fedisableexcept (int exceptions
)
615 exceptions
&= FE_ALL_EXCEPT
;
617 unsigned int fpc
, orig_fpc
;
618 _FPU_GETCW (orig_fpc
);
619 # if FE_INEXACT == 8 /* glibc compatible FE_* values */
620 fpc
= orig_fpc
& ~((unsigned int) exceptions
<< 24);
621 # else /* musl libc compatible FE_* values */
622 fpc
= orig_fpc
& ~((unsigned int) exceptions
<< 8);
627 # if FE_INEXACT == 8 /* glibc compatible FE_* values */
628 return FE_ALL_EXCEPT
& (orig_fpc
>> 24);
629 # else /* musl libc compatible FE_* values */
630 return FE_ALL_EXCEPT
& (orig_fpc
>> 8);
639 # if FE_INEXACT == 8 /* glibc compatible FE_* values */
640 return FE_ALL_EXCEPT
& (fpc
>> 24);
641 # else /* musl libc compatible FE_* values */
642 return FE_ALL_EXCEPT
& (fpc
>> 8);
646 # elif defined __sh__
649 feenableexcept (int exceptions
)
651 exceptions
&= FE_ALL_EXCEPT
;
653 unsigned int fpscr
, orig_fpscr
;
654 _FPU_GETCW (orig_fpscr
);
655 fpscr
= orig_fpscr
| ((unsigned int) exceptions
<< 5);
656 if (fpscr
!= orig_fpscr
)
659 return FE_ALL_EXCEPT
& (orig_fpscr
>> 5);
663 fedisableexcept (int exceptions
)
665 exceptions
&= FE_ALL_EXCEPT
;
667 unsigned int fpscr
, orig_fpscr
;
668 _FPU_GETCW (orig_fpscr
);
669 fpscr
= orig_fpscr
& ~ ((unsigned int) exceptions
<< 5);
670 if (fpscr
!= orig_fpscr
)
673 return FE_ALL_EXCEPT
& (orig_fpscr
>> 5);
681 return FE_ALL_EXCEPT
& (fpscr
>> 5);
684 # elif defined __sparc
687 feenableexcept (int exceptions
)
689 exceptions
&= FE_ALL_EXCEPT
;
691 unsigned long fsr
, orig_fsr
;
692 _FPU_GETCW (orig_fsr
);
693 # if FE_INEXACT == 32 /* glibc compatible FE_* values */
694 fsr
= orig_fsr
| (exceptions
<< 18);
695 # else /* Solaris compatible FE_* values */
696 fsr
= orig_fsr
| (exceptions
<< 23);
701 # if FE_INEXACT == 32 /* glibc compatible FE_* values */
702 return FE_ALL_EXCEPT
& (orig_fsr
>> 18);
703 # else /* Solaris compatible FE_* values */
704 return FE_ALL_EXCEPT
& (orig_fsr
>> 23);
709 fedisableexcept (int exceptions
)
711 exceptions
&= FE_ALL_EXCEPT
;
713 unsigned long fsr
, orig_fsr
;
714 _FPU_GETCW (orig_fsr
);
715 # if FE_INEXACT == 32 /* glibc compatible FE_* values */
716 fsr
= orig_fsr
& ~(exceptions
<< 18);
717 # else /* Solaris compatible FE_* values */
718 fsr
= orig_fsr
& ~(exceptions
<< 23);
723 # if FE_INEXACT == 32 /* glibc compatible FE_* values */
724 return FE_ALL_EXCEPT
& (orig_fsr
>> 18);
725 # else /* Solaris compatible FE_* values */
726 return FE_ALL_EXCEPT
& (orig_fsr
>> 23);
735 # if FE_INEXACT == 32 /* glibc compatible FE_* values */
736 return FE_ALL_EXCEPT
& (fsr
>> 18);
737 # else /* Solaris compatible FE_* values */
738 return FE_ALL_EXCEPT
& (fsr
>> 23);
744 # if defined __GNUC__ || defined __clang__
745 # warning "Unknown CPU / architecture. Please report your platform and compiler to <bug-gnulib@gnu.org>."
747 # define NEED_FALLBACK 1
753 /* The compiler does not support __asm__ statements or equivalent
757 /* FreeBSD ≥ 3.1, NetBSD ≥ 1.1, OpenBSD, IRIX, Solaris, Minix ≥ 3.2. */
759 /* Get fpgetmask, fpsetmask. */
762 /* The type is called 'fp_except_t' on FreeBSD, but 'fp_except' on
763 all other systems. */
764 # if !defined __FreeBSD__
765 # define fp_except_t fp_except
769 exceptions_to_mask (int exceptions
)
772 if (exceptions
& FE_INVALID
)
774 if (exceptions
& FE_DIVBYZERO
)
776 if (exceptions
& FE_OVERFLOW
)
778 if (exceptions
& FE_UNDERFLOW
)
780 if (exceptions
& FE_INEXACT
)
786 mask_to_exceptions (fp_except_t m
)
790 exceptions
|= FE_INVALID
;
792 exceptions
|= FE_DIVBYZERO
;
794 exceptions
|= FE_OVERFLOW
;
796 exceptions
|= FE_UNDERFLOW
;
798 exceptions
|= FE_INEXACT
;
803 feenableexcept (int exceptions
)
805 exceptions
&= FE_ALL_EXCEPT
;
807 fp_except_t trapbits
= fpgetmask ();
808 fpsetmask (trapbits
| exceptions_to_mask (exceptions
));
809 return mask_to_exceptions (trapbits
);
813 fedisableexcept (int exceptions
)
815 exceptions
&= FE_ALL_EXCEPT
;
817 fp_except_t trapbits
= fpgetmask ();
818 fpsetmask (trapbits
& ~ exceptions_to_mask (exceptions
));
819 return mask_to_exceptions (trapbits
);
825 fp_except_t trapbits
= fpgetmask ();
826 return mask_to_exceptions (trapbits
);
829 # elif defined _AIX && defined __powerpc__ /* AIX */
833 <https://www.ibm.com/docs/en/aix/7.3?topic=f-fp-any-enable-fp-is-enabled-fp-enable-all-fp-enable-fp-disable-all-fp-disable-subroutine>
834 <https://www.ibm.com/docs/en/aix/7.3?topic=f-fp-trap-subroutine> */
836 /* Convert from an 'int exceptions' to an fptrap_t. */
837 # if 0 /* Unoptimized */
838 # define exceptions_to_fptrap(exceptions) \
839 ( ((exceptions) & FE_INVALID ? TRP_INVALID : 0) \
840 | ((exceptions) & FE_DIVBYZERO ? TRP_DIV_BY_ZERO : 0) \
841 | ((exceptions) & FE_OVERFLOW ? TRP_OVERFLOW : 0) \
842 | ((exceptions) & FE_UNDERFLOW ? TRP_UNDERFLOW : 0) \
843 | ((exceptions) & FE_INEXACT ? TRP_INEXACT : 0))
844 # else /* Optimized */
845 # define exceptions_to_fptrap(exceptions) \
846 (((unsigned int) (exceptions) & FE_ALL_EXCEPT) >> 22)
850 feenableexcept (int exceptions
)
852 exceptions
&= FE_ALL_EXCEPT
;
854 int prev_enabled
= fegetexcept ();
857 fp_enable (exceptions_to_fptrap (exceptions
));
858 if (prev_enabled
== 0 /* && fegetexcept () != 0 */)
859 /* Enable precise trapping mode. */
860 fp_trap (FP_TRAP_SYNC
);
866 fedisableexcept (int exceptions
)
868 exceptions
&= FE_ALL_EXCEPT
;
870 int prev_enabled
= fegetexcept ();
873 fp_disable (exceptions_to_fptrap (exceptions
));
874 if (prev_enabled
!= 0 && fegetexcept () == 0)
875 /* Disable precise trapping mode. */
876 fp_trap (FP_TRAP_OFF
);
884 return fegetexcept_impl ();
887 # elif HAVE_FESETTRAPENABLE
891 feenableexcept (int exceptions
)
893 exceptions
&= FE_ALL_EXCEPT
;
895 int prev_enabled
= fegettrapenable ();
897 fesettrapenable (prev_enabled
| exceptions
);
902 fedisableexcept (int exceptions
)
904 exceptions
&= FE_ALL_EXCEPT
;
906 int prev_enabled
= fegettrapenable ();
908 fesettrapenable (prev_enabled
& ~exceptions
);
915 return fegettrapenable ();
920 # define NEED_FALLBACK 1
928 /* A dummy fallback. */
931 feenableexcept (int exceptions
)
933 exceptions
&= FE_ALL_EXCEPT
;
940 fedisableexcept (int exceptions
)