ov_insn : insn_code;
spr_info : spr_id;
ram_spr : ram_spr_info;
- fprs : std_ulogic;
- fprabc : std_ulogic;
- in3rc : std_ulogic;
- maybe_rb : std_ulogic;
end record;
constant dc0_t_init : dc0_t :=
(f_in => IcacheToDecode1Init, ov_insn => INSN_illegal,
INSN_wait => (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_xor => (ALU, NONE, OP_XOR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE),
INSN_xori => (ALU, NONE, OP_XOR, NONE, CONST_UI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
- INSN_xoris => (ALU, NONE, OP_XOR, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE)
+ INSN_xoris => (ALU, NONE, OP_XOR, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
+
+ others => (NONE, NONE, OP_ILLEGAL, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE)
);
function decode_ram_spr(sprn : spr_num_t) return ram_spr_info is
when "000100" => -- 4
-- major opcode 4, mostly VMX/VSX stuff but also some integer ops (madd*)
v.override := not f_in.insn(5);
- v.in3rc := '1';
- v.maybe_rb := '1';
-
- when "010111" => -- 23
- -- rlwnm[.]
- v.maybe_rb := '1';
when "011111" => -- 31
-- major opcode 31, lots of things
+ -- Use the first half of the row table for all columns
v.use_row := '1';
- v.maybe_rb := '1';
-
- if HAS_FPU and std_match(f_in.insn(10 downto 1), "1----10111") then
- -- lower half of column 23 has FP loads and stores
- v.fprs := '1';
- end if;
when "010000" => -- 16
-- Predict backward branches as taken, forward as untaken
-- Columns 8-15 and 24-31 don't have any valid instructions
-- (where insn(5..1) is the column number).
-- addpcis (column 2) is in the major table
- -- Use the row table for columns 0-1 and 16-23 (mapped to 8-15)
- -- Columns 4-7 in the row table are used for op 59 cols 12-15
+ -- Other valid columns are mapped to columns in the second
+ -- half of the row table: columns 0-1 are mapped to 16-17
+ -- and 16-23 are mapped to 24-31.
v.override := f_in.insn(4);
v.use_row := f_in.insn(5) or (not f_in.insn(3) and not f_in.insn(2));
v.ov_insn := INSN_nop;
end if;
- when "011110" => -- 30
- v.maybe_rb := f_in.insn(4);
-
- when "110100" | "110101" | "110110" | "110111" => -- 52, 53, 54, 55
- -- stfd[u] and stfs[u]
- if HAS_FPU then
- v.fprs := '1';
- end if;
-
when "111011" => -- 59
if HAS_FPU then
-- floating point operations, mostly single-precision
- -- Use row table for columns 12-15, major table for 16-31
+ -- Columns 0-11 are illegal; columns 12-15 are mapped
+ -- to columns 20-23 in the second half of the row table,
+ -- and columns 16-31 are in the major table.
v.override := not f_in.insn(5) and (not f_in.insn(4) or not f_in.insn(3));
v.use_row := not f_in.insn(5);
- v.in3rc := '1';
- v.fprabc := '1';
- v.fprs := '1';
- v.maybe_rb := '1';
+ else
+ v.override := '1';
end if;
when "111111" => -- 63
if HAS_FPU then
-- floating point operations, general and double-precision
+ -- Use columns 0-15 of the second half of the row table
+ -- for columns 0-15, and the major table for columns 16-31.
v.use_row := not f_in.insn(5);
- v.in3rc := '1';
- v.fprabc := '1';
- v.fprs := '1';
- v.maybe_rb := '1';
+ else
+ v.override := '1';
end if;
when others =>
variable vr : Decode1ToRegisterFileType;
variable icode : insn_code;
variable sprn : spr_num_t;
+ variable maybe_rb : std_ulogic;
begin
v := Decode1ToDecode2Init;
end if;
-- Work out GPR/FPR read addresses
- vr.reg_1_addr := dc0.fprabc & insn_ra(dc0.f_in.insn);
- vr.reg_2_addr := dc0.fprabc & insn_rb(dc0.f_in.insn);
- if dc0.in3rc = '1' then
- vr.reg_3_addr := dc0.fprabc & insn_rcreg(dc0.f_in.insn);
- else
- vr.reg_3_addr := dc0.fprs & insn_rs(dc0.f_in.insn);
+ maybe_rb := '0';
+ vr.reg_1_addr := '0' & insn_ra(dc0.f_in.insn);
+ vr.reg_2_addr := '0' & insn_rb(dc0.f_in.insn);
+ vr.reg_3_addr := '0' & insn_rs(dc0.f_in.insn);
+ if icode >= INSN_first_rb then
+ maybe_rb := '1';
+ if icode < INSN_first_frs then
+ if icode >= INSN_first_rc then
+ vr.reg_3_addr := '0' & insn_rcreg(dc0.f_in.insn);
+ end if;
+ else
+ -- access FRS operand
+ vr.reg_3_addr(5) := '1';
+ if icode >= INSN_first_frab then
+ -- access FRA and/or FRB operands
+ vr.reg_1_addr(5) := '1';
+ vr.reg_2_addr(5) := '1';
+ end if;
+ if icode >= INSN_first_frabc then
+ -- access FRC operand
+ vr.reg_3_addr := '1' & insn_rcreg(dc0.f_in.insn);
+ end if;
+ end if;
end if;
vr.read_1_enable := dc0.f_in.valid and not dc0.f_in.fetch_failed;
- vr.read_2_enable := dc0.f_in.valid and not dc0.f_in.fetch_failed and dc0.maybe_rb;
+ vr.read_2_enable := dc0.f_in.valid and not dc0.f_in.fetch_failed and maybe_rb;
vr.read_3_enable := dc0.f_in.valid and not dc0.f_in.fetch_failed;
v.reg_a := vr.reg_1_addr;
OP_FETCH_FAILED
);
+ -- The following list is ordered in such a way that we can know some
+ -- things about which registers are accessed by an instruction by its place
+ -- in the list. In other words we can decide whether an instruction
+ -- accesses FPRs and whether it has an RB operand by doing simple
+ -- comparisons of the insn_code for the instruction with a few constants.
type insn_code is (
+ -- The following instructions don't have an RB operand or access FPRs
INSN_illegal,
INSN_fetch_fail,
- INSN_add,
- INSN_addc,
- INSN_adde,
- INSN_addex,
- INSN_addg6s,
INSN_addi,
INSN_addic,
INSN_addic_dot,
INSN_addme,
INSN_addpcis,
INSN_addze,
- INSN_and,
- INSN_andc,
INSN_andi_dot,
INSN_andis_dot,
INSN_attn,
INSN_bcctr,
INSN_bclr,
INSN_bctar,
- INSN_bperm,
INSN_cbcdtd,
INSN_cdtbcd,
- INSN_cmp,
- INSN_cmpb,
- INSN_cmpeqb,
INSN_cmpi,
- INSN_cmpl,
INSN_cmpli,
- INSN_cmprb,
- INSN_cntlzd,
INSN_cntlzw,
- INSN_cnttzd,
+ INSN_cntlzd,
INSN_cnttzw,
+ INSN_cnttzd,
INSN_crand,
INSN_crandc,
INSN_creqv,
INSN_crorc,
INSN_crxor,
INSN_darn,
- INSN_dcbf,
- INSN_dcbst,
- INSN_dcbt,
- INSN_dcbtst,
- INSN_dcbz,
- INSN_divd,
- INSN_divde,
- INSN_divdeu,
- INSN_divdu,
- INSN_divw,
- INSN_divwe,
- INSN_divweu,
- INSN_divwu,
INSN_eieio,
- INSN_eqv,
INSN_extsb,
INSN_extsh,
INSN_extsw,
INSN_extswsli,
- INSN_fabs,
- INSN_fadd,
- INSN_fadds,
- INSN_fcfid,
- INSN_fcfids,
- INSN_fcfidu,
- INSN_fcfidus,
- INSN_fcmpo,
- INSN_fcmpu,
- INSN_fcpsgn,
- INSN_fctid,
- INSN_fctidu,
- INSN_fctiduz,
- INSN_fctidz,
- INSN_fctiw,
- INSN_fctiwu,
- INSN_fctiwuz,
- INSN_fctiwz,
- INSN_fdiv,
- INSN_fdivs,
- INSN_fmadd,
- INSN_fmadds,
- INSN_fmr,
- INSN_fmrgew,
- INSN_fmrgow,
- INSN_fmsub,
- INSN_fmsubs,
- INSN_fmul,
- INSN_fmuls,
- INSN_fnabs,
- INSN_fneg,
- INSN_fnmadd,
- INSN_fnmadds,
- INSN_fnmsub,
- INSN_fnmsubs,
- INSN_fre,
- INSN_fres,
- INSN_frim,
- INSN_frin,
- INSN_frip,
- INSN_friz,
- INSN_frsp,
- INSN_frsqrte,
- INSN_frsqrtes,
- INSN_fsel,
- INSN_fsqrt,
- INSN_fsqrts,
- INSN_fsub,
- INSN_fsubs,
- INSN_ftdiv,
- INSN_ftsqrt,
- INSN_icbi,
- INSN_icbt,
- INSN_isel,
INSN_isync,
- INSN_lbarx,
INSN_lbz,
- INSN_lbzcix,
INSN_lbzu,
- INSN_lbzux,
- INSN_lbzx,
INSN_ld,
- INSN_ldarx,
- INSN_ldbrx,
- INSN_ldcix,
INSN_ldu,
- INSN_ldux,
- INSN_ldx,
- INSN_lfd,
- INSN_lfdu,
- INSN_lfdux,
- INSN_lfdx,
- INSN_lfiwax,
- INSN_lfiwzx,
- INSN_lfs,
- INSN_lfsu,
- INSN_lfsux,
- INSN_lfsx,
INSN_lha,
- INSN_lharx,
INSN_lhau,
- INSN_lhaux,
- INSN_lhax,
- INSN_lhbrx,
INSN_lhz,
- INSN_lhzcix,
INSN_lhzu,
- INSN_lhzux,
- INSN_lhzx,
INSN_lwa,
- INSN_lwarx,
- INSN_lwaux,
- INSN_lwax,
- INSN_lwbrx,
INSN_lwz,
- INSN_lwzcix,
INSN_lwzu,
- INSN_lwzux,
- INSN_lwzx,
- INSN_maddhd,
- INSN_maddhdu,
- INSN_maddld,
INSN_mcrf,
INSN_mcrfs,
INSN_mcrxrx,
INSN_mfcr,
- INSN_mffs,
INSN_mfmsr,
INSN_mfspr,
- INSN_modsd,
- INSN_modsw,
- INSN_modud,
- INSN_moduw,
INSN_mtcrf,
INSN_mtfsb,
- INSN_mtfsf,
INSN_mtfsfi,
INSN_mtmsr,
INSN_mtmsrd,
INSN_mtspr,
- INSN_mulhd,
- INSN_mulhdu,
- INSN_mulhw,
- INSN_mulhwu,
- INSN_mulld,
INSN_mulli,
- INSN_mullw,
- INSN_nand,
INSN_neg,
INSN_nop,
- INSN_nor,
- INSN_or,
- INSN_orc,
INSN_ori,
INSN_oris,
INSN_popcntb,
- INSN_popcntd,
INSN_popcntw,
- INSN_prtyd,
+ INSN_popcntd,
INSN_prtyw,
+ INSN_prtyd,
INSN_rfid,
- INSN_rldcl,
- INSN_rldcr,
INSN_rldic,
INSN_rldicl,
INSN_rldicr,
INSN_rldimi,
INSN_rlwimi,
INSN_rlwinm,
- INSN_rlwnm,
INSN_sc,
INSN_setb,
INSN_slbia,
- INSN_sld,
- INSN_slw,
- INSN_srad,
INSN_sradi,
- INSN_sraw,
INSN_srawi,
- INSN_srd,
- INSN_srw,
INSN_stb,
+ INSN_stbu,
+ INSN_std,
+ INSN_stdu,
+ INSN_sth,
+ INSN_sthu,
+ INSN_stw,
+ INSN_stwu,
+ INSN_subfic,
+ INSN_subfme,
+ INSN_subfze,
+ INSN_sync,
+ INSN_tdi,
+ INSN_tlbsync,
+ INSN_twi,
+ INSN_wait,
+ INSN_xori,
+ INSN_xoris,
+
+ -- pad to 112 to simplify comparison logic
+ INSN_103,
+ INSN_104, INSN_105, INSN_106, INSN_107,
+ INSN_108, INSN_109, INSN_110, INSN_111,
+
+ -- The following instructions have an RB operand but don't access FPRs
+ INSN_add,
+ INSN_addc,
+ INSN_adde,
+ INSN_addex,
+ INSN_addg6s,
+ INSN_and,
+ INSN_andc,
+ INSN_bperm,
+ INSN_cmp,
+ INSN_cmpb,
+ INSN_cmpeqb,
+ INSN_cmpl,
+ INSN_cmprb,
+ INSN_dcbf,
+ INSN_dcbst,
+ INSN_dcbt,
+ INSN_dcbtst,
+ INSN_dcbz,
+ INSN_divd,
+ INSN_divdu,
+ INSN_divde,
+ INSN_divdeu,
+ INSN_divw,
+ INSN_divwu,
+ INSN_divwe,
+ INSN_divweu,
+ INSN_eqv,
+ INSN_icbi,
+ INSN_icbt,
+ INSN_isel,
+ INSN_lbarx,
+ INSN_lbzcix,
+ INSN_lbzux,
+ INSN_lbzx,
+ INSN_ldarx,
+ INSN_ldbrx,
+ INSN_ldcix,
+ INSN_ldx,
+ INSN_ldux,
+ INSN_lharx,
+ INSN_lhax,
+ INSN_lhaux,
+ INSN_lhbrx,
+ INSN_lhzcix,
+ INSN_lhzx,
+ INSN_lhzux,
+ INSN_lwarx,
+ INSN_lwax,
+ INSN_lwaux,
+ INSN_lwbrx,
+ INSN_lwzcix,
+ INSN_lwzx,
+ INSN_lwzux,
+ INSN_modsd,
+ INSN_modsw,
+ INSN_moduw,
+ INSN_modud,
+ INSN_mulhw,
+ INSN_mulhwu,
+ INSN_mulhd,
+ INSN_mulhdu,
+ INSN_mullw,
+ INSN_mulld,
+ INSN_nand,
+ INSN_nor,
+ INSN_or,
+ INSN_orc,
+ INSN_rldcl,
+ INSN_rldcr,
+ INSN_rlwnm,
+ INSN_slw,
+ INSN_sld,
+ INSN_sraw,
+ INSN_srad,
+ INSN_srw,
+ INSN_srd,
INSN_stbcix,
INSN_stbcx,
- INSN_stbu,
- INSN_stbux,
INSN_stbx,
- INSN_std,
+ INSN_stbux,
INSN_stdbrx,
INSN_stdcix,
INSN_stdcx,
- INSN_stdu,
- INSN_stdux,
INSN_stdx,
- INSN_stfd,
- INSN_stfdu,
- INSN_stfdux,
- INSN_stfdx,
- INSN_stfiwx,
- INSN_stfs,
- INSN_stfsu,
- INSN_stfsux,
- INSN_stfsx,
- INSN_sth,
+ INSN_stdux,
INSN_sthbrx,
INSN_sthcix,
INSN_sthcx,
- INSN_sthu,
- INSN_sthux,
INSN_sthx,
- INSN_stw,
+ INSN_sthux,
INSN_stwbrx,
INSN_stwcix,
INSN_stwcx,
- INSN_stwu,
- INSN_stwux,
INSN_stwx,
+ INSN_stwux,
INSN_subf,
INSN_subfc,
INSN_subfe,
- INSN_subfic,
- INSN_subfme,
- INSN_subfze,
- INSN_sync,
INSN_td,
- INSN_tdi,
INSN_tlbie,
INSN_tlbiel,
- INSN_tlbsync,
INSN_tw,
- INSN_twi,
- INSN_wait,
INSN_xor,
- INSN_xori,
- INSN_xoris
+
+ -- 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,
+
+ -- The following instructions have a third input addressed by RC
+ INSN_maddld,
+ INSN_maddhd,
+ 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_236, INSN_237, INSN_238, INSN_239,
+ INSN_240, INSN_241, INSN_242, INSN_243,
+ INSN_244, INSN_245, INSN_246, INSN_247,
+ INSN_248, INSN_249, INSN_250, INSN_251,
+ 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,
+ INSN_stfs,
+ INSN_stfsu,
+ INSN_stfdux,
+ INSN_stfdx,
+ INSN_stfiwx,
+ INSN_stfsux,
+ INSN_stfsx,
+ -- 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,
+ INSN_lfiwax,
+ INSN_lfiwzx,
+ INSN_lfsx,
+ INSN_lfsux,
+ INSN_275, -- padding
+
+ -- The following instructions access FRA and/or FRB operands
+ INSN_fabs,
+ INSN_fadd,
+ INSN_fadds,
+ INSN_fcfid,
+ INSN_fcfids,
+ INSN_fcfidu,
+ INSN_fcfidus,
+ INSN_fcmpo,
+ INSN_fcmpu,
+ INSN_fcpsgn,
+ INSN_fctid,
+ INSN_fctidz,
+ INSN_fctidu,
+ INSN_fctiduz,
+ INSN_fctiw,
+ INSN_fctiwz,
+ INSN_fctiwu,
+ INSN_fctiwuz,
+ INSN_fdiv,
+ INSN_fdivs,
+ INSN_fmr,
+ INSN_fmrgew,
+ INSN_fmrgow,
+ INSN_fnabs,
+ INSN_fneg,
+ INSN_fre,
+ INSN_fres,
+ INSN_frim,
+ INSN_frin,
+ INSN_frip,
+ INSN_friz,
+ INSN_frsp,
+ INSN_frsqrte,
+ INSN_frsqrtes,
+ INSN_fsqrt,
+ INSN_fsqrts,
+ INSN_fsub,
+ INSN_fsubs,
+ INSN_ftdiv,
+ INSN_ftsqrt,
+ INSN_mffs,
+ INSN_mtfsf,
+
+ -- pad to 320
+ INSN_318, INSN_319,
+
+ -- The following instructions access FRA, FRB (possibly) and FRC operands
+ INSN_fmul,
+ INSN_fmuls,
+ INSN_fmadd,
+ INSN_fmadds,
+ INSN_fmsub,
+ INSN_fmsubs,
+ INSN_fnmadd,
+ INSN_fnmadds,
+ INSN_fnmsub,
+ INSN_fnmsubs,
+ INSN_fsel
);
+ constant INSN_first_rb : insn_code := INSN_add;
+ constant INSN_first_rc : insn_code := INSN_maddld;
+ constant INSN_first_frs : insn_code := INSN_stfd;
+ constant INSN_first_frab : insn_code := INSN_fabs;
+ constant INSN_first_frabc : insn_code := INSN_fmul;
+
type input_reg_a_t is (NONE, RA, RA_OR_ZERO, 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);