write_enable : std_ulogic;
write_reg: gspr_index_t;
write_data: std_ulogic_vector(63 downto 0);
- write_len : std_ulogic_vector(3 downto 0);
write_cr_enable : std_ulogic;
write_cr_mask : std_ulogic_vector(7 downto 0);
write_cr_data : std_ulogic_vector(31 downto 0);
write_xerc_enable : std_ulogic;
xerc : xer_common_t;
- sign_extend: std_ulogic;
end record;
constant Execute1ToWritebackInit : Execute1ToWritebackType := (valid => '0', rc => '0', write_enable => '0',
- write_cr_enable => '0', sign_extend => '0',
+ write_cr_enable => '0',
write_xerc_enable => '0', xerc => xerc_init,
others => (others => '0'));
variable sign1, sign2 : std_ulogic;
variable abs1, abs2 : signed(63 downto 0);
variable overflow : std_ulogic;
+ variable negative : std_ulogic;
begin
result := (others => '0');
result_with_carry := (others => '0');
v.e.valid := '1';
v.e.write_reg := e_in.write_reg;
- v.e.write_len := x"8";
- v.e.sign_extend := '0';
v.slow_op_dest := gspr_to_gpr(e_in.write_reg);
v.slow_op_rc := e_in.rc;
v.slow_op_oe := e_in.oe;
when OP_CNTZ =>
result := countzero_result;
result_en := '1';
- when OP_EXTS =>
- v.e.write_len := e_in.data_len;
- v.e.sign_extend := '1';
- result := e_in.read_data3;
+ when OP_EXTS =>
+ -- note data_len is a 1-hot encoding
+ negative := (e_in.data_len(0) and e_in.read_data3(7)) or
+ (e_in.data_len(1) and e_in.read_data3(15)) or
+ (e_in.data_len(2) and e_in.read_data3(31));
+ result := (others => negative);
+ if e_in.data_len(2) = '1' then
+ result(31 downto 16) := e_in.read_data3(31 downto 16);
+ end if;
+ if e_in.data_len(2) = '1' or e_in.data_len(1) = '1' then
+ result(15 downto 8) := e_in.read_data3(15 downto 8);
+ end if;
+ result(7 downto 0) := e_in.read_data3(7 downto 0);
result_en := '1';
when OP_ISEL =>
crbit := to_integer(unsigned(insn_bc(e_in.insn)));
result_en := '1';
result := r.next_lr;
v.e.write_reg := fast_spr_num(SPR_LR);
- v.e.write_len := x"8";
- v.e.sign_extend := '0';
v.e.valid := '1';
elsif r.mul_in_progress = '1' or r.div_in_progress = '1' then
if (r.mul_in_progress = '1' and multiply_to_x.valid = '1') or
v.e.xerc.so := v.slow_op_xerc.so or overflow;
end if;
v.e.valid := '1';
- v.e.write_len := x"8";
- v.e.sign_extend := '0';
else
stall_out <= '1';
v.mul_in_progress := r.mul_in_progress;
signal sign_extend : std_ulogic;
signal negative : std_ulogic;
signal second_word : std_ulogic;
- signal zero : std_ulogic;
begin
writeback_0: process(clk)
begin
variable k : unsigned(3 downto 0);
variable cf: std_ulogic_vector(3 downto 0);
variable xe: xer_common_t;
+ variable zero : std_ulogic;
+ variable sign : std_ulogic;
begin
x := "" & e_in.valid;
y := "" & l_in.valid;
rc <= '0';
brev_lenm1 <= "000";
- byte_offset <= "000";
- data_len <= x"8";
partial_write <= '0';
- sign_extend <= '0';
second_word <= '0';
xe := e_in.xerc;
data_in <= (others => '0');
if e_in.write_enable = '1' then
w_out.write_reg <= e_in.write_reg;
w_out.write_enable <= '1';
- data_in <= e_in.write_data;
- data_len <= unsigned(e_in.write_len);
- sign_extend <= e_in.sign_extend;
rc <= e_in.rc;
end if;
c_out.write_xerc_data <= e_in.xerc;
end if;
+ sign_extend <= l_in.sign_extend;
+ data_len <= unsigned(l_in.write_len);
+ byte_offset <= unsigned(l_in.write_shift);
if l_in.write_enable = '1' then
w_out.write_reg <= gpr_to_gspr(l_in.write_reg);
- data_in <= l_in.write_data;
- data_len <= unsigned(l_in.write_len);
- byte_offset <= unsigned(l_in.write_shift);
- sign_extend <= l_in.sign_extend;
if l_in.byte_reverse = '1' then
brev_lenm1 <= unsigned(l_in.write_len(2 downto 0)) - 1;
end if;
end loop;
for i in 0 to 7 loop
j := to_integer(perm(i)) * 8;
- data_permuted(i * 8 + 7 downto i * 8) <= data_in(j + 7 downto j);
+ data_permuted(i * 8 + 7 downto i * 8) <= l_in.write_data(j + 7 downto j);
end loop;
-- If the data can arrive split over two cycles, this will be correct
trim_ctl(i) <= '0' & (negative and sign_extend);
end if;
end loop;
- zero <= not negative;
for i in 0 to 7 loop
case trim_ctl(i) is
when "11" =>
data_trimmed(i * 8 + 7 downto i * 8) <= data_latched(i * 8 + 7 downto i * 8);
when "10" =>
data_trimmed(i * 8 + 7 downto i * 8) <= data_permuted(i * 8 + 7 downto i * 8);
- if or data_permuted(i * 8 + 7 downto i * 8) /= '0' then
- zero <= '0';
- end if;
when "01" =>
data_trimmed(i * 8 + 7 downto i * 8) <= x"FF";
when others =>
end loop;
-- deliver to regfile
- w_out.write_data <= data_trimmed;
+ if l_in.write_enable = '1' then
+ w_out.write_data <= data_trimmed;
+ else
+ w_out.write_data <= e_in.write_data;
+ end if;
-- Perform CR0 update for RC forms
+ -- Note that loads never have a form with an RC bit, therefore this can test e_in.write_data
if rc = '1' then
+ sign := e_in.write_data(63);
+ zero := not (or e_in.write_data);
c_out.write_cr_enable <= '1';
c_out.write_cr_mask <= num_to_fxm(0);
- cf(3) := negative;
- cf(2) := not negative and not zero;
+ cf(3) := sign;
+ cf(2) := not sign and not zero;
cf(1) := zero;
cf(0) := xe.so;
c_out.write_cr_data(31 downto 28) <= cf;