@ -82,8 +82,6 @@ architecture behaviour of execute1 is
signal rotator_carry: std_ulogic;
signal rotator_carry: std_ulogic;
signal logical_result: std_ulogic_vector(63 downto 0);
signal logical_result: std_ulogic_vector(63 downto 0);
signal countzero_result: std_ulogic_vector(63 downto 0);
signal countzero_result: std_ulogic_vector(63 downto 0);
signal popcnt_result: std_ulogic_vector(63 downto 0);
signal parity_result: std_ulogic_vector(63 downto 0);
-- multiply signals
-- multiply signals
signal x_to_multiply: Execute1ToMultiplyType;
signal x_to_multiply: Execute1ToMultiplyType;
@ -208,9 +206,7 @@ begin
invert_in => e_in.invert_a,
invert_in => e_in.invert_a,
invert_out => e_in.invert_out,
invert_out => e_in.invert_out,
result => logical_result,
result => logical_result,
datalen => e_in.data_len,
datalen => e_in.data_len
popcnt => popcnt_result,
parity => parity_result
);
);
countzero_0: entity work.zero_counter
countzero_0: entity work.zero_counter
@ -295,7 +291,6 @@ begin
variable sign1, sign2 : std_ulogic;
variable sign1, sign2 : std_ulogic;
variable abs1, abs2 : signed(63 downto 0);
variable abs1, abs2 : signed(63 downto 0);
variable overflow : std_ulogic;
variable overflow : std_ulogic;
variable negative : std_ulogic;
variable zerohi, zerolo : std_ulogic;
variable zerohi, zerolo : std_ulogic;
variable msb_a, msb_b : std_ulogic;
variable msb_a, msb_b : std_ulogic;
variable a_lt : std_ulogic;
variable a_lt : std_ulogic;
@ -308,6 +303,7 @@ begin
variable is_branch : std_ulogic;
variable is_branch : std_ulogic;
variable taken_branch : std_ulogic;
variable taken_branch : std_ulogic;
variable abs_branch : std_ulogic;
variable abs_branch : std_ulogic;
variable spr_val : std_ulogic_vector(63 downto 0);
begin
begin
result := (others => '0');
result := (others => '0');
result_with_carry := (others => '0');
result_with_carry := (others => '0');
@ -627,7 +623,7 @@ begin
end if;
end if;
end if;
end if;
end if;
end if;
when OP_AND | OP_OR | OP_XOR =>
when OP_AND | OP_OR | OP_XOR | OP_POPCNT | OP_PRTY | OP_CMPB | OP_EXTS =>
result := logical_result;
result := logical_result;
result_en := '1';
result_en := '1';
when OP_B =>
when OP_B =>
@ -677,27 +673,10 @@ begin
ctrl_tmp.msr(MSR_DR) <= '1';
ctrl_tmp.msr(MSR_DR) <= '1';
end if;
end if;
when OP_CMPB =>
result := ppc_cmpb(c_in, b_in);
result_en := '1';
when OP_CNTZ =>
when OP_CNTZ =>
v.e.valid := '0';
v.e.valid := '0';
v.cntz_in_progress := '1';
v.cntz_in_progress := '1';
v.busy := '1';
v.busy := '1';
when OP_EXTS =>
-- note data_len is a 1-hot encoding
negative := (e_in.data_len(0) and c_in(7)) or
(e_in.data_len(1) and c_in(15)) or
(e_in.data_len(2) and c_in(31));
result := (others => negative);
if e_in.data_len(2) = '1' then
result(31 downto 16) := c_in(31 downto 16);
end if;
if e_in.data_len(2) = '1' or e_in.data_len(1) = '1' then
result(15 downto 8) := c_in(15 downto 8);
end if;
result(7 downto 0) := c_in(7 downto 0);
result_en := '1';
when OP_ISEL =>
when OP_ISEL =>
crbit := to_integer(unsigned(insn_bc(e_in.insn)));
crbit := to_integer(unsigned(insn_bc(e_in.insn)));
if e_in.cr(31-crbit) = '1' then
if e_in.cr(31-crbit) = '1' then
@ -769,24 +748,25 @@ begin
result(63-45) := v.e.xerc.ca32;
result(63-45) := v.e.xerc.ca32;
end if;
end if;
else
else
spr_val := c_in;
case decode_spr_num(e_in.insn) is
case decode_spr_num(e_in.insn) is
when SPR_TB =>
when SPR_TB =>
result := ctrl.tb;
spr_val := ctrl.tb;
when SPR_DEC =>
when SPR_DEC =>
result := ctrl.dec;
spr_val := ctrl.dec;
when 724 => -- LOG_ADDR SPR
when 724 => -- LOG_ADDR SPR
result := log_wr_addr & r.log_addr_spr;
spr_val := log_wr_addr & r.log_addr_spr;
when 725 => -- LOG_DATA SPR
when 725 => -- LOG_DATA SPR
result := log_rd_data;
spr_val := log_rd_data;
v.log_addr_spr := std_ulogic_vector(unsigned(r.log_addr_spr) + 1);
v.log_addr_spr := std_ulogic_vector(unsigned(r.log_addr_spr) + 1);
when others =>
when others =>
-- mfspr from unimplemented SPRs should be a nop in
-- mfspr from unimplemented SPRs should be a nop in
-- supervisor mode and a program interrupt for user mode
-- supervisor mode and a program interrupt for user mode
result := c_in;
if ctrl.msr(MSR_PR) = '1' then
if ctrl.msr(MSR_PR) = '1' then
illegal := '1';
illegal := '1';
end if;
end if;
end case;
end case;
result := spr_val;
end if;
end if;
when OP_MFCR =>
when OP_MFCR =>
if e_in.insn(20) = '0' then
if e_in.insn(20) = '0' then
@ -862,12 +842,6 @@ begin
end if;
end if;
end case;
end case;
end if;
end if;
when OP_POPCNT =>
result := popcnt_result;
result_en := '1';
when OP_PRTY =>
result := parity_result;
result_en := '1';
when OP_RLC | OP_RLCL | OP_RLCR | OP_SHL | OP_SHR | OP_EXTSWSLI =>
when OP_RLC | OP_RLCL | OP_RLCR | OP_SHL | OP_SHR | OP_EXTSWSLI =>
result := rotator_result;
result := rotator_result;
if e_in.output_carry = '1' then
if e_in.output_carry = '1' then
@ -917,12 +891,14 @@ begin
-- Update LR on the next cycle after a branch link
-- Update LR on the next cycle after a branch link
-- If we're not writing back anything else, we can write back LR
-- If we're not writing back anything else, we can write back LR
-- this cycle, otherwise we take an extra cycle.
-- this cycle, otherwise we take an extra cycle. We use the
-- exc_write path since next_nia is written through that path
-- in other places.
if e_in.lr = '1' then
if e_in.lr = '1' then
if result_en = '0' then
if result_en = '0' then
result_en := '1';
v.e.exc_write_enable := '1';
result := next_nia;
v.e.exc_write_data := next_nia;
v.e.write_reg := fast_spr_num(SPR_LR);
v.e.exc_write_reg := fast_spr_num(SPR_LR);
else
else
v.lr_update := '1';
v.lr_update := '1';
v.next_lr := next_nia;
v.next_lr := next_nia;
@ -939,9 +915,9 @@ begin
end if;
end if;
elsif r.lr_update = '1' then
elsif r.lr_update = '1' then
result_en := '1';
v.e.exc_write_enable := '1';
result := r.next_lr;
v.e.exc_write_data := r.next_lr;
v.e.write_reg := fast_spr_num(SPR_LR);
v.e.exc_write_reg := fast_spr_num(SPR_LR);
v.e.valid := '1';
v.e.valid := '1';
elsif r.cntz_in_progress = '1' then
elsif r.cntz_in_progress = '1' then
-- cnt[lt]z always takes two cycles
-- cnt[lt]z always takes two cycles