FPU: Fix behaviour of fdiv with denormalized divisor

Renormalization of the divisor for fdiv[s] was adjusting the result
exponent in the wrong direction, making the result smaller in
magnitude than it should be by a power of 2.  Fix this by negating
r.shift in the RENORM_B2 state and then subtracting it in the LOOKUP
cycle.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/425/head
Paul Mackerras 10 months ago
parent 59a7996f1c
commit 51954671f3

@ -1817,8 +1817,17 @@ begin


when RENORM_B2 => when RENORM_B2 =>
set_b := '1'; set_b := '1';
re_sel2 <= REXP2_NE; -- For fdiv, we need to increase result_exp by shift rather
re_set_result <= '1'; -- than decreasing it as for fre/frsqrte and fsqrt.
-- We do that by negating r.shift in this cycle and then
-- setting result_exp to new_exp in the next cycle
if r.use_a = '1' then
rs_sel1 <= RSH1_S;
rs_neg1 <= '1';
else
re_sel2 <= REXP2_NE;
re_set_result <= '1';
end if;
v.opsel_a := AIN_B; v.opsel_a := AIN_B;
v.state := LOOKUP; v.state := LOOKUP;


@ -2038,6 +2047,12 @@ begin
when LOOKUP => when LOOKUP =>
-- r.opsel_a = AIN_B -- r.opsel_a = AIN_B
-- wait one cycle for inverse_table[B] lookup -- wait one cycle for inverse_table[B] lookup
-- if this is a division, compute exponent
-- (see comment on RENORM_B2 above)
if r.use_a = '1' then
re_sel2 <= REXP2_NE;
re_set_result <= '1';
end if;
v.first := '1'; v.first := '1';
if r.insn(4) = '0' then if r.insn(4) = '0' then
if r.insn(3) = '0' then if r.insn(3) = '0' then

Loading…
Cancel
Save