execute1: Improve architecture compliance of MSR and related instructions
authorPaul Mackerras <paulus@ozlabs.org>
Tue, 28 Apr 2020 10:28:20 +0000 (20:28 +1000)
committerPaul Mackerras <paulus@ozlabs.org>
Tue, 28 Apr 2020 21:44:06 +0000 (07:44 +1000)
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>
common.vhdl
execute1.vhdl

index 9f6e96d03b7b65f0a3819d70b70e36549ba72e3c..9041d324f1578686536713a35ceb37cd539aa152 100644 (file)
@@ -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;
 
index 2c0a558950e2e66d0b4e83013ed9366fe7cc682e..0f4eea938274e7e83738a00298828ae9e8380a00 100644 (file)
@@ -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);