Decode sc in the major opcode decode table
authorPaul Mackerras <paulus@ozlabs.org>
Mon, 6 Apr 2020 03:24:08 +0000 (13:24 +1000)
committerPaul Mackerras <paulus@ozlabs.org>
Tue, 7 Apr 2020 10:08:43 +0000 (20:08 +1000)
This decodes sc using entry 17 of the major_decode_rom_array table
instead of a special case in the decode1_1 process.  This means that
only the major opcode (the top 6 bits) is checked at decode time.
To make sure that the instruction is sc not scv, we now check bit
1 of the instruction at execute time and generate an illegal
instruction interrupt if it is 0 (indicating scv).  The level field
of the sc instruction is now ignored.

This reduces LUT consumption by 31 LUTs on the Arty A7-100.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
decode1.vhdl
execute1.vhdl

index 5ee5176948be45e3ac02482fcdc0f8b098af72cf..dbcea4781c42783e99faea0ecd610bbb63091c1b 100644 (file)
@@ -60,6 +60,7 @@ architecture behaviour of decode1 is
                20 =>       (ALU,    OP_RLC,       RA,         CONST_SH32,  RS,   RA,   '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC,   '0', '0'), -- rlwimi
                21 =>       (ALU,    OP_RLC,       NONE,       CONST_SH32,  RS,   RA,   '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC,   '0', '0'), -- rlwinm
                23 =>       (ALU,    OP_RLC,       NONE,       RB,          RS,   RA,   '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC,   '0', '0'), -- rlwnm
+                17 =>       (ALU,    OP_SC,        NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- sc
                38 =>       (LDST,   OP_STORE,     RA_OR_ZERO, CONST_SI,    RS,   NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- stb
                39 =>       (LDST,   OP_STORE,     RA_OR_ZERO, CONST_SI,    RS,   NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0'), -- stbu
                44 =>       (LDST,   OP_STORE,     RA_OR_ZERO, CONST_SI,    RS,   NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- sth
@@ -344,7 +345,6 @@ architecture behaviour of decode1 is
         --                                                      op                                           in   out   A   out  in    out  len        ext                                 pipe
         constant attn_instr    : decode_rom_t := (ALU,    OP_ATTN,      NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1');
        constant nop_instr     : decode_rom_t := (ALU,    OP_NOP,       NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0');
-       constant sc_instr     :  decode_rom_t := (ALU,    OP_SC,        NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0');
 
 begin
        decode1_0: process(clk)
@@ -402,9 +402,6 @@ begin
                 elsif std_match(f_in.insn, "01100000000000000000000000000000") then
                         report "PPC_nop";
                         v.decode := nop_instr;
-                elsif std_match(f_in.insn, "010001--------------0000000---1-") then
-                        report "PPC_sc";
-                        v.decode := sc_instr;
                 elsif std_match(f_in.insn, "000000---------------0100000000-") then
                         report "PPC_attn";
                         v.decode := attn_instr;
index 0aff3dfc4c193771b99fd5ad719476c6a6c87d7f..dd5cb21641f6231394cacc0924fe24023bfd4f9c 100644 (file)
@@ -239,6 +239,7 @@ begin
        variable exception : std_ulogic;
         variable exception_nextpc : std_ulogic;
         variable trapval : std_ulogic_vector(4 downto 0);
+        variable illegal : std_ulogic;
     begin
        result := (others => '0');
        result_with_carry := (others => '0');
@@ -388,6 +389,7 @@ begin
 
        ctrl_tmp.irq_state <= WRITE_SRR0;
        exception := '0';
+        illegal := '0';
         exception_nextpc := '0';
         v.e.exc_write_enable := '0';
         v.e.exc_write_reg := fast_spr_num(SPR_SRR0);
@@ -426,22 +428,21 @@ begin
            when OP_ILLEGAL =>
                -- we need two cycles to write srr0 and 1
                -- will need more when we have to write DSISR, DAR and HIER
-               exception := '1';
-               ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#700#, 64));
-               ctrl_tmp.srr1 <= msr_copy(ctrl.msr);
-               -- Since we aren't doing Hypervisor emulation assist (0xe40) we
-               -- set bit 44 to indicate we have an illegal
-               ctrl_tmp.srr1(63 - 44) <= '1';
-               report "illegal";
+               illegal := '1';
            when OP_SC =>
-               -- FIXME Assume everything is SC (not SCV) for now
+               -- check bit 1 of the instruction is 1 so we know this is sc;
+                -- 0 would mean scv, so generate an illegal instruction interrupt
                -- we need two cycles to write srr0 and 1
                -- will need more when we have to write DSISR, DAR and HIER
-               exception := '1';
-                exception_nextpc := '1';
-               ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#C00#, 64));
-               ctrl_tmp.srr1 <= msr_copy(ctrl.msr);
-               report "sc";
+                if e_in.insn(1) = '1' then
+                    exception := '1';
+                    exception_nextpc := '1';
+                    ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#C00#, 64));
+                    ctrl_tmp.srr1 <= msr_copy(ctrl.msr);
+                    report "sc";
+                else
+                    illegal := '1';
+                end if;
            when OP_ATTN =>
                terminate_out <= '1';
                report "ATTN";
@@ -836,6 +837,15 @@ begin
            end if;
        end if;
 
+        if illegal = '1' then
+            exception := '1';
+            ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#700#, 64));
+            ctrl_tmp.srr1 <= msr_copy(ctrl.msr);
+            -- Since we aren't doing Hypervisor emulation assist (0xe40) we
+            -- set bit 44 to indicate we have an illegal
+            ctrl_tmp.srr1(63 - 44) <= '1';
+            report "illegal";
+        end if;
        if exception = '1' then
             v.e.exc_write_enable := '1';
             if exception_nextpc = '1' then