|
11 | 11 |
|
12 | 12 | #include "hdr/stdint_proxy.h" |
13 | 13 | #include "hdr/types/fenv_t.h" |
| 14 | +#include "src/__support/CPP/bit.h" |
14 | 15 | #include "src/__support/FPUtil/x86_64/fenv_x86_common.h" |
15 | 16 | #include "src/__support/macros/attributes.h" // LIBC_INLINE |
16 | 17 | #include "src/__support/macros/config.h" |
@@ -85,6 +86,40 @@ LIBC_INLINE static void raise_except(uint16_t excepts) { |
85 | 86 | uint32_t mxcsr = _MM_GET_EXCEPTION_STATE(); |
86 | 87 | mxcsr |= excepts; |
87 | 88 | _MM_SET_EXCEPTION_STATE(mxcsr); |
| 89 | +#ifdef LIBC_TRAP_ON_RAISE_FP_EXCEPT |
| 90 | + // We will try to trigger the SIGFPE if floating point exceptions are not |
| 91 | + // masked. Since we already set all the floating point exception flags, we |
| 92 | + // only need to trigger the trap on one of them. |
| 93 | + static constexpr float EXCEPTION_INPUTS[6][2] = { |
| 94 | + // FE_INVALID: 0.0 * inf |
| 95 | + {0.0f, cpp::bit_cast<float>(0x7f80'0000U)}, |
| 96 | + // FE_DENORM: 1.0 * 0x1.0p-128 |
| 97 | + {1.0f, 0x1.0p-128f}, |
| 98 | + // FE_DIVBYZERO: 1.0 / 0.0 |
| 99 | + {1.0f, 0.0f}, |
| 100 | + // FE_OVERFLOW: 0x1.0p127 * 0x1.0p127 |
| 101 | + {0x1.0p127f, 0x1.0p127f}, |
| 102 | + // FE_UNDERFLOW: 0x1.0p-126 * 0x1.0p-126 |
| 103 | + {0x1.0p-126f, 0x1.0p-126f}, |
| 104 | + // FE_INEXACT: (1 + 2^-12) * (1 + 2^-12) |
| 105 | + {0x1.001p0f, 0x1.001p0f}}; |
| 106 | + |
| 107 | + uint32_t except_masks = |
| 108 | + (~(get_mxcsr() >> ExceptionFlags::MXCSR_EXCEPTION_MASK_BIT_POSITION)) & |
| 109 | + excepts; |
| 110 | + if (except_masks) { |
| 111 | + int idx = cpp::countr_zero(except_masks); |
| 112 | + if (idx == 2) { |
| 113 | + // FE_DIVBYZERO, we need floating point division operations. |
| 114 | + [[maybe_unused]] volatile float z = EXCEPTION_INPUTS[idx][0]; |
| 115 | + z /= EXCEPTION_INPUTS[idx][1]; |
| 116 | + } else { |
| 117 | + // For the remaining exceptions, we floating point multiplications. |
| 118 | + [[maybe_unused]] volatile float z = EXCEPTION_INPUTS[idx][0]; |
| 119 | + z *= EXCEPTION_INPUTS[idx][1]; |
| 120 | + } |
| 121 | + } |
| 122 | +#endif // LIBC_TRAP_ON_RAISE_FP_EXCEPT |
88 | 123 | } |
89 | 124 |
|
90 | 125 | LIBC_INLINE static uint16_t enable_except(uint16_t excepts) { |
|
0 commit comments