mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-05-02 22:43:29 +00:00
execute1: Improve architecture compliance of MSR and related instructions
This makes our treatment of the MSR conform better with the ISA. - On reset, initialize the MSR to have the SF and LE bits set and all the others reset. For good measure initialize r properly too. - Fix the bit numbering in msr_copy (the code was using big-endian bit numbers, not little-endian). - Use constants like MSR_EE to index MSR bits instead of expressions like '63 - 48', for readability. - Set MSR[SF, LE] and clear MSR[PR, IR, DR, RI] on interrupts. - Copy the relevant fields for rfid instead of using msr_copy, because the partial function fields of the MSR should be left unchanged, not zeroed. Our implementation of rfid is like the architecture description of hrfid, because we don't implement hypervisor mode. - Return the whole MSR for mfmsr. - Implement the L field for mtmsrd (L=1 copies just EE and RI). - For mtmsrd with L=0, leave out the HV, ME and LE bits as per the arch. - For mtmsrd and rfid, if PR ends up set, then also set EE, IR and DR as per the arch. - A few other minor tidyups (no semantic change). Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
@@ -7,6 +7,15 @@ use work.decode_types.all;
|
||||
|
||||
package common is
|
||||
|
||||
-- MSR bit numbers
|
||||
constant MSR_SF : integer := (63 - 0); -- Sixty-Four bit mode
|
||||
constant MSR_EE : integer := (63 - 48); -- External interrupt Enable
|
||||
constant MSR_PR : integer := (63 - 49); -- PRoblem state
|
||||
constant MSR_IR : integer := (63 - 58); -- Instruction Relocation
|
||||
constant MSR_DR : integer := (63 - 59); -- Data Relocation
|
||||
constant MSR_RI : integer := (63 - 62); -- Recoverable Interrupt
|
||||
constant MSR_LE : integer := (63 - 63); -- Little Endian
|
||||
|
||||
-- SPR numbers
|
||||
subtype spr_num_t is integer range 0 to 1023;
|
||||
|
||||
|
||||
@@ -48,6 +48,11 @@ architecture behaviour of execute1 is
|
||||
slow_op_oe : std_ulogic;
|
||||
slow_op_xerc : xer_common_t;
|
||||
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;
|
||||
|
||||
@@ -124,11 +129,11 @@ architecture behaviour of execute1 is
|
||||
-- tion MSR bits are not saved or restored.
|
||||
-- Full function MSR bits lie in the range 0:32, 37:41, and
|
||||
-- 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(32 downto 0) := msr(32 downto 0);
|
||||
msr_out(41 downto 37) := msr(41 downto 37);
|
||||
msr_out(63 downto 48) := msr(63 downto 48);
|
||||
msr_out(63 downto 31) := msr(63 downto 31);
|
||||
msr_out(26 downto 22) := msr(26 downto 22);
|
||||
msr_out(15 downto 0) := msr(15 downto 0);
|
||||
return msr_out;
|
||||
end;
|
||||
|
||||
@@ -193,14 +198,20 @@ begin
|
||||
execute1_0: process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
r <= rin;
|
||||
ctrl <= ctrl_tmp;
|
||||
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;
|
||||
if rst = '1' then
|
||||
r <= reg_type_init;
|
||||
ctrl.msr <= (MSR_SF => '1', MSR_LE => '1', others => '0');
|
||||
ctrl.irq_state <= WRITE_SRR0;
|
||||
else
|
||||
r <= rin;
|
||||
ctrl <= ctrl_tmp;
|
||||
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 process;
|
||||
|
||||
@@ -370,7 +381,7 @@ begin
|
||||
ctrl_tmp.dec <= std_ulogic_vector(unsigned(ctrl.dec) - 1);
|
||||
|
||||
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";
|
||||
irq_valid := '1';
|
||||
end if;
|
||||
@@ -400,7 +411,13 @@ begin
|
||||
v.e.exc_write_reg := fast_spr_num(SPR_SRR1);
|
||||
v.e.exc_write_data := ctrl.srr1;
|
||||
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_nia <= ctrl.irq_nia;
|
||||
v.e.valid := e_in.valid;
|
||||
@@ -545,7 +562,7 @@ begin
|
||||
when OP_B =>
|
||||
f_out.redirect <= '1';
|
||||
if (insn_aa(e_in.insn)) then
|
||||
f_out.redirect_nia <= std_ulogic_vector(signed(b_in));
|
||||
f_out.redirect_nia <= b_in;
|
||||
else
|
||||
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(b_in));
|
||||
end if;
|
||||
@@ -561,7 +578,7 @@ begin
|
||||
if ppc_bc_taken(bo, bi, e_in.cr, a_in) = 1 then
|
||||
f_out.redirect <= '1';
|
||||
if (insn_aa(e_in.insn)) then
|
||||
f_out.redirect_nia <= std_ulogic_vector(signed(b_in));
|
||||
f_out.redirect_nia <= b_in;
|
||||
else
|
||||
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(b_in));
|
||||
end if;
|
||||
@@ -584,7 +601,17 @@ begin
|
||||
when OP_RFID =>
|
||||
f_out.redirect <= '1';
|
||||
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 =>
|
||||
result := ppc_cmpb(c_in, b_in);
|
||||
result_en := '1';
|
||||
@@ -658,7 +685,7 @@ begin
|
||||
end loop;
|
||||
end if;
|
||||
when OP_MFMSR =>
|
||||
result := msr_copy(ctrl.msr);
|
||||
result := ctrl.msr;
|
||||
result_en := '1';
|
||||
when OP_MFSPR =>
|
||||
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);
|
||||
end if;
|
||||
v.e.write_cr_data := c_in(31 downto 0);
|
||||
when OP_MTMSRD =>
|
||||
-- FIXME handle just the bits we need to.
|
||||
ctrl_tmp.msr <= msr_copy(c_in);
|
||||
when OP_MTMSRD =>
|
||||
if e_in.insn(16) = '1' then
|
||||
-- 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 =>
|
||||
report "MTSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
|
||||
"=" & to_hstring(c_in);
|
||||
|
||||
Reference in New Issue
Block a user