mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-11 23:43:15 +00:00
FPU: Fix comparison of remainder in square root code
The square root procedure needs to compare B - R^2 with 2R + 1 to decide whether to increment the square root estimate R by 1. It currently does this by putting 2R + 1 in B and using the pcmpb_lt and pcmpb_eq signals. This is not correct because the comparisons that generate those signals have a 2-bit shift embedded into them. Instead, put 2R + 1 into C and use pcmpc_lt/eq, which don't have the 2-bit shift. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
parent
f3b9566ae2
commit
41988e3b5f
16
fpu.vhdl
16
fpu.vhdl
@ -1303,6 +1303,9 @@ begin
|
||||
end if;
|
||||
|
||||
-- Compare P with zero and with B
|
||||
-- This has a 2-bit shift in it (p(59..4) compared to b(57..2))
|
||||
-- because it's used in the FP division code to determine whether
|
||||
-- to increment the quotient at bit 2 (DP_RBIT).
|
||||
px_nz := or (r.p(UNIT_BIT + 1 downto 4));
|
||||
pcmpb_eq := '0';
|
||||
if r.p(59 downto 4) = r.b.mantissa(UNIT_BIT + 1 downto DP_RBIT) then
|
||||
@ -1314,6 +1317,9 @@ begin
|
||||
elsif unsigned(r.p(59 downto 4)) < unsigned(r.b.mantissa(UNIT_BIT + 1 downto DP_RBIT)) then
|
||||
pcmpb_lt := '1';
|
||||
end if;
|
||||
-- Compare P with zero and with C
|
||||
-- This is used in the square root and integer division code
|
||||
-- to decide whether to increment the result by 1
|
||||
pcmpc_eq := '0';
|
||||
if r.p = r.c.mantissa then
|
||||
pcmpc_eq := '1';
|
||||
@ -2271,29 +2277,29 @@ begin
|
||||
|
||||
when SQRT_11 =>
|
||||
-- compute P = A - R * R (remainder)
|
||||
-- also put 2 * R + 1 into B for comparison with P
|
||||
-- also put 2 * R + 1 into C for comparison with P
|
||||
msel_1 <= MUL1_R;
|
||||
msel_2 <= MUL2_R;
|
||||
msel_add <= MULADD_A;
|
||||
msel_inv <= '1';
|
||||
f_to_multiply.valid <= r.first;
|
||||
shiftin := '1';
|
||||
set_b := r.first;
|
||||
set_c := r.first;
|
||||
if multiply_to_f.valid = '1' then
|
||||
v.state := SQRT_12;
|
||||
end if;
|
||||
|
||||
when SQRT_12 =>
|
||||
-- test if remainder is 0 or >= B = 2*R + 1
|
||||
-- test if remainder is 0 or >= C = 2*R + 1
|
||||
set_r := '0';
|
||||
opsel_c <= CIN_INC;
|
||||
if pcmpb_lt = '1' then
|
||||
if pcmpc_lt = '1' then
|
||||
-- square root is correct, set X if remainder non-zero
|
||||
v.x := r.p(UNIT_BIT + 2) or px_nz;
|
||||
else
|
||||
-- square root needs to be incremented by 1
|
||||
set_r := '1';
|
||||
v.x := not pcmpb_eq;
|
||||
v.x := not pcmpc_eq;
|
||||
end if;
|
||||
v.state := FINISH;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user