diff --git a/common.vhdl b/common.vhdl index 44302c7..838179b 100644 --- a/common.vhdl +++ b/common.vhdl @@ -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')); diff --git a/decode1.vhdl b/decode1.vhdl index c987bec..138e483 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -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; diff --git a/decode2.vhdl b/decode2.vhdl index f58bd9b..fa3b54d 100644 --- a/decode2.vhdl +++ b/decode2.vhdl @@ -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; diff --git a/decode_types.vhdl b/decode_types.vhdl index e9f6e70..428d943 100644 --- a/decode_types.vhdl +++ b/decode_types.vhdl @@ -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); diff --git a/insn_helpers.vhdl b/insn_helpers.vhdl index 2ddcadb..acd75e9 100644 --- a/insn_helpers.vhdl +++ b/insn_helpers.vhdl @@ -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; diff --git a/predecode.vhdl b/predecode.vhdl index 7e1149b..41b26ad 100644 --- a/predecode.vhdl +++ b/predecode.vhdl @@ -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 );