Decode prefixed instructions
authorPaul Mackerras <paulus@ozlabs.org>
Mon, 3 Jul 2023 02:32:43 +0000 (12:32 +1000)
committerPaul Mackerras <paulus@ozlabs.org>
Thu, 6 Jul 2023 09:39:40 +0000 (19:39 +1000)
This adds logic to do basic decoding of the prefixed instructions
defined in PowerISA v3.1B which are in the SFFS (Scalar Fixed plus
Floating-Point Subset) compliancy subset.  In PowerISA v3.1B SFFS,
there are 14 prefixed load/store instructions plus the prefixed no-op
instruction (pnop).  The prefixed load/store instructions all use an
extended version of D-form, which has an extra 18 bits of displacement
in the prefix, plus an 'R' bit which enables PC-relative addressing.

When decode1 sees an instruction word where the insn_code is
INSN_prefix (i.e. the primary opcode was 1), it stores the prefix word
and sends nothing down to decode2 in that cycle.  When the next valid
instruction word arrives, it is interpreted as a suffix, meaning that
its insn_code gets modified before being used to look up the decode
table.

The insn_code values are rearranged so that the values for
instructions which are the suffix of a valid prefixed instruction are
all at even indexes, and the corresponding prefixed instructions
follow immediately, so that an insn_code value can be converted to the
corresponding prefixed value by setting the LSB of the insn_code
value.  There are two prefixed instructions, pld and pstd, for which
the suffix is not a valid SFFS instruction by itself, so these have
been given dummy insn_code values which decode as illegal (INSN_op57
and INSN_op61).

For a prefixed instruction, decode1 examines the type and subtype
fields of the prefix and checks that the suffix is valid for the type
and subtype.  This check doesn't affect which entry of the decode
table is used; the result is passed down to decode2, and will in
future be acted upon in execute1.

The instruction address passed down to decode2 is the address of the
prefix.  To enable this, part of the instruction address is saved when
the prefix is seen, and then the instruction address received from
icache is partly overlaid by the saved prefix address.  Because
prefixed instructions are not permitted to cross 64-byte boundaries,
we only need to save bits 5:2 of the instruction to do this.  If the
alignment restriction ever gets relaxed, we will then need to save
more bits of the address.

Decode2 has been extended to handle the R bit of the prefix (in 8LS
and MLS forms) and to be able to generate the 34-bit immediate value
from the prefix and suffix.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
common.vhdl
decode1.vhdl
decode2.vhdl
decode_types.vhdl
insn_helpers.vhdl
predecode.vhdl

index 44302c76b480051d396c147647cf984c3666c7c4..838179b1720e8ac842680eab1d196d6de44cf4b5 100644 (file)
@@ -263,6 +263,9 @@ package common is
        valid: std_ulogic;
        stop_mark : std_ulogic;
        nia: std_ulogic_vector(63 downto 0);
+        prefixed: std_ulogic;
+        prefix: std_ulogic_vector(25 downto 0);
+        illegal_suffix: std_ulogic;
        insn: std_ulogic_vector(31 downto 0);
        decode: decode_rom_t;
         br_pred: std_ulogic; -- Branch was predicted to be taken
@@ -274,7 +277,9 @@ package common is
         reg_c : gspr_index_t;
     end record;
     constant Decode1ToDecode2Init : Decode1ToDecode2Type :=
-        (valid => '0', stop_mark => '0', nia => (others => '0'), insn => (others => '0'),
+        (valid => '0', stop_mark => '0', nia => (others => '0'),
+         prefixed => '0', prefix => (others => '0'), insn => (others => '0'),
+         illegal_suffix => '0',
          decode => decode_rom_init, br_pred => '0', big_endian => '0',
          spr_info => spr_id_init, ram_spr => ram_spr_info_init,
          reg_a => (others => '0'), reg_b => (others => '0'), reg_c => (others => '0'));
index c987beca00d79e4bafc0d8941a0b6d26674ee730..138e483113f9fdfe2dbdaa8a7d66752ac3af74eb 100644 (file)
@@ -45,6 +45,16 @@ architecture behaviour of decode1 is
     signal decode_rom_addr : insn_code;
     signal decode : decode_rom_t;
 
+    type prefix_state_t is record
+        prefixed : std_ulogic;
+        prefix   : std_ulogic_vector(25 downto 0);
+        pref_ia  : std_ulogic_vector(3 downto 0);
+    end record;
+    constant prefix_state_init : prefix_state_t := (prefixed => '0', prefix => (others => '0'),
+                                                    pref_ia => (others => '0'));
+
+    signal pr, pr_in : prefix_state_t;
+
     signal fetch_failed : std_ulogic;
 
     -- If we have an FPU, then it is used for integer divisions,
@@ -266,6 +276,22 @@ architecture behaviour of decode1 is
         INSN_orc         =>  (ALU,  NONE, OP_OR,        NONE,       RB,          RS,   RA,   '0', '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC,   '0', '0', NONE),
         INSN_ori         =>  (ALU,  NONE, OP_OR,        NONE,       CONST_UI,    RS,   RA,   '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
         INSN_oris        =>  (ALU,  NONE, OP_OR,        NONE,       CONST_UI_HI, RS,   RA,   '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
+        INSN_paddi       =>  (ALU,  NONE, OP_ADD,       RA0_OR_CIA, CONST_PSI,   NONE, RT,   '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
+        INSN_plbz        =>  (LDST, NONE, OP_LOAD,      RA0_OR_CIA, CONST_PSI,   NONE, RT,   '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
+        INSN_pld         =>  (LDST, NONE, OP_LOAD,      RA0_OR_CIA, CONST_PSI,   NONE, RT,   '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
+        INSN_plfd        =>  (LDST, FPU,  OP_LOAD,      RA0_OR_CIA, CONST_PSI,   NONE, FRT,  '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
+        INSN_plfs        =>  (LDST, FPU,  OP_LOAD,      RA0_OR_CIA, CONST_PSI,   NONE, FRT,  '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE),
+        INSN_plha        =>  (LDST, NONE, OP_LOAD,      RA0_OR_CIA, CONST_PSI,   NONE, RT,   '0', '0', '0', '0', ZERO, '0', is2B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE),
+        INSN_plhz        =>  (LDST, NONE, OP_LOAD,      RA0_OR_CIA, CONST_PSI,   NONE, RT,   '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
+        INSN_plwa        =>  (LDST, NONE, OP_LOAD,      RA0_OR_CIA, CONST_PSI,   NONE, RT,   '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE),
+        INSN_plwz        =>  (LDST, NONE, OP_LOAD,      RA0_OR_CIA, CONST_PSI,   NONE, RT,   '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
+        INSN_pnop        =>  (ALU,  NONE, OP_NOP,       NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
+        INSN_pstb        =>  (LDST, NONE, OP_STORE,     RA0_OR_CIA, CONST_PSI,   RS,   NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
+        INSN_pstd        =>  (LDST, NONE, OP_STORE,     RA0_OR_CIA, CONST_PSI,   RS,   NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
+        INSN_pstfd       =>  (LDST, FPU,  OP_STORE,     RA0_OR_CIA, CONST_PSI,   FRS,  NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
+        INSN_pstfs       =>  (LDST, FPU,  OP_STORE,     RA0_OR_CIA, CONST_PSI,   FRS,  NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE),
+        INSN_psth        =>  (LDST, NONE, OP_STORE,     RA0_OR_CIA, CONST_PSI,   RS,   NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
+        INSN_pstw        =>  (LDST, NONE, OP_STORE,     RA0_OR_CIA, CONST_PSI,   RS,   NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
         INSN_popcntb     =>  (ALU,  NONE, OP_POPCNT,    NONE,       NONE,        RS,   RA,   '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
         INSN_popcntd     =>  (ALU,  NONE, OP_POPCNT,    NONE,       NONE,        RS,   RA,   '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
         INSN_popcntw     =>  (ALU,  NONE, OP_POPCNT,    NONE,       NONE,        RS,   RA,   '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
@@ -434,12 +460,17 @@ begin
             if rst = '1' then
                 r <= Decode1ToDecode2Init;
                 fetch_failed <= '0';
+                pr <= prefix_state_init;
             elsif flush_in = '1' then
                 r.valid <= '0';
                 fetch_failed <= '0';
+                pr <= prefix_state_init;
             elsif stall_in = '0' then
                 r <= rin;
                 fetch_failed <= f_in.fetch_failed;
+                if f_in.valid = '1' then
+                    pr <= pr_in;
+                end if;
             end if;
             if rst = '1' then
                 br.br_nia <= (others => '0');
@@ -471,12 +502,18 @@ begin
         variable icode : insn_code;
         variable sprn : spr_num_t;
         variable maybe_rb : std_ulogic;
+        variable pv : prefix_state_t;
+        variable icode_bits : std_ulogic_vector(9 downto 0);
+        variable valid_suffix : std_ulogic;
     begin
         v := Decode1ToDecode2Init;
+        pv := pr;
 
         v.valid := f_in.valid;
         v.nia  := f_in.nia;
         v.insn := f_in.insn;
+        v.prefix := pr.prefix;
+        v.prefixed := pr.prefixed;
         v.stop_mark := f_in.stop_mark;
         v.big_endian := f_in.big_endian;
 
@@ -490,17 +527,59 @@ begin
         end if;
 
         icode := f_in.icode;
+        icode_bits := std_ulogic_vector(to_unsigned(insn_code'pos(icode), 10));
 
         if f_in.fetch_failed = '1' then
-            icode := INSN_fetch_fail;
+            icode_bits := std_ulogic_vector(to_unsigned(insn_code'pos(INSN_fetch_fail), 10));
             -- Only send down a single OP_FETCH_FAILED
             v.valid := not fetch_failed;
+            pv := prefix_state_init;
+
+        elsif pr.prefixed = '1' then
+            -- Check suffix value and convert to the prefixed instruction code
+            if pr.prefix(24) = '1' then
+                -- either pnop or illegal
+                icode_bits := std_ulogic_vector(to_unsigned(insn_code'pos(INSN_pnop), 10));
+            else
+                -- various load/store instructions
+                icode_bits(0) := '1';
+            end if;
+            valid_suffix := '0';
+            case pr.prefix(25 downto 23) is
+                when "000" =>    -- 8LS
+                    if icode >= INSN_first_8ls and icode < INSN_first_rb then
+                        valid_suffix := '1';
+                    end if;
+                when "100" =>   -- MLS
+                    if icode >= INSN_first_mls and icode < INSN_first_8ls then
+                        valid_suffix := '1';
+                    elsif icode >= INSN_first_fp_mls and icode < INSN_first_fp_nonmls then
+                        valid_suffix := '1';
+                    end if;
+                when "110" =>   -- MRR, i.e. pnop
+                    if pr.prefix(22 downto 20) = "000" then
+                        valid_suffix := '1';
+                    end if;
+                when others =>
+            end case;
+            v.nia(5 downto 2) := pr.pref_ia;
+            v.prefixed := '1';
+            v.prefix := pr.prefix;
+            v.illegal_suffix := not valid_suffix;
+            pv := prefix_state_init;
+
+        elsif icode = INSN_prefix then
+            pv.prefixed := '1';
+            pv.pref_ia := f_in.nia(5 downto 2);
+            pv.prefix := f_in.insn(25 downto 0);
+            v.valid := '0';
+
         end if;
-        decode_rom_addr <= icode;
+        decode_rom_addr <= insn_code'val(to_integer(unsigned(icode_bits)));
 
         if f_in.valid = '1' then
-            report "Decode " & insn_code'image(icode) & " " & to_hstring(f_in.insn) &
-                " at " & to_hstring(f_in.nia);
+            report "Decode " & insn_code'image(insn_code'val(to_integer(unsigned(icode_bits)))) & " " &
+                to_hstring(f_in.insn) & " at " & to_hstring(f_in.nia);
         end if;
 
         -- Branch predictor
@@ -533,6 +612,8 @@ begin
         br_target := std_ulogic_vector(signed(br.br_nia) + br.br_offset);
 
         -- Work out GPR/FPR read addresses
+        -- Note that for prefixed instructions we are working this out based
+        -- only on the suffix.
         maybe_rb := '0';
         vr.reg_1_addr := '0' & insn_ra(f_in.insn);
         vr.reg_2_addr := '0' & insn_rb(f_in.insn);
@@ -568,6 +649,7 @@ begin
         -- Update registers
         rin <= v;
         br_in <= bv;
+        pr_in <= pv;
 
         -- Update outputs
         d_out <= r;
index f58bd9b77e3602897dd9e9ed00dc941f069447d8..fa3b54d45f3ad9d711fcd36b5830b42c9ec8e190 100644 (file)
@@ -83,12 +83,13 @@ architecture behaviour of decode2 is
     constant decode_output_reg_init : decode_output_reg_t := ('0', (others => '0'));
 
     function decode_input_reg_a (t : input_reg_a_t; insn_in : std_ulogic_vector(31 downto 0);
+                                 prefix : std_ulogic_vector(25 downto 0);
                                  instr_addr : std_ulogic_vector(63 downto 0))
         return decode_input_reg_t is
     begin
-        if t = RA or (t = RA_OR_ZERO and insn_ra(insn_in) /= "00000") then
+        if t = RA or ((t = RA_OR_ZERO or t = RA0_OR_CIA) and insn_ra(insn_in) /= "00000") then
             return ('1', gpr_to_gspr(insn_ra(insn_in)), (others => '0'));
-        elsif t = CIA then
+        elsif t = CIA or (t = RA0_OR_CIA and insn_prefix_r(prefix) = '1') then
             return ('0', (others => '0'), instr_addr);
         elsif HAS_FPU and t = FRA then
             return ('1', fpr_to_gspr(insn_fra(insn_in)), (others => '0'));
@@ -97,7 +98,8 @@ architecture behaviour of decode2 is
         end if;
     end;
 
-    function decode_input_reg_b (t : input_reg_b_t; insn_in : std_ulogic_vector(31 downto 0))
+    function decode_input_reg_b (t : input_reg_b_t; insn_in : std_ulogic_vector(31 downto 0);
+                                 prefix : std_ulogic_vector(25 downto 0))
         return decode_input_reg_t is
         variable ret : decode_input_reg_t;
     begin
@@ -114,6 +116,8 @@ architecture behaviour of decode2 is
                 ret := ('0', (others => '0'), std_ulogic_vector(resize(unsigned(insn_ui(insn_in)), 64)));
             when CONST_SI =>
                 ret := ('0', (others => '0'), std_ulogic_vector(resize(signed(insn_si(insn_in)), 64)));
+            when CONST_PSI =>
+                ret := ('0', (others => '0'), std_ulogic_vector(resize(signed(insn_prefixed_si(prefix, insn_in)), 64)));
             when CONST_SI_HI =>
                 ret := ('0', (others => '0'), std_ulogic_vector(resize(signed(insn_si(insn_in)) & x"0000", 64)));
             when CONST_UI_HI =>
@@ -373,8 +377,8 @@ begin
         decoded_reg_c <= decode_input_reg_init;
         decoded_reg_o <= decode_output_reg_init;
         if d_in.valid = '1' then
-            decoded_reg_a <= decode_input_reg_a (d_in.decode.input_reg_a, d_in.insn, d_in.nia);
-            decoded_reg_b <= decode_input_reg_b (d_in.decode.input_reg_b, d_in.insn);
+            decoded_reg_a <= decode_input_reg_a (d_in.decode.input_reg_a, d_in.insn, d_in.prefix, d_in.nia);
+            decoded_reg_b <= decode_input_reg_b (d_in.decode.input_reg_b, d_in.insn, d_in.prefix);
             decoded_reg_c <= decode_input_reg_c (d_in.decode.input_reg_c, d_in.insn);
             decoded_reg_o <= decode_output_reg (d_in.decode.output_reg_a, d_in.insn);
         end if;
index e9f6e70c35afd06511c7d1e366ecaf977d6ba2ff..428d943652787ed584248dc7e659432cebc9c84e 100644 (file)
@@ -34,15 +34,16 @@ package decode_types is
         -- The following instructions don't have an RB operand or access FPRs
         INSN_illegal, -- 0
         INSN_fetch_fail,
-        INSN_addi,
+        INSN_prefix,
+        INSN_pnop,
         INSN_addic,
         INSN_addic_dot,
         INSN_addis,
         INSN_addme,
         INSN_addpcis,
         INSN_addze,
-        INSN_andi_dot,
-        INSN_andis_dot, -- 10
+        INSN_andi_dot, -- 10
+        INSN_andis_dot,
         INSN_attn,
         INSN_b,
         INSN_bc,
@@ -51,8 +52,8 @@ package decode_types is
         INSN_bctar,
         INSN_cbcdtd,
         INSN_cdtbcd,
-        INSN_cmpi,
-        INSN_cmpli, -- 20
+        INSN_cmpi, -- 20
+        INSN_cmpli,
         INSN_cntlzw,
         INSN_cntlzd,
         INSN_cnttzw,
@@ -61,8 +62,8 @@ package decode_types is
         INSN_crandc,
         INSN_creqv,
         INSN_crnand,
-        INSN_crnor,
-        INSN_cror, -- 30
+        INSN_crnor, -- 30
+        INSN_cror,
         INSN_crorc,
         INSN_crxor,
         INSN_darn,
@@ -71,182 +72,203 @@ package decode_types is
         INSN_extsh,
         INSN_extsw,
         INSN_extswsli,
-        INSN_isync,
-        INSN_lbz, -- 40
+        INSN_isync, -- 40
         INSN_lbzu,
         INSN_ld,
         INSN_ldu,
-        INSN_lha,
         INSN_lhau,
-        INSN_lhz,
-        INSN_lhzu,
         INSN_lwa,
-        INSN_lwz,
-        INSN_lwzu, -- 50
+        INSN_lwzu,
         INSN_mcrf,
         INSN_mcrxrx,
         INSN_mfcr,
-        INSN_mfmsr,
+        INSN_mfmsr, -- 50
         INSN_mfspr,
         INSN_mtcrf,
         INSN_mtmsr,
         INSN_mtmsrd,
         INSN_mtspr,
-        INSN_mulli, -- 60
+        INSN_mulli,
         INSN_neg,
         INSN_nop,
         INSN_ori,
-        INSN_oris,
+        INSN_oris, -- 60
         INSN_popcntb,
         INSN_popcntw,
         INSN_popcntd,
         INSN_prtyw,
         INSN_prtyd,
-        INSN_rfid, -- 70
+        INSN_rfid,
         INSN_rldic,
         INSN_rldicl,
         INSN_rldicr,
-        INSN_rldimi,
+        INSN_rldimi, -- 70
         INSN_rlwimi,
         INSN_rlwinm,
         INSN_sc,
         INSN_setb,
         INSN_slbia,
-        INSN_sradi, -- 80
+        INSN_sradi,
         INSN_srawi,
-        INSN_stb,
         INSN_stbu,
         INSN_std,
-        INSN_stdu,
-        INSN_sth,
+        INSN_stdu, -- 80
         INSN_sthu,
-        INSN_stw,
         INSN_stwu,
-        INSN_subfic, -- 90
+        INSN_subfic,
         INSN_subfme,
         INSN_subfze,
         INSN_sync,
         INSN_tdi,
         INSN_tlbsync,
         INSN_twi,
-        INSN_wait,
+        INSN_wait, -- 90
         INSN_xori,
         INSN_xoris,
+        INSN_93, -- padding
+        INSN_94,
+        INSN_95,
+
+        -- Non-prefixed instructions that have a MLS:D prefixed form and
+        -- their corresponding prefixed instructions.
+        -- The non-prefixed versions have even indexes so that we can
+        -- convert them to the prefixed version by setting bit 0
+        INSN_addi, -- 96
+        INSN_paddi,
+        INSN_lbz,
+        INSN_plbz,
+        INSN_lha, -- 100
+        INSN_plha,
+        INSN_lhz,
+        INSN_plhz,
+        INSN_lwz,
+        INSN_plwz,
+        INSN_stb,
+        INSN_pstb,
+        INSN_sth,
+        INSN_psth,
+        INSN_stw, -- 110
+        INSN_pstw,
 
-        -- pad to 112 to simplify comparison logic
-        INSN_100, INSN_101, INSN_102, INSN_103,
-        INSN_104, INSN_105, INSN_106, INSN_107,
-        INSN_108, INSN_109, INSN_110, INSN_111,
+        -- Slots for non-prefixed opcodes that are 8LS:D when prefixed
+        INSN_lhzu, -- 112
+        INSN_plwa,
+        INSN_op57,
+        INSN_pld,
+        INSN_op61,
+        INSN_pstd,
+
+        -- pad to 128 to simplify comparison logic
+        INSN_076, INSN_077,
+        INSN_078, INSN_079, INSN_07a, INSN_07b, INSN_07c, INSN_07d, INSN_07e, INSN_07f,
 
         -- The following instructions have an RB operand but don't access FPRs
         INSN_add,
         INSN_addc,
-        INSN_adde,
+        INSN_adde, -- 130
         INSN_addex,
         INSN_addg6s,
         INSN_and,
         INSN_andc,
         INSN_bperm,
-        INSN_cmp, -- 120
+        INSN_cmp,
         INSN_cmpb,
         INSN_cmpeqb,
         INSN_cmpl,
-        INSN_cmprb,
+        INSN_cmprb, -- 140
         INSN_dcbf,
         INSN_dcbst,
         INSN_dcbt,
         INSN_dcbtst,
         INSN_dcbz,
-        INSN_divd, -- 130
+        INSN_divd,
         INSN_divdu,
         INSN_divde,
         INSN_divdeu,
-        INSN_divw,
+        INSN_divw, -- 150
         INSN_divwu,
         INSN_divwe,
         INSN_divweu,
         INSN_eqv,
         INSN_icbi,
-        INSN_icbt, -- 140
+        INSN_icbt,
         INSN_isel,
         INSN_lbarx,
         INSN_lbzcix,
-        INSN_lbzux,
+        INSN_lbzux, -- 160
         INSN_lbzx,
         INSN_ldarx,
         INSN_ldbrx,
         INSN_ldcix,
         INSN_ldx,
-        INSN_ldux, -- 150
+        INSN_ldux,
         INSN_lharx,
         INSN_lhax,
         INSN_lhaux,
-        INSN_lhbrx,
+        INSN_lhbrx, -- 170
         INSN_lhzcix,
         INSN_lhzx,
         INSN_lhzux,
         INSN_lwarx,
         INSN_lwax,
-        INSN_lwaux, -- 160
+        INSN_lwaux,
         INSN_lwbrx,
         INSN_lwzcix,
         INSN_lwzx,
-        INSN_lwzux,
+        INSN_lwzux, -- 180
         INSN_modsd,
         INSN_modsw,
         INSN_moduw,
         INSN_modud,
         INSN_mulhw,
-        INSN_mulhwu, -- 170
+        INSN_mulhwu,
         INSN_mulhd,
         INSN_mulhdu,
         INSN_mullw,
-        INSN_mulld,
+        INSN_mulld, -- 190
         INSN_nand,
         INSN_nor,
         INSN_or,
         INSN_orc,
         INSN_rldcl,
-        INSN_rldcr, -- 180
+        INSN_rldcr,
         INSN_rlwnm,
         INSN_slw,
         INSN_sld,
-        INSN_sraw,
+        INSN_sraw, -- 200
         INSN_srad,
         INSN_srw,
         INSN_srd,
         INSN_stbcix,
         INSN_stbcx,
-        INSN_stbx, -- 190
+        INSN_stbx,
         INSN_stbux,
         INSN_stdbrx,
         INSN_stdcix,
-        INSN_stdcx,
+        INSN_stdcx, -- 210
         INSN_stdx,
         INSN_stdux,
         INSN_sthbrx,
         INSN_sthcix,
         INSN_sthcx,
-        INSN_sthx, -- 200
+        INSN_sthx,
         INSN_sthux,
         INSN_stwbrx,
         INSN_stwcix,
-        INSN_stwcx,
+        INSN_stwcx, -- 220
         INSN_stwx,
         INSN_stwux,
         INSN_subf,
         INSN_subfc,
         INSN_subfe,
-        INSN_td, -- 210
+        INSN_td,
         INSN_tlbie,
         INSN_tlbiel,
         INSN_tw,
-        INSN_xor,
+        INSN_xor, -- 230
 
-        -- pad to 224 to simplify comparison logic
-        INSN_215,
-        INSN_216, INSN_217, INSN_218, INSN_219,
-        INSN_220, INSN_221, INSN_222, INSN_223,
+        -- pad to 232 to simplify comparison logic
+        INSN_231,
 
         -- The following instructions have a third input addressed by RC
         INSN_maddld,
@@ -254,9 +276,7 @@ package decode_types is
         INSN_maddhdu,
 
         -- pad to 256 to simplify comparison logic
-        INSN_227,
-        INSN_228, INSN_229, INSN_230, INSN_231,
-        INSN_232, INSN_233, INSN_234, INSN_235,
+        INSN_235,
         INSN_236, INSN_237, INSN_238, INSN_239,
         INSN_240, INSN_241, INSN_242, INSN_243,
         INSN_244, INSN_245, INSN_246, INSN_247,
@@ -264,39 +284,52 @@ package decode_types is
         INSN_252, INSN_253, INSN_254, INSN_255,
 
         -- The following instructions access floating-point registers
-        -- These ones have an FRS operand, but RA/RB are GPRs
-        INSN_stfd,
-        INSN_stfdu,
+        -- They have an FRS operand, but RA/RB are GPRs
+
+        -- Non-prefixed floating-point loads and stores that have a MLS:D
+        -- prefixed form, and their corresponding prefixed instructions.
+        INSN_stfd, -- 256
+        INSN_pstfd,
         INSN_stfs,
+        INSN_pstfs,
+        INSN_lfd, -- 260
+        INSN_plfd,
+        INSN_lfs,
+        INSN_plfs,
+
+        -- opcodes that can't have a prefix
+        INSN_stfdu, -- 264
         INSN_stfsu,
-        INSN_stfdux, -- 260
+        INSN_stfdux,
         INSN_stfdx,
         INSN_stfiwx,
         INSN_stfsux,
-        INSN_stfsx,
+        INSN_stfsx, -- 270
         -- These ones don't actually have an FRS operand (rather an FRT destination)
         -- but are here so that all FP instructions are >= INST_first_frs.
-        INSN_lfd,
         INSN_lfdu,
-        INSN_lfs,
         INSN_lfsu,
         INSN_lfdx,
-        INSN_lfdux, -- 270
+        INSN_lfdux,
         INSN_lfiwax,
         INSN_lfiwzx,
         INSN_lfsx,
         INSN_lfsux,
         -- These are here in order to keep the FP instructions together
         INSN_mcrfs,
-        INSN_mtfsb,
+        INSN_mtfsb, -- 280
         INSN_mtfsfi,
-        INSN_278, -- padding
-        INSN_279,
+        INSN_282, -- padding
+        INSN_283,
+        INSN_284,
+        INSN_285,
+        INSN_286,
+        INSN_287,
 
         -- The following instructions access FRA and/or FRB operands
-        INSN_fabs, -- 280
+        INSN_fabs, -- 288
         INSN_fadd,
-        INSN_fadds,
+        INSN_fadds, -- 290
         INSN_fcfid,
         INSN_fcfids,
         INSN_fcfidu,
@@ -304,9 +337,9 @@ package decode_types is
         INSN_fcmpo,
         INSN_fcmpu,
         INSN_fcpsgn,
-        INSN_fctid, -- 290
+        INSN_fctid,
         INSN_fctidz,
-        INSN_fctidu,
+        INSN_fctidu, -- 300
         INSN_fctiduz,
         INSN_fctiw,
         INSN_fctiwz,
@@ -314,9 +347,9 @@ package decode_types is
         INSN_fctiwuz,
         INSN_fdiv,
         INSN_fdivs,
-        INSN_fmr, -- 300
+        INSN_fmr,
         INSN_fmrgew,
-        INSN_fmrgow,
+        INSN_fmrgow, -- 310
         INSN_fnabs,
         INSN_fneg,
         INSN_fre,
@@ -324,9 +357,9 @@ package decode_types is
         INSN_frim,
         INSN_frin,
         INSN_frip,
-        INSN_friz, -- 310
+        INSN_friz,
         INSN_frsp,
-        INSN_frsqrte,
+        INSN_frsqrte, -- 320
         INSN_frsqrtes,
         INSN_fsqrt,
         INSN_fsqrts,
@@ -334,18 +367,18 @@ package decode_types is
         INSN_fsubs,
         INSN_ftdiv,
         INSN_ftsqrt,
-        INSN_mffs, -- 320
+        INSN_mffs,
         INSN_mtfsf,
 
-        -- pad to 328
-        INSN_322, INSN_323, INSN_324, INSN_325, INSN_326, INSN_327,
+        -- pad to 336
+        INSN_330, INSN_331, INSN_332, INSN_333, INSN_334, INSN_335,
 
         -- The following instructions access FRA, FRB (possibly) and FRC operands
-        INSN_fmul,
+        INSN_fmul, -- 336
         INSN_fmuls,
-        INSN_fmadd, -- 330
+        INSN_fmadd,
         INSN_fmadds,
-        INSN_fmsub,
+        INSN_fmsub, -- 340
         INSN_fmsubs,
         INSN_fnmadd,
         INSN_fnmadds,
@@ -359,10 +392,14 @@ package decode_types is
     constant INSN_first_frs : insn_code := INSN_stfd;
     constant INSN_first_frab : insn_code := INSN_fabs;
     constant INSN_first_frabc : insn_code := INSN_fmul;
+    constant INSN_first_mls : insn_code := INSN_addi;
+    constant INSN_first_8ls : insn_code := INSN_lhzu;
+    constant INSN_first_fp_mls : insn_code := INSN_stfd;
+    constant INSN_first_fp_nonmls : insn_code := INSN_stfdu;
 
-    type input_reg_a_t is (NONE, RA, RA_OR_ZERO, CIA, FRA);
+    type input_reg_a_t is (NONE, RA, RA_OR_ZERO, RA0_OR_CIA, CIA, FRA);
     type input_reg_b_t is (NONE, RB, CONST_UI, CONST_SI, CONST_SI_HI, CONST_UI_HI, CONST_LI, CONST_BD,
-                           CONST_DXHI4, CONST_DS, CONST_DQ, CONST_M1, CONST_SH, CONST_SH32, FRB);
+                           CONST_DXHI4, CONST_DS, CONST_DQ, CONST_M1, CONST_SH, CONST_SH32, CONST_PSI, FRB);
     type input_reg_c_t is (NONE, RS, RCR, FRC, FRS);
     type output_reg_a_t is (NONE, RT, RA, FRT);
     type rc_t is (NONE, ONE, RC, RCOE);
index 2ddcadb005fd393ec6f37234d2d9bf23f6030a83..acd75e97ae46c1ac7f252feab7a44c7fd4d90516 100644 (file)
@@ -43,6 +43,9 @@ package insn_helpers is
     function insn_frb (insn_in : std_ulogic_vector) return std_ulogic_vector;
     function insn_frc (insn_in : std_ulogic_vector) return std_ulogic_vector;
     function insn_u (insn_in : std_ulogic_vector) return std_ulogic_vector;
+    function insn_prefix_r(prefix : std_ulogic_vector) return std_ulogic;
+    function insn_prefixed_si(prefix : std_ulogic_vector; suffix : std_ulogic_vector)
+        return std_ulogic_vector;
 end package insn_helpers;
 
 package body insn_helpers is
@@ -250,4 +253,16 @@ package body insn_helpers is
     begin
         return insn_in(15 downto 12);
     end;
+
+    function insn_prefix_r(prefix : std_ulogic_vector) return std_ulogic is
+    begin
+        return prefix(20);
+    end;
+
+    function insn_prefixed_si(prefix : std_ulogic_vector; suffix : std_ulogic_vector)
+        return std_ulogic_vector is
+    begin
+        return prefix(17 downto 0) & suffix(15 downto 0);
+    end;
+
 end package body insn_helpers;
index 7e1149bfa5379b05c882e662e6e1a8a4ec7d0963..41b26ade867f99501fff7ef1cbe6f3f8f465d6ad 100644 (file)
@@ -158,6 +158,11 @@ architecture behaviour of predecoder is
         2#111111_11010# to 2#111111_11011# =>  INSN_fmadd,
         2#111111_11100# to 2#111111_11101# =>  INSN_fnmsub,
         2#111111_11110# to 2#111111_11111# =>  INSN_fnmadd,
+        -- prefix word, PO1
+        2#000001_00000# to 2#000001_11111# =>  INSN_prefix,
+        -- Major opcodes 57 and 61 are SFFS load/store instructions when prefixed
+        2#111001_00000# to 2#111001_11111# =>  INSN_op57,
+        2#111101_00000# to 2#111101_11111# =>  INSN_op61,
         others                             =>  INSN_illegal
         );