@ -38,6 +38,10 @@ architecture behaviour of execute1 is
next_lr : std_ulogic_vector(63 downto 0);
mul_in_progress : std_ulogic;
div_in_progress : std_ulogic;
slow_op_dest : gpr_index_t;
slow_op_rc : std_ulogic;
slow_op_oe : std_ulogic;
slow_op_xerc : xer_common_t;
end record;
signal r, rin : reg_type;
@ -187,6 +191,7 @@ begin
variable carry_32, carry_64 : std_ulogic;
variable sign1, sign2 : std_ulogic;
variable abs1, abs2 : signed(63 downto 0);
variable overflow : std_ulogic;
begin
result := (others => '0');
result_with_carry := (others => '0');
@ -238,12 +243,6 @@ begin
-- signals to multiply unit
x_to_multiply <= Execute1ToMultiplyInit;
x_to_multiply.insn_type <= e_in.insn_type;
x_to_multiply.write_reg <= gspr_to_gpr(e_in.write_reg);
x_to_multiply.rc <= e_in.rc;
x_to_multiply.xerc <= v.e.xerc;
if e_in.insn_type = OP_MUL_L64 then
x_to_multiply.oe <= e_in.oe;
end if;
x_to_multiply.is_32bit <= e_in.is_32bit;
if e_in.is_32bit = '1' then
@ -291,16 +290,12 @@ begin
end if;
x_to_divider <= Execute1ToDividerInit;
x_to_divider.write_reg <= gspr_to_gpr(e_in.write_reg);
x_to_divider.is_signed <= e_in.is_signed;
x_to_divider.is_32bit <= e_in.is_32bit;
if e_in.insn_type = OP_MOD then
x_to_divider.is_modulus <= '1';
end if;
x_to_divider.neg_result <= sign1 xor (sign2 and not x_to_divider.is_modulus);
x_to_divider.rc <= e_in.rc;
x_to_divider.oe <= e_in.oe;
x_to_divider.xerc <= v.e.xerc;
if e_in.is_32bit = '0' then
-- 64-bit forms
if e_in.insn_type = OP_DIVE then
@ -342,6 +337,10 @@ begin
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;
v.slow_op_xerc := v.e.xerc;
case_0: case e_in.insn_type is
@ -664,35 +663,36 @@ begin
v.e.write_len := x"8";
v.e.sign_extend := '0';
v.e.valid := '1';
elsif r.mul_in_progress = '1' then
if multiply_to_x.valid = '1' then
v.e.write_reg := gpr_to_gspr(multiply_to_x.write_reg_nr);
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
(r.div_in_progress = '1' and divider_to_x.valid = '1') then
if r.mul_in_progress = '1' then
result := multiply_to_x.write_reg_data;
result_en := '1';
v.e.rc := multiply_to_x.rc;
v.e.xerc := multiply_to_x.xerc;
v.e.write_xerc_enable := multiply_to_x.write_xerc_enable;
v.e.valid := '1';
v.e.write_len := x"8";
v.e.sign_extend := '0';
overflow := multiply_to_x.overflow;
else
stall_out <= '1';
v.mul_in_progress := '1';
end if;
elsif r.div_in_progress = '1' then
if divider_to_x.valid = '1' then
v.e.write_reg := gpr_to_gspr(divider_to_x.write_reg_nr);
result := divider_to_x.write_reg_data;
overflow := divider_to_x.overflow;
end if;
result_en := '1';
v.e.rc := divider_to_x.rc;
v.e.xerc := divider_to_x.xerc;
v.e.write_xerc_enable := divider_to_x.write_xerc_enable;
v.e.write_reg := gpr_to_gspr(v.slow_op_dest);
v.e.rc := v.slow_op_rc;
v.e.xerc := v.slow_op_xerc;
v.e.write_xerc_enable := v.slow_op_oe;
-- We must test oe because the RC update code in writeback
-- will use the xerc value to set CR0:SO so we must not clobber
-- xerc if OE wasn't set.
if v.slow_op_oe = '1' then
v.e.xerc.ov := overflow;
v.e.xerc.ov32 := overflow;
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.div_in_progress := '1';
v.mul_in_progress := r.mul_in_progress;
v.div_in_progress := r.div_in_progress;
end if;
end if;