mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-13 15:18:09 +00:00
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>
480 lines
12 KiB
VHDL
480 lines
12 KiB
VHDL
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
|
|
package decode_types is
|
|
type insn_type_t is (OP_ILLEGAL, OP_NOP, OP_ADD,
|
|
OP_AND, OP_ATTN, OP_B, OP_BC, OP_BCREG,
|
|
OP_BCD, OP_BPERM, OP_CMP, OP_CMPB, OP_CMPEQB, OP_CMPRB,
|
|
OP_CNTZ, OP_CROP,
|
|
OP_DARN, OP_DCBF, OP_DCBST, OP_DCBT, OP_DCBTST,
|
|
OP_DCBZ, OP_ICBI, OP_ICBT,
|
|
OP_FP_CMP, OP_FP_ARITH, OP_FP_MOVE, OP_FP_MISC,
|
|
OP_DIV, OP_DIVE, OP_MOD,
|
|
OP_EXTS, OP_EXTSWSLI,
|
|
OP_ISEL, OP_ISYNC,
|
|
OP_LOAD, OP_STORE,
|
|
OP_MCRXRX, OP_MFCR, OP_MFMSR, OP_MFSPR,
|
|
OP_MTCRF, OP_MTMSRD, OP_MTSPR, OP_MUL_L64,
|
|
OP_MUL_H64, OP_MUL_H32, OP_OR,
|
|
OP_POPCNT, OP_PRTY, OP_RFID,
|
|
OP_RLC, OP_RLCL, OP_RLCR, OP_SC, OP_SETB,
|
|
OP_SHL, OP_SHR,
|
|
OP_SYNC, OP_TLBIE, OP_TRAP,
|
|
OP_XOR,
|
|
OP_ADDG6S,
|
|
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, -- 0
|
|
INSN_fetch_fail,
|
|
INSN_prefix,
|
|
INSN_pnop,
|
|
INSN_addic,
|
|
INSN_addic_dot,
|
|
INSN_addis,
|
|
INSN_addme,
|
|
INSN_addpcis,
|
|
INSN_addze,
|
|
INSN_andi_dot, -- 10
|
|
INSN_andis_dot,
|
|
INSN_attn,
|
|
INSN_b,
|
|
INSN_bc,
|
|
INSN_bcctr,
|
|
INSN_bclr,
|
|
INSN_bctar,
|
|
INSN_cbcdtd,
|
|
INSN_cdtbcd,
|
|
INSN_cmpi, -- 20
|
|
INSN_cmpli,
|
|
INSN_cntlzw,
|
|
INSN_cntlzd,
|
|
INSN_cnttzw,
|
|
INSN_cnttzd,
|
|
INSN_crand,
|
|
INSN_crandc,
|
|
INSN_creqv,
|
|
INSN_crnand,
|
|
INSN_crnor, -- 30
|
|
INSN_cror,
|
|
INSN_crorc,
|
|
INSN_crxor,
|
|
INSN_darn,
|
|
INSN_eieio,
|
|
INSN_extsb,
|
|
INSN_extsh,
|
|
INSN_extsw,
|
|
INSN_extswsli,
|
|
INSN_isync, -- 40
|
|
INSN_lbzu,
|
|
INSN_ld,
|
|
INSN_ldu,
|
|
INSN_lhau,
|
|
INSN_lwa,
|
|
INSN_lwzu,
|
|
INSN_mcrf,
|
|
INSN_mcrxrx,
|
|
INSN_mfcr,
|
|
INSN_mfmsr, -- 50
|
|
INSN_mfspr,
|
|
INSN_mtcrf,
|
|
INSN_mtmsr,
|
|
INSN_mtmsrd,
|
|
INSN_mtspr,
|
|
INSN_mulli,
|
|
INSN_neg,
|
|
INSN_nop,
|
|
INSN_ori,
|
|
INSN_oris, -- 60
|
|
INSN_popcntb,
|
|
INSN_popcntw,
|
|
INSN_popcntd,
|
|
INSN_prtyw,
|
|
INSN_prtyd,
|
|
INSN_rfid,
|
|
INSN_rldic,
|
|
INSN_rldicl,
|
|
INSN_rldicr,
|
|
INSN_rldimi, -- 70
|
|
INSN_rlwimi,
|
|
INSN_rlwinm,
|
|
INSN_sc,
|
|
INSN_setb,
|
|
INSN_slbia,
|
|
INSN_sradi,
|
|
INSN_srawi,
|
|
INSN_stbu,
|
|
INSN_std,
|
|
INSN_stdu, -- 80
|
|
INSN_sthu,
|
|
INSN_stwu,
|
|
INSN_subfic,
|
|
INSN_subfme,
|
|
INSN_subfze,
|
|
INSN_sync,
|
|
INSN_tdi,
|
|
INSN_tlbsync,
|
|
INSN_twi,
|
|
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,
|
|
|
|
-- 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, -- 130
|
|
INSN_addex,
|
|
INSN_addg6s,
|
|
INSN_and,
|
|
INSN_andc,
|
|
INSN_bperm,
|
|
INSN_cmp,
|
|
INSN_cmpb,
|
|
INSN_cmpeqb,
|
|
INSN_cmpl,
|
|
INSN_cmprb, -- 140
|
|
INSN_dcbf,
|
|
INSN_dcbst,
|
|
INSN_dcbt,
|
|
INSN_dcbtst,
|
|
INSN_dcbz,
|
|
INSN_divd,
|
|
INSN_divdu,
|
|
INSN_divde,
|
|
INSN_divdeu,
|
|
INSN_divw, -- 150
|
|
INSN_divwu,
|
|
INSN_divwe,
|
|
INSN_divweu,
|
|
INSN_eqv,
|
|
INSN_icbi,
|
|
INSN_icbt,
|
|
INSN_isel,
|
|
INSN_lbarx,
|
|
INSN_lbzcix,
|
|
INSN_lbzux, -- 160
|
|
INSN_lbzx,
|
|
INSN_ldarx,
|
|
INSN_ldbrx,
|
|
INSN_ldcix,
|
|
INSN_ldx,
|
|
INSN_ldux,
|
|
INSN_lharx,
|
|
INSN_lhax,
|
|
INSN_lhaux,
|
|
INSN_lhbrx, -- 170
|
|
INSN_lhzcix,
|
|
INSN_lhzx,
|
|
INSN_lhzux,
|
|
INSN_lwarx,
|
|
INSN_lwax,
|
|
INSN_lwaux,
|
|
INSN_lwbrx,
|
|
INSN_lwzcix,
|
|
INSN_lwzx,
|
|
INSN_lwzux, -- 180
|
|
INSN_modsd,
|
|
INSN_modsw,
|
|
INSN_moduw,
|
|
INSN_modud,
|
|
INSN_mulhw,
|
|
INSN_mulhwu,
|
|
INSN_mulhd,
|
|
INSN_mulhdu,
|
|
INSN_mullw,
|
|
INSN_mulld, -- 190
|
|
INSN_nand,
|
|
INSN_nor,
|
|
INSN_or,
|
|
INSN_orc,
|
|
INSN_rldcl,
|
|
INSN_rldcr,
|
|
INSN_rlwnm,
|
|
INSN_slw,
|
|
INSN_sld,
|
|
INSN_sraw, -- 200
|
|
INSN_srad,
|
|
INSN_srw,
|
|
INSN_srd,
|
|
INSN_stbcix,
|
|
INSN_stbcx,
|
|
INSN_stbx,
|
|
INSN_stbux,
|
|
INSN_stdbrx,
|
|
INSN_stdcix,
|
|
INSN_stdcx, -- 210
|
|
INSN_stdx,
|
|
INSN_stdux,
|
|
INSN_sthbrx,
|
|
INSN_sthcix,
|
|
INSN_sthcx,
|
|
INSN_sthx,
|
|
INSN_sthux,
|
|
INSN_stwbrx,
|
|
INSN_stwcix,
|
|
INSN_stwcx, -- 220
|
|
INSN_stwx,
|
|
INSN_stwux,
|
|
INSN_subf,
|
|
INSN_subfc,
|
|
INSN_subfe,
|
|
INSN_td,
|
|
INSN_tlbie,
|
|
INSN_tlbiel,
|
|
INSN_tw,
|
|
INSN_xor, -- 230
|
|
|
|
-- pad to 232 to simplify comparison logic
|
|
INSN_231,
|
|
|
|
-- The following instructions have a third input addressed by RC
|
|
INSN_maddld,
|
|
INSN_maddhd,
|
|
INSN_maddhdu,
|
|
|
|
-- pad to 256 to simplify comparison logic
|
|
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
|
|
-- 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,
|
|
INSN_stfdx,
|
|
INSN_stfiwx,
|
|
INSN_stfsux,
|
|
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_lfdu,
|
|
INSN_lfsu,
|
|
INSN_lfdx,
|
|
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, -- 280
|
|
INSN_mtfsfi,
|
|
INSN_282, -- padding
|
|
INSN_283,
|
|
INSN_284,
|
|
INSN_285,
|
|
INSN_286,
|
|
INSN_287,
|
|
|
|
-- The following instructions access FRA and/or FRB operands
|
|
INSN_fabs, -- 288
|
|
INSN_fadd,
|
|
INSN_fadds, -- 290
|
|
INSN_fcfid,
|
|
INSN_fcfids,
|
|
INSN_fcfidu,
|
|
INSN_fcfidus,
|
|
INSN_fcmpo,
|
|
INSN_fcmpu,
|
|
INSN_fcpsgn,
|
|
INSN_fctid,
|
|
INSN_fctidz,
|
|
INSN_fctidu, -- 300
|
|
INSN_fctiduz,
|
|
INSN_fctiw,
|
|
INSN_fctiwz,
|
|
INSN_fctiwu,
|
|
INSN_fctiwuz,
|
|
INSN_fdiv,
|
|
INSN_fdivs,
|
|
INSN_fmr,
|
|
INSN_fmrgew,
|
|
INSN_fmrgow, -- 310
|
|
INSN_fnabs,
|
|
INSN_fneg,
|
|
INSN_fre,
|
|
INSN_fres,
|
|
INSN_frim,
|
|
INSN_frin,
|
|
INSN_frip,
|
|
INSN_friz,
|
|
INSN_frsp,
|
|
INSN_frsqrte, -- 320
|
|
INSN_frsqrtes,
|
|
INSN_fsqrt,
|
|
INSN_fsqrts,
|
|
INSN_fsub,
|
|
INSN_fsubs,
|
|
INSN_ftdiv,
|
|
INSN_ftsqrt,
|
|
INSN_mffs,
|
|
INSN_mtfsf,
|
|
|
|
-- 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, -- 336
|
|
INSN_fmuls,
|
|
INSN_fmadd,
|
|
INSN_fmadds,
|
|
INSN_fmsub, -- 340
|
|
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;
|
|
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, 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, 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);
|
|
type carry_in_t is (ZERO, CA, OV, ONE);
|
|
|
|
constant SH_OFFSET : integer := 0;
|
|
constant MB_OFFSET : integer := 1;
|
|
constant ME_OFFSET : integer := 1;
|
|
constant SH32_OFFSET : integer := 0;
|
|
constant MB32_OFFSET : integer := 1;
|
|
constant ME32_OFFSET : integer := 2;
|
|
|
|
constant FXM_OFFSET : integer := 0;
|
|
|
|
constant BO_OFFSET : integer := 0;
|
|
constant BI_OFFSET : integer := 1;
|
|
constant BH_OFFSET : integer := 2;
|
|
|
|
constant BF_OFFSET : integer := 0;
|
|
constant L_OFFSET : integer := 1;
|
|
|
|
constant TOO_OFFSET : integer := 0;
|
|
|
|
type unit_t is (ALU, LDST, FPU);
|
|
type facility_t is (NONE, FPU);
|
|
type length_t is (NONE, is1B, is2B, is4B, is8B);
|
|
|
|
type repeat_t is (NONE, -- instruction is not repeated
|
|
DUPD); -- update-form load
|
|
|
|
type decode_rom_t is record
|
|
unit : unit_t;
|
|
facility : facility_t;
|
|
insn_type : insn_type_t;
|
|
input_reg_a : input_reg_a_t;
|
|
input_reg_b : input_reg_b_t;
|
|
input_reg_c : input_reg_c_t;
|
|
output_reg_a : output_reg_a_t;
|
|
|
|
input_cr : std_ulogic;
|
|
output_cr : std_ulogic;
|
|
|
|
invert_a : std_ulogic;
|
|
invert_out : std_ulogic;
|
|
input_carry : carry_in_t;
|
|
output_carry : std_ulogic;
|
|
|
|
-- load/store signals
|
|
length : length_t;
|
|
byte_reverse : std_ulogic;
|
|
sign_extend : std_ulogic;
|
|
update : std_ulogic;
|
|
reserve : std_ulogic;
|
|
|
|
-- multiplier and ALU signals
|
|
is_32bit : std_ulogic;
|
|
is_signed : std_ulogic;
|
|
|
|
rc : rc_t;
|
|
lr : std_ulogic;
|
|
|
|
sgl_pipe : std_ulogic;
|
|
repeat : repeat_t;
|
|
end record;
|
|
constant decode_rom_init : decode_rom_t := (unit => ALU, facility => NONE,
|
|
insn_type => OP_ILLEGAL, input_reg_a => NONE,
|
|
input_reg_b => NONE, input_reg_c => NONE,
|
|
output_reg_a => NONE, input_cr => '0', output_cr => '0',
|
|
invert_a => '0', invert_out => '0', input_carry => ZERO, output_carry => '0',
|
|
length => NONE, byte_reverse => '0', sign_extend => '0',
|
|
update => '0', reserve => '0', is_32bit => '0',
|
|
is_signed => '0', rc => NONE, lr => '0', sgl_pipe => '0', repeat => NONE);
|
|
|
|
end decode_types;
|
|
|
|
package body decode_types is
|
|
end decode_types;
|