diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-22 08:02:35 -1000 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-22 08:02:35 -1000 |
| commit | 979fac3eaaa02fa887c7dfe6509248b21dca3872 (patch) | |
| tree | feba5ab6a2305c92162cd09549fd7832b8aaa22a | |
| parent | 5b6eaf4aeba0aab8cc757d79102aa9662d148f97 (diff) | |
| parent | b74843b38da8f1186fd7d447646c835b47096a15 (diff) | |
Merge tag 'alpha-fixes-v7.4' of git://git.kernel.org/pub/scm/linux/kernel/git/mattst88/alpha
Pull alpha floating point emulation fix from Matt Turner:
"Make the FP emulation determine tininess after rounding, as the
hardware does.
soft-fp always determined it before rounding, so an operation that
trapped for software completion could report an underflow the same
operation would not report when it did not trap. glibc's math
testsuite catches the disagreement.
This adds _FP_TININESS_AFTER_ROUNDING to the shared soft-fp code in
include/math-emu/, as glibc's copy already has, and sets it only for
alpha. It defaults to zero, so powerpc, sh and sparc are unchanged.
This is the last patch of a three-patch series; the first two were
merged for v7.3"
* tag 'alpha-fixes-v7.4' of git://git.kernel.org/pub/scm/linux/kernel/git/mattst88/alpha:
alpha: determine tininess after rounding in the FP emulation
| -rw-r--r-- | arch/alpha/include/asm/sfp-machine.h | 4 | ||||
| -rw-r--r-- | include/math-emu/op-common.h | 23 | ||||
| -rw-r--r-- | include/math-emu/soft-fp.h | 8 |
3 files changed, 33 insertions, 2 deletions
diff --git a/arch/alpha/include/asm/sfp-machine.h b/arch/alpha/include/asm/sfp-machine.h index 5fe63afbd474..bff1ad963c68 100644 --- a/arch/alpha/include/asm/sfp-machine.h +++ b/arch/alpha/include/asm/sfp-machine.h @@ -59,6 +59,10 @@ R##_c = FP_CLS_NAN; \ } while (0) +/* Alpha determines tininess after rounding, so the emulation must do the + same as the hardware does for the results it produces itself. */ +#define _FP_TININESS_AFTER_ROUNDING 1 + /* Obtain the current rounding mode. */ #define FP_ROUNDMODE mode #define FP_RND_NEAREST (FPCR_DYN_NORMAL >> FPCR_DYN_SHIFT) diff --git a/include/math-emu/op-common.h b/include/math-emu/op-common.h index 8ce066c035cf..1d1ce5c08efc 100644 --- a/include/math-emu/op-common.h +++ b/include/math-emu/op-common.h @@ -135,6 +135,24 @@ do { \ else \ { \ /* we've got a denormalized number */ \ + int _FP_PACK_CANONICAL_is_tiny = 1; \ + if (_FP_TININESS_AFTER_ROUNDING && X##_e == 0) \ + { \ + /* Architectures that detect tininess after rounding \ + only signal underflow if the result is still \ + subnormal once rounded as if the exponent range \ + were unbounded. Round a copy to find out. */ \ + FP_DECL_##fs(_FP_PACK_CANONICAL_T); \ + /* The class field is not used by the rounding below, \ + and is unused entirely where this block is dead. */ \ + (void)_FP_PACK_CANONICAL_T##_c; \ + _FP_FRAC_COPY_##wc(_FP_PACK_CANONICAL_T, X); \ + _FP_PACK_CANONICAL_T##_s = X##_s; \ + _FP_PACK_CANONICAL_T##_e = X##_e; \ + _FP_ROUND(wc, _FP_PACK_CANONICAL_T); \ + if (_FP_FRAC_OVERP_##wc(fs, _FP_PACK_CANONICAL_T)) \ + _FP_PACK_CANONICAL_is_tiny = 0; \ + } \ X##_e = -X##_e + 1; \ if (X##_e <= _FP_WFRACBITS_##fs) \ { \ @@ -161,8 +179,9 @@ do { \ _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ } \ } \ - if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) || \ - (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW)) \ + if (_FP_PACK_CANONICAL_is_tiny \ + && ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) || \ + (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW))) \ FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \ } \ else \ diff --git a/include/math-emu/soft-fp.h b/include/math-emu/soft-fp.h index 5650c1628383..02ada0a9fca1 100644 --- a/include/math-emu/soft-fp.h +++ b/include/math-emu/soft-fp.h @@ -31,6 +31,14 @@ #include <endian.h> #endif +/* Whether the architecture determines tininess of a floating-point + result after rounding rather than before it. IEEE 754 permits either + but requires the same choice for every operation, so this has to agree + with what the hardware does for the results it produces itself. */ +#ifndef _FP_TININESS_AFTER_ROUNDING +#define _FP_TININESS_AFTER_ROUNDING 0 +#endif + #define _FP_WORKBITS 3 #define _FP_WORK_LSB ((_FP_W_TYPE)1 << 3) #define _FP_WORK_ROUND ((_FP_W_TYPE)1 << 2) |
