diff options
author | Pjotr Prins | 2018-08-25 15:49:47 +0000 |
---|---|---|
committer | Pjotr Prins | 2018-08-25 15:49:47 +0000 |
commit | 4c74f1374e6e7a48a14724e61178953d08c571d4 (patch) | |
tree | 6f8b7aa035fff9ee0606d7558b76a0fe03da0859 /src | |
parent | be551a1b3c324dc96750cf992b6a5784e2b92ec7 (diff) | |
download | pangemma-4c74f1374e6e7a48a14724e61178953d08c571d4.tar.gz |
debug: feenableexcept for MacOS and limit to Intel x64 machines
Diffstat (limited to 'src')
-rw-r--r-- | src/debug.cpp | 56 |
1 files changed, 53 insertions, 3 deletions
diff --git a/src/debug.cpp b/src/debug.cpp index 0b9c19d..c998ffe 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -82,16 +82,66 @@ You can disable floating point tests with the -no-check switch (use at your own this is an Intel hardware feature that does not slow down computations. */ +#if defined(__APPLE__) && defined(__MACH__) + +// Public domain polyfill for feenableexcept on OS X +// http://www-personal.umich.edu/~williams/archive/computation/fe-handling-example.c + +inline int feenableexcept(unsigned int excepts) +{ + static fenv_t fenv; + unsigned int new_excepts = excepts & FE_ALL_EXCEPT; + // previous masks + unsigned int old_excepts; + + if (fegetenv(&fenv)) { + return -1; + } + old_excepts = fenv.__control & FE_ALL_EXCEPT; + + // unmask + fenv.__control &= ~new_excepts; + fenv.__mxcsr &= ~(new_excepts << 7); + + return fesetenv(&fenv) ? -1 : old_excepts; +} + +inline int fedisableexcept(unsigned int excepts) +{ + static fenv_t fenv; + unsigned int new_excepts = excepts & FE_ALL_EXCEPT; + // all previous masks + unsigned int old_excepts; + + if (fegetenv(&fenv)) { + return -1; + } + old_excepts = fenv.__control & FE_ALL_EXCEPT; + + // mask + fenv.__control |= new_excepts; + fenv.__mxcsr |= new_excepts << 7; + + return fesetenv(&fenv) ? -1 : old_excepts; +} + +#endif + void enable_segfpe() { #ifdef __GNUC__ - signal(SIGFPE, sighandler); - feenableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW); + #if defined(__x86_64__) + debug_msg("enable segfpe hardware floating point error detection"); + signal(SIGFPE, sighandler); + feenableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW); + #endif #endif } void disable_segfpe() { #ifdef __GNUC__ - fedisableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW); + #if defined(__x86_64__) + fedisableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW); + #endif #endif } |