From e5651e2eab9adf780a229878124b9c96f9fc13c2 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 9 Dec 2025 16:12:05 +1100 Subject: [PATCH] FPU: Avoid adding bias twice in UE=1 underflow case In case of underflow with UE=1, ROUND_UFLOW state adds the exponent bias and then goes to NORMALIZE state if the value is not normalized. Then NORMALIZE state will go back to ROUND_UFLOW if the exponent is still tiny, resulting in the bias getting added twice. To avoid this, if ROUND_UFLOW needs to do normalization, it goes to a new NORM_UFLOW state which does the normalization and goes to ROUNDING state. Signed-off-by: Paul Mackerras --- fpu.vhdl | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/fpu.vhdl b/fpu.vhdl index c539e9d..a005c81 100644 --- a/fpu.vhdl +++ b/fpu.vhdl @@ -72,7 +72,7 @@ architecture behaviour of fpu is INT_SHIFT, INT_ROUND, INT_ISHIFT, INT_FINAL, INT_CHECK, INT_OFLOW, FINISH, NORMALIZE, - ROUND_UFLOW, ROUND_OFLOW, + ROUND_UFLOW, NORM_UFLOW, ROUND_OFLOW, ROUNDING, ROUND_INC, ROUNDING_2, ROUNDING_3, DENORM, RENORM_A, RENORM_B, RENORM_C, @@ -2459,12 +2459,22 @@ begin re_set_result <= '1'; if r.r(UNIT_BIT) = '0' then rs_norm <= '1'; - v.state := NORMALIZE; + v.state := NORM_UFLOW; else v.state := ROUNDING; end if; end if; + when NORM_UFLOW => + -- normalize for UE=1 underflow case + -- r.shift = clz(r.r) - 7 + opsel_r <= RES_SHIFT; + set_r := '1'; + re_sel2 <= REXP2_NE; + re_set_result <= '1'; + set_x := '1'; + v.state := ROUNDING; + when ROUND_OFLOW => rcls_op <= RCLS_TINF; v.fpscr(FPSCR_OX) := '1'; @@ -2560,8 +2570,8 @@ begin rcls_op <= RCLS_TZERO; -- If the result is zero, that's handled below. -- Renormalize result after rounding - re_set_result <= '1'; v.denorm := exp_tiny; + re_set_result <= '1'; if new_exp < to_signed(-1022, EXP_BITS) then v.state := DENORM; else