Loading...
Searching...
No Matches
feexceptErsatz.H
Go to the documentation of this file.
1// ============================================================================
2// Generic handling of floating point exceptions
3//
4// 2018 Alexey Matveichev
5// 2021 Tatsuya Shimizu - ARM64 support
6// 2023 Guanyang Xue - improve ARM64 support
7// ----------------------------------------------------------------------------
8//
9// Original Author
10// David N. Williams
11//
12// License
13// Public Domain
14//
15// Description
16// Alternate, nondefault handling of IEEE 754 floating-point exceptions
17// in OS X, based on the GNU functions feenableexcept(), fedisableeexcept()
18// and fegetexcept() [in libm]
19//
20// http://www-personal.umich.edu/~williams/archive/computation/fe-handling-example.c
21// ============================================================================
22
23#ifndef Foam_feexceptErsatz_H
24#define Foam_feexceptErsatz_H
25
26#ifdef __APPLE__
27#include <fenv.h>
28
29// Workaround for Apple Silicon - has SIGILL (illegal instruction) not SIGFPE
30#if defined __arm64__
31#undef SIGFPE
32#define SIGFPE SIGILL
33#endif
34
35// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
36
37inline int feenableexcept(unsigned int excepts)
38{
39 static fenv_t fenv;
40 unsigned int new_excepts = excepts & FE_ALL_EXCEPT;
41 unsigned int old_excepts; // previous masks
42
43 if (fegetenv(&fenv))
44 {
45 return -1;
46 }
47
48#if defined __arm64__
49 old_excepts = fenv.__fpsr & FE_ALL_EXCEPT;
50
51 fenv.__fpsr |= new_excepts;
52 fenv.__fpcr |= (new_excepts << 8);
53#else
54 old_excepts = fenv.__control & FE_ALL_EXCEPT;
55
56 fenv.__control &= ~new_excepts;
57 fenv.__mxcsr &= ~(new_excepts << 7);
58#endif
59
60 return fesetenv(&fenv) ? -1 : old_excepts;
61}
62
63
64inline int fedisableexcept(unsigned int excepts)
65{
66 static fenv_t fenv;
67 unsigned int new_excepts = excepts & FE_ALL_EXCEPT;
68 unsigned int old_excepts; // all previous masks
69
70 if (fegetenv(&fenv))
71 {
72 return -1;
73 }
74
75#if defined __arm64__
76 old_excepts = fenv.__fpsr & FE_ALL_EXCEPT;
77
78 fenv.__fpsr &= ~new_excepts;
79 fenv.__fpcr &= ~(new_excepts << 8);
80#else
81 old_excepts = fenv.__control & FE_ALL_EXCEPT;
82
83 fenv.__control |= new_excepts;
84 fenv.__mxcsr |= (new_excepts << 7);
85#endif
86
87 return fesetenv(&fenv) ? -1 : old_excepts;
88}
89
90// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
91
92#endif // __APPLE__
93#endif
94
95// ************************************************************************* //