On 10/13/26 05:14, Matt Turner wrote:
Alpha raises underflow only if the result it delivers is tiny. softfloat implements IEEE 754 tininess after rounding, which rounds as if the exponent range were unbounded. The two disagree about a result that rounds up to the smallest normal:0x4p-1024 / 0x1.0000000000001p+0 in FE_UPWARD = 0x4p-1024 The binade below DBL_MIN has a finer spacing than the denormals, so with an unbounded exponent the quotient rounds to a value below DBL_MIN and softfloat raises underflow. Alpha does not. glibc marks math/test-float32x-float64-div as XFAIL on Alpha because of this (glibc commit a32db99a38), and under qemu that test unexpectedly passes. Every result that is tiny by Alpha's rule is also tiny by the IEEE one, so there is no need for another tininess mode in softfloat. Drop underflow in the S and T format add, sub, mul, div and cvtts helpers when the delivered result is normal. An insn with a denormal operand is different. Unless DNZ is set it traps for software completion and the kernel computes the result, and the kernel's emulation raises underflow in the same situation: 0x3.ffffffffffffcp-1024 / 0x1.fffffffffffffp-1 in FE_UPWARD = 0x4p-1024, FPCR_UNF set That result is tiny whether tininess is detected before rounding, as math-emu does, or after rounding, as softfloat does. linux-user computes these results in the helper instead of trapping, so keep softfloat's underflow when float_flag_input_denormal_used is set. In system mode gen_ieee_input raises the trap before the helper runs. Signed-off-by: Matt Turner <[email protected]> --- target/alpha/fpu_helper.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/target/alpha/fpu_helper.c b/target/alpha/fpu_helper.c index 643ce641e8..d902cdd9dc 100644 --- a/target/alpha/fpu_helper.c +++ b/target/alpha/fpu_helper.c @@ -55,6 +55,24 @@ static uint32_t soft_to_fpcr_exc(CPUAlphaState *env) return ret; }+/*+ * Alpha raises no underflow when the delivered result is normal. + * softfloat does when that result was rounded up to the smallest + * normal, so drop it, except when a denormal operand means the kernel + * computed the result. + */ +static uint32_t soft_to_fpcr_exc_tiny(CPUAlphaState *env, bool normal) +{ + bool swc = get_float_exception_flags(&FP_STATUS) + & float_flag_input_denormal_used; + uint32_t ret = soft_to_fpcr_exc(env); + + if (unlikely(ret & FPCR_UNF) && normal && !swc) { + ret &= ~FPCR_UNF; + } + return ret; +}
You can't talk about what the kernel does without testing CONFIG_USER_ONLY in there somewhere.
swc doesn't need to be computed early -- ideally neither would normal, but that would require two helpers.
Is it possible to merge this with soft_to_fpcr_exc proper? I see that the comparison results wouldn't have a result value to reference for normality, but they never raise underflow either, so you could just pass 0.
r~
