divide: Move data formatting out of decode2

This moves the data formatting (sign extension of 32-bit operands, and
shifting of the dividend for 32-bit extended divide operations) out of
decode2 into the first cycle of the divider pipe.  This will help make
it possible to do forwarding of results from the execute pipe at the
front of execute1.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/121/head
Paul Mackerras 5 years ago
parent 9568e5f848
commit d9cde63bbc

@ -294,30 +294,10 @@ begin
else
signed_division := d_in.insn(10);
end if;
v.d.is_extended := d_in.insn(8) and not d_in.insn(7);
v.d.is_signed := signed_division;
if d_in.insn(2) = '0' then
-- 64-bit forms
if d_in.insn(8) = '1' and d_in.insn(7) = '0' then
v.d.is_extended := '1';
end if;
v.d.dividend := decoded_reg_a.data;
v.d.divisor := decoded_reg_b.data;
else
-- 32-bit forms
if d_in.insn(8) = '1' and d_in.insn(7) = '0' then -- extended forms
v.d.dividend := decoded_reg_a.data(31 downto 0) & x"00000000";
elsif signed_division = '1' and decoded_reg_a.data(31) = '1' then
-- sign extend to 64 bits
v.d.dividend := x"ffffffff" & decoded_reg_a.data(31 downto 0);
else
v.d.dividend := x"00000000" & decoded_reg_a.data(31 downto 0);
end if;
if signed_division = '1' and decoded_reg_b.data(31) = '1' then
v.d.divisor := x"ffffffff" & decoded_reg_b.data(31 downto 0);
else
v.d.divisor := x"00000000" & decoded_reg_b.data(31 downto 0);
end if;
end if;
v.d.dividend := decoded_reg_a.data;
v.d.divisor := decoded_reg_b.data;
v.d.rc := decode_rc(d_in.decode.rc, d_in.insn);

-- load/store unit

@ -48,17 +48,34 @@ begin
running <= '0';
count <= "0000000";
elsif d_in.valid = '1' then
if d_in.is_extended = '1' and not (d_in.is_signed = '1' and d_in.dividend(63) = '1') then
if d_in.is_extended = '1' and d_in.is_32bit = '0' and
not (d_in.is_signed = '1' and d_in.dividend(63) = '1') then
-- 64-bit extended division
dend <= '0' & d_in.dividend & x"0000000000000000";
else
elsif d_in.is_32bit = '0' then
-- other 64-bit ops
dend <= '0' & x"0000000000000000" & d_in.dividend;
elsif d_in.is_extended = '1' then
-- 32-bit extended ops
dend <= '0' & x"0000000000000000" & d_in.dividend(31 downto 0) & x"00000000";
elsif d_in.is_signed = '1' and d_in.dividend(31) = '1' then
-- other 32-bit signed ops with negative dividend
dend <= '0' & x"0000000000000000ffffffff" & d_in.dividend(31 downto 0);
else
dend <= '0' & x"000000000000000000000000" & d_in.dividend(31 downto 0);
end if;
div <= unsigned(d_in.divisor);
if d_in.is_32bit = '0' then
div <= unsigned(d_in.divisor);
elsif d_in.is_signed = '1' and d_in.divisor(31) = '1' then
div <= unsigned(x"ffffffff" & d_in.divisor(31 downto 0));
else
div <= unsigned(x"00000000" & d_in.divisor(31 downto 0));
end if;
quot <= (others => '0');
write_reg <= d_in.write_reg;
neg_result <= '0';
is_modulus <= d_in.is_modulus;
extended <= d_in.is_extended;
extended <= d_in.is_extended and not d_in.is_32bit;
is_32bit <= d_in.is_32bit;
is_signed <= d_in.is_signed;
rc <= d_in.rc;
@ -66,7 +83,11 @@ begin
running <= '1';
overflow <= '0';
ovf32 <= '0';
signcheck <= d_in.is_signed and (d_in.dividend(63) or d_in.divisor(63));
if d_in.is_32bit = '1' then
signcheck <= d_in.is_signed and (d_in.dividend(31) or d_in.divisor(31));
else
signcheck <= d_in.is_signed and (d_in.dividend(63) or d_in.divisor(63));
end if;
elsif signcheck = '1' then
signcheck <= '0';
neg_result <= dend(63) xor (div(63) and not is_modulus);

@ -319,13 +319,13 @@ begin
divwe_loop : for vlength in 1 to 4 loop
for dlength in 1 to vlength loop
for i in 0 to 100 loop
ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 32)) & x"00000000";
ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));

d1.dividend <= ra;
d1.divisor <= rb;
d1.is_signed <= '1';
d1.is_extended <= '0';
d1.is_extended <= '1';
d1.is_32bit <= '1';
d1.valid <= '1';

@ -342,7 +342,7 @@ begin

behave_rt := (others => '0');
if rb /= x"0000000000000000" then
q64 := std_ulogic_vector(signed(ra) / signed(rb));
q64 := std_ulogic_vector(signed(ra(31 downto 0) & x"00000000") / signed(rb));
if q64(63 downto 31) = x"00000000" & '0' or
q64(63 downto 31) = x"ffffffff" & '1' then
behave_rt := x"00000000" & q64(31 downto 0);
@ -359,13 +359,13 @@ begin
divweu_loop : for vlength in 1 to 4 loop
for dlength in 1 to vlength loop
for i in 0 to 100 loop
ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 32)) & x"00000000";
ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));

d1.dividend <= ra;
d1.divisor <= rb;
d1.is_signed <= '0';
d1.is_extended <= '0';
d1.is_extended <= '1';
d1.is_32bit <= '1';
d1.valid <= '1';

@ -381,8 +381,8 @@ begin
assert d2.valid = '1';

behave_rt := (others => '0');
if unsigned(rb(31 downto 0)) > unsigned(ra(63 downto 32)) then
behave_rt := std_ulogic_vector(unsigned(ra) / unsigned(rb));
if unsigned(rb(31 downto 0)) > unsigned(ra(31 downto 0)) then
behave_rt := std_ulogic_vector(unsigned(ra(31 downto 0) & x"00000000") / unsigned(rb));
end if;
assert behave_rt = d2.write_reg_data
report "bad divweu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);

Loading…
Cancel
Save