decode1: Divide insn_code values into ranges to indicate register usage

This lets us compute r_out.reg_*_addr and r_out.read_2_enable values
without needing access to the primary opcode value.  We also have that
non-FP instructions are < 256.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/382/head
Paul Mackerras 2 years ago
parent c3ee10f013
commit c9aea45ffe

@ -39,10 +39,6 @@ architecture behaviour of decode1 is
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,
@ -792,7 +788,9 @@ architecture behaviour of decode1 is
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
@ -959,22 +957,11 @@ begin
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
@ -990,8 +977,9 @@ begin
-- 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));

@ -1002,35 +990,26 @@ begin
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 =>
@ -1097,6 +1076,7 @@ begin
variable vr : Decode1ToRegisterFileType;
variable icode : insn_code;
variable sprn : spr_num_t;
variable maybe_rb : std_ulogic;
begin
v := Decode1ToDecode2Init;

@ -1124,15 +1104,32 @@ begin
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;

@ -25,14 +25,15 @@ package decode_types is
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,
@ -40,8 +41,6 @@ package decode_types is
INSN_addme,
INSN_addpcis,
INSN_addze,
INSN_and,
INSN_andc,
INSN_andi_dot,
INSN_andis_dot,
INSN_attn,
@ -50,20 +49,14 @@ package decode_types is
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,
@ -73,242 +66,298 @@ package decode_types is
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);

Loading…
Cancel
Save