From c9aea45ffe8188579fd1f4686a3d80bba29fa827 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 28 Jul 2022 19:00:04 +1000 Subject: [PATCH] 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 --- decode1.vhdl | 85 +++++----- decode_types.vhdl | 401 ++++++++++++++++++++++++++-------------------- 2 files changed, 266 insertions(+), 220 deletions(-) diff --git a/decode1.vhdl b/decode1.vhdl index 9dd57d9..98c5b80 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -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; diff --git a/decode_types.vhdl b/decode_types.vhdl index 443d093..dd2781e 100644 --- a/decode_types.vhdl +++ b/decode_types.vhdl @@ -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);