@ -48,6 +48,11 @@ architecture behaviour of execute1 is
slow_op_oe : std_ulogic;
slow_op_oe : std_ulogic;
slow_op_xerc : xer_common_t;
slow_op_xerc : xer_common_t;
end record;
end record;
constant reg_type_init : reg_type :=
(e => Execute1ToWritebackInit, lr_update => '0',
mul_in_progress => '0', div_in_progress => '0', cntz_in_progress => '0',
slow_op_rc => '0', slow_op_oe => '0', slow_op_xerc => xerc_init,
others => (others => '0'));
signal r, rin : reg_type;
signal r, rin : reg_type;
@ -124,11 +129,11 @@ architecture behaviour of execute1 is
-- tion MSR bits are not saved or restored.
-- tion MSR bits are not saved or restored.
-- Full function MSR bits lie in the range 0:32, 37:41, and
-- Full function MSR bits lie in the range 0:32, 37:41, and
-- 48:63, and partial function MSR bits lie in the range
-- 48:63, and partial function MSR bits lie in the range
-- 33:36 and 42:47.
-- 33:36 and 42:47. (Note this is IBM bit numbering).
msr_out := (others => '0');
msr_out := (others => '0');
msr_out(32 downto 0) := msr(32 downto 0);
msr_out(63 downto 31) := msr(63 downto 31);
msr_out(41 downto 37) := msr(41 downto 37);
msr_out(26 downto 22) := msr(26 downto 22);
msr_out(63 downto 48) := msr(63 downto 48);
msr_out(15 downto 0) := msr(15 downto 0);
return msr_out;
return msr_out;
end;
end;
@ -193,14 +198,20 @@ begin
execute1_0: process(clk)
execute1_0: process(clk)
begin
begin
if rising_edge(clk) then
if rising_edge(clk) then
r <= rin;
if rst = '1' then
ctrl <= ctrl_tmp;
r <= reg_type_init;
assert not (r.lr_update = '1' and e_in.valid = '1')
ctrl.msr <= (MSR_SF => '1', MSR_LE => '1', others => '0');
report "LR update collision with valid in EX1"
ctrl.irq_state <= WRITE_SRR0;
severity failure;
else
if r.lr_update = '1' then
r <= rin;
report "LR update to " & to_hstring(r.next_lr);
ctrl <= ctrl_tmp;
end if;
assert not (r.lr_update = '1' and e_in.valid = '1')
report "LR update collision with valid in EX1"
severity failure;
if r.lr_update = '1' then
report "LR update to " & to_hstring(r.next_lr);
end if;
end if;
end if;
end if;
end process;
end process;
@ -370,7 +381,7 @@ begin
ctrl_tmp.dec <= std_ulogic_vector(unsigned(ctrl.dec) - 1);
ctrl_tmp.dec <= std_ulogic_vector(unsigned(ctrl.dec) - 1);
irq_valid := '0';
irq_valid := '0';
if ctrl.msr(63 - 48) = '1' and ctrl.dec(63) = '1' then
if ctrl.msr(MSR_EE) = '1' and ctrl.dec(63) = '1' then
report "IRQ valid";
report "IRQ valid";
irq_valid := '1';
irq_valid := '1';
end if;
end if;
@ -400,7 +411,13 @@ begin
v.e.exc_write_reg := fast_spr_num(SPR_SRR1);
v.e.exc_write_reg := fast_spr_num(SPR_SRR1);
v.e.exc_write_data := ctrl.srr1;
v.e.exc_write_data := ctrl.srr1;
v.e.exc_write_enable := '1';
v.e.exc_write_enable := '1';
ctrl_tmp.msr(63 - 48) <= '0'; -- clear EE
ctrl_tmp.msr(MSR_SF) <= '1';
ctrl_tmp.msr(MSR_EE) <= '0';
ctrl_tmp.msr(MSR_PR) <= '0';
ctrl_tmp.msr(MSR_IR) <= '0';
ctrl_tmp.msr(MSR_DR) <= '0';
ctrl_tmp.msr(MSR_RI) <= '0';
ctrl_tmp.msr(MSR_LE) <= '1';
f_out.redirect <= '1';
f_out.redirect <= '1';
f_out.redirect_nia <= ctrl.irq_nia;
f_out.redirect_nia <= ctrl.irq_nia;
v.e.valid := e_in.valid;
v.e.valid := e_in.valid;
@ -545,7 +562,7 @@ begin
when OP_B =>
when OP_B =>
f_out.redirect <= '1';
f_out.redirect <= '1';
if (insn_aa(e_in.insn)) then
if (insn_aa(e_in.insn)) then
f_out.redirect_nia <= std_ulogic_vector(signed(b_in));
f_out.redirect_nia <= b_in;
else
else
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(b_in));
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(b_in));
end if;
end if;
@ -561,7 +578,7 @@ begin
if ppc_bc_taken(bo, bi, e_in.cr, a_in) = 1 then
if ppc_bc_taken(bo, bi, e_in.cr, a_in) = 1 then
f_out.redirect <= '1';
f_out.redirect <= '1';
if (insn_aa(e_in.insn)) then
if (insn_aa(e_in.insn)) then
f_out.redirect_nia <= std_ulogic_vector(signed(b_in));
f_out.redirect_nia <= b_in;
else
else
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(b_in));
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(b_in));
end if;
end if;
@ -584,7 +601,17 @@ begin
when OP_RFID =>
when OP_RFID =>
f_out.redirect <= '1';
f_out.redirect <= '1';
f_out.redirect_nia <= a_in(63 downto 2) & "00"; -- srr0
f_out.redirect_nia <= a_in(63 downto 2) & "00"; -- srr0
ctrl_tmp.msr <= msr_copy(std_ulogic_vector(signed(b_in))); -- srr1
-- Can't use msr_copy here because the partial function MSR
-- bits should be left unchanged, not zeroed.
ctrl_tmp.msr(63 downto 31) <= b_in(63 downto 31);
ctrl_tmp.msr(26 downto 22) <= b_in(26 downto 22);
ctrl_tmp.msr(15 downto 0) <= b_in(15 downto 0);
if b_in(MSR_PR) = '1' then
ctrl_tmp.msr(MSR_EE) <= '1';
ctrl_tmp.msr(MSR_IR) <= '1';
ctrl_tmp.msr(MSR_DR) <= '1';
end if;
when OP_CMPB =>
when OP_CMPB =>
result := ppc_cmpb(c_in, b_in);
result := ppc_cmpb(c_in, b_in);
result_en := '1';
result_en := '1';
@ -658,7 +685,7 @@ begin
end loop;
end loop;
end if;
end if;
when OP_MFMSR =>
when OP_MFMSR =>
result := msr_copy(ctrl.msr);
result := ctrl.msr;
result_en := '1';
result_en := '1';
when OP_MFSPR =>
when OP_MFSPR =>
report "MFSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
report "MFSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
@ -714,9 +741,23 @@ begin
v.e.write_cr_mask := num_to_fxm(crnum);
v.e.write_cr_mask := num_to_fxm(crnum);
end if;
end if;
v.e.write_cr_data := c_in(31 downto 0);
v.e.write_cr_data := c_in(31 downto 0);
when OP_MTMSRD =>
when OP_MTMSRD =>
-- FIXME handle just the bits we need to.
if e_in.insn(16) = '1' then
ctrl_tmp.msr <= msr_copy(c_in);
-- just update EE and RI
ctrl_tmp.msr(MSR_EE) <= c_in(MSR_EE);
ctrl_tmp.msr(MSR_RI) <= c_in(MSR_RI);
else
-- Architecture says to leave out bits 3 (HV), 51 (ME)
-- and 63 (LE) (IBM bit numbering)
ctrl_tmp.msr(63 downto 61) <= c_in(63 downto 61);
ctrl_tmp.msr(59 downto 13) <= c_in(59 downto 13);
ctrl_tmp.msr(11 downto 1) <= c_in(11 downto 1);
if c_in(MSR_PR) = '1' then
ctrl_tmp.msr(MSR_EE) <= '1';
ctrl_tmp.msr(MSR_IR) <= '1';
ctrl_tmp.msr(MSR_DR) <= '1';
end if;
end if;
when OP_MTSPR =>
when OP_MTSPR =>
report "MTSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
report "MTSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
"=" & to_hstring(c_in);
"=" & to_hstring(c_in);