mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-13 15:18:09 +00:00
These are done in loadstore1. The HashDigest function is computed in 9 cycles; for 8 cycles, a state machine does 4 steps of key expansion per cycle, and for each of 4 lanes of data, does 4 steps of ciphering; then there is 1 cycle to combine the results into the final hash value. At present, hashcmp does not overlap the computation of the hash with fetching of data from memory (in the case of a cache miss). The 'is_signed' field in the instruction decode table is used to distinguish hashst and hashcmp from ordinary loads and stores. We have a new 'RBC' value for input_reg_c_t which says that we are reading RB but we want the value to come in via the C port; this is because we want the 5-bit immediate offset on the B port. Note that in the list of insn_code values, hashst/chk have been put in the section for instructions with an RB operand, which is not strictly correct given that the B port is used for the immediate D operand; however, adding them to the section for instructions without an RB operand would have made that section exceed 128 entries, causing changes to the padding needed. The only downside to having hashst/cmp where they are is that the debug logic can't use the RB port to read GPR/FPRs when a hashst/cmp instruction is being decoded. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
653 lines
29 KiB
VHDL
653 lines
29 KiB
VHDL
-- Instruction pre-decoder for microwatt
|
|
-- One cycle latency. Does 'WIDTH' instructions in parallel.
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.numeric_std.all;
|
|
|
|
library work;
|
|
use work.common.all;
|
|
use work.decode_types.all;
|
|
use work.insn_helpers.all;
|
|
|
|
entity predecoder is
|
|
generic (
|
|
HAS_FPU : boolean := true;
|
|
WIDTH : natural := 2;
|
|
ICODE_LEN : natural := 10;
|
|
IMAGE_LEN : natural := 26
|
|
);
|
|
port (
|
|
clk : in std_ulogic;
|
|
valid_in : in std_ulogic;
|
|
insns_in : in std_ulogic_vector(WIDTH * 32 - 1 downto 0);
|
|
icodes_out : out std_ulogic_vector(WIDTH * (ICODE_LEN + IMAGE_LEN) - 1 downto 0)
|
|
);
|
|
end entity predecoder;
|
|
|
|
architecture behaviour of predecoder is
|
|
|
|
type predecoder_rom_t is array(0 to 2047) of insn_code;
|
|
|
|
constant major_predecode_rom : predecoder_rom_t := (
|
|
2#001100_00000# to 2#001100_11111# => INSN_addic,
|
|
2#001101_00000# to 2#001101_11111# => INSN_addic_dot,
|
|
2#001110_00000# to 2#001110_11111# => INSN_addi,
|
|
2#001111_00000# to 2#001111_11111# => INSN_addis,
|
|
2#010011_00100# to 2#010011_00101# => INSN_addpcis,
|
|
2#011100_00000# to 2#011100_11111# => INSN_andi_dot,
|
|
2#011101_00000# to 2#011101_11111# => INSN_andis_dot,
|
|
2#000000_00000# => INSN_attn,
|
|
2#010010_00000# to 2#010010_00001# => INSN_brel,
|
|
2#010010_00010# to 2#010010_00011# => INSN_babs,
|
|
2#010010_00100# to 2#010010_00101# => INSN_brel,
|
|
2#010010_00110# to 2#010010_00111# => INSN_babs,
|
|
2#010010_01000# to 2#010010_01001# => INSN_brel,
|
|
2#010010_01010# to 2#010010_01011# => INSN_babs,
|
|
2#010010_01100# to 2#010010_01101# => INSN_brel,
|
|
2#010010_01110# to 2#010010_01111# => INSN_babs,
|
|
2#010010_10000# to 2#010010_10001# => INSN_brel,
|
|
2#010010_10010# to 2#010010_10011# => INSN_babs,
|
|
2#010010_10100# to 2#010010_10101# => INSN_brel,
|
|
2#010010_10110# to 2#010010_10111# => INSN_babs,
|
|
2#010010_11000# to 2#010010_11001# => INSN_brel,
|
|
2#010010_11010# to 2#010010_11011# => INSN_babs,
|
|
2#010010_11100# to 2#010010_11101# => INSN_brel,
|
|
2#010010_11110# to 2#010010_11111# => INSN_babs,
|
|
2#010000_00000# to 2#010000_00001# => INSN_bcrel,
|
|
2#010000_00010# to 2#010000_00011# => INSN_bcabs,
|
|
2#010000_00100# to 2#010000_00101# => INSN_bcrel,
|
|
2#010000_00110# to 2#010000_00111# => INSN_bcabs,
|
|
2#010000_01000# to 2#010000_01001# => INSN_bcrel,
|
|
2#010000_01010# to 2#010000_01011# => INSN_bcabs,
|
|
2#010000_01100# to 2#010000_01101# => INSN_bcrel,
|
|
2#010000_01110# to 2#010000_01111# => INSN_bcabs,
|
|
2#010000_10000# to 2#010000_10001# => INSN_bcrel,
|
|
2#010000_10010# to 2#010000_10011# => INSN_bcabs,
|
|
2#010000_10100# to 2#010000_10101# => INSN_bcrel,
|
|
2#010000_10110# to 2#010000_10111# => INSN_bcabs,
|
|
2#010000_11000# to 2#010000_11001# => INSN_bcrel,
|
|
2#010000_11010# to 2#010000_11011# => INSN_bcabs,
|
|
2#010000_11100# to 2#010000_11101# => INSN_bcrel,
|
|
2#010000_11110# to 2#010000_11111# => INSN_bcabs,
|
|
2#001011_00000# to 2#001011_11111# => INSN_cmpi,
|
|
2#001010_00000# to 2#001010_11111# => INSN_cmpli,
|
|
2#100010_00000# to 2#100010_11111# => INSN_lbz,
|
|
2#100011_00000# to 2#100011_11111# => INSN_lbzu,
|
|
2#110010_00000# to 2#110010_11111# => INSN_lfd,
|
|
2#110011_00000# to 2#110011_11111# => INSN_lfdu,
|
|
2#110000_00000# to 2#110000_11111# => INSN_lfs,
|
|
2#110001_00000# to 2#110001_11111# => INSN_lfsu,
|
|
2#101010_00000# to 2#101010_11111# => INSN_lha,
|
|
2#101011_00000# to 2#101011_11111# => INSN_lhau,
|
|
2#101000_00000# to 2#101000_11111# => INSN_lhz,
|
|
2#101001_00000# to 2#101001_11111# => INSN_lhzu,
|
|
2#100000_00000# to 2#100000_11111# => INSN_lwz,
|
|
2#100001_00000# to 2#100001_11111# => INSN_lwzu,
|
|
2#000111_00000# to 2#000111_11111# => INSN_mulli,
|
|
2#011000_00000# to 2#011000_11111# => INSN_ori,
|
|
2#011001_00000# to 2#011001_11111# => INSN_oris,
|
|
2#010100_00000# to 2#010100_11111# => INSN_rlwimi,
|
|
2#010101_00000# to 2#010101_11111# => INSN_rlwinm,
|
|
2#010111_00000# to 2#010111_11111# => INSN_rlwnm,
|
|
2#010001_00000# to 2#010001_11111# => INSN_sc,
|
|
2#100110_00000# to 2#100110_11111# => INSN_stb,
|
|
2#100111_00000# to 2#100111_11111# => INSN_stbu,
|
|
2#110110_00000# to 2#110110_11111# => INSN_stfd,
|
|
2#110111_00000# to 2#110111_11111# => INSN_stfdu,
|
|
2#110100_00000# to 2#110100_11111# => INSN_stfs,
|
|
2#110101_00000# to 2#110101_11111# => INSN_stfsu,
|
|
2#101100_00000# to 2#101100_11111# => INSN_sth,
|
|
2#101101_00000# to 2#101101_11111# => INSN_sthu,
|
|
2#100100_00000# to 2#100100_11111# => INSN_stw,
|
|
2#100101_00000# to 2#100101_11111# => INSN_stwu,
|
|
2#001000_00000# to 2#001000_11111# => INSN_subfic,
|
|
2#000010_00000# to 2#000010_11111# => INSN_tdi,
|
|
2#000011_00000# to 2#000011_11111# => INSN_twi,
|
|
2#011010_00000# to 2#011010_11111# => INSN_xori,
|
|
2#011011_00000# to 2#011011_11111# => INSN_xoris,
|
|
-- major opcode 4
|
|
2#000100_10000# => INSN_maddhd,
|
|
2#000100_10001# => INSN_maddhdu,
|
|
2#000100_10011# => INSN_maddld,
|
|
-- major opcode 30
|
|
2#011110_01000# to 2#011110_01001# => INSN_rldic,
|
|
2#011110_01010# to 2#011110_01011# => INSN_rldic,
|
|
2#011110_00000# to 2#011110_00001# => INSN_rldicl,
|
|
2#011110_00010# to 2#011110_00011# => INSN_rldicl,
|
|
2#011110_00100# to 2#011110_00101# => INSN_rldicr,
|
|
2#011110_00110# to 2#011110_00111# => INSN_rldicr,
|
|
2#011110_01100# to 2#011110_01101# => INSN_rldimi,
|
|
2#011110_01110# to 2#011110_01111# => INSN_rldimi,
|
|
2#011110_10000# to 2#011110_10001# => INSN_rldcl,
|
|
2#011110_10010# to 2#011110_10011# => INSN_rldcr,
|
|
-- major opcode 56
|
|
2#111000_00000# to 2#111000_11111# => INSN_lq,
|
|
-- major opcode 58
|
|
2#111010_00000# => INSN_ld,
|
|
2#111010_00001# => INSN_ldu,
|
|
2#111010_00010# => INSN_lwa,
|
|
2#111010_00100# => INSN_ld,
|
|
2#111010_00101# => INSN_ldu,
|
|
2#111010_00110# => INSN_lwa,
|
|
2#111010_01000# => INSN_ld,
|
|
2#111010_01001# => INSN_ldu,
|
|
2#111010_01010# => INSN_lwa,
|
|
2#111010_01100# => INSN_ld,
|
|
2#111010_01101# => INSN_ldu,
|
|
2#111010_01110# => INSN_lwa,
|
|
2#111010_10000# => INSN_ld,
|
|
2#111010_10001# => INSN_ldu,
|
|
2#111010_10010# => INSN_lwa,
|
|
2#111010_10100# => INSN_ld,
|
|
2#111010_10101# => INSN_ldu,
|
|
2#111010_10110# => INSN_lwa,
|
|
2#111010_11000# => INSN_ld,
|
|
2#111010_11001# => INSN_ldu,
|
|
2#111010_11010# => INSN_lwa,
|
|
2#111010_11100# => INSN_ld,
|
|
2#111010_11101# => INSN_ldu,
|
|
2#111010_11110# => INSN_lwa,
|
|
-- major opcode 59
|
|
2#111011_00100# to 2#111011_00101# => INSN_fdivs,
|
|
2#111011_01000# to 2#111011_01001# => INSN_fsubs,
|
|
2#111011_01010# to 2#111011_01011# => INSN_fadds,
|
|
2#111011_01100# to 2#111011_01101# => INSN_fsqrts,
|
|
2#111011_10000# to 2#111011_10001# => INSN_fres,
|
|
2#111011_10010# to 2#111011_10011# => INSN_fmuls,
|
|
2#111011_10100# to 2#111011_10101# => INSN_frsqrtes,
|
|
2#111011_11000# to 2#111011_11001# => INSN_fmsubs,
|
|
2#111011_11010# to 2#111011_11011# => INSN_fmadds,
|
|
2#111011_11100# to 2#111011_11101# => INSN_fnmsubs,
|
|
2#111011_11110# to 2#111011_11111# => INSN_fnmadds,
|
|
-- major opcode 62
|
|
2#111110_00000# => INSN_std,
|
|
2#111110_00001# => INSN_stdu,
|
|
2#111110_00010# => INSN_stq,
|
|
2#111110_00100# => INSN_std,
|
|
2#111110_00101# => INSN_stdu,
|
|
2#111110_00110# => INSN_stq,
|
|
2#111110_01000# => INSN_std,
|
|
2#111110_01001# => INSN_stdu,
|
|
2#111110_01010# => INSN_stq,
|
|
2#111110_01100# => INSN_std,
|
|
2#111110_01101# => INSN_stdu,
|
|
2#111110_01110# => INSN_stq,
|
|
2#111110_10000# => INSN_std,
|
|
2#111110_10001# => INSN_stdu,
|
|
2#111110_10010# => INSN_stq,
|
|
2#111110_10100# => INSN_std,
|
|
2#111110_10101# => INSN_stdu,
|
|
2#111110_10110# => INSN_stq,
|
|
2#111110_11000# => INSN_std,
|
|
2#111110_11001# => INSN_stdu,
|
|
2#111110_11010# => INSN_stq,
|
|
2#111110_11100# => INSN_std,
|
|
2#111110_11101# => INSN_stdu,
|
|
2#111110_11110# => INSN_stq,
|
|
-- major opcode 63
|
|
2#111111_00100# to 2#111111_00101# => INSN_fdiv,
|
|
2#111111_01000# to 2#111111_01001# => INSN_fsub,
|
|
2#111111_01010# to 2#111111_01011# => INSN_fadd,
|
|
2#111111_01100# to 2#111111_01101# => INSN_fsqrt,
|
|
2#111111_01110# to 2#111111_01111# => INSN_fsel,
|
|
2#111111_10000# to 2#111111_10001# => INSN_fre,
|
|
2#111111_10010# to 2#111111_10011# => INSN_fmul,
|
|
2#111111_10100# to 2#111111_10101# => INSN_frsqrte,
|
|
2#111111_11000# to 2#111111_11001# => INSN_fmsub,
|
|
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, 60 and 61 are SFFS load/store instructions when prefixed
|
|
2#111001_00000# to 2#111001_11111# => INSN_op57,
|
|
2#111100_00000# to 2#111100_11111# => INSN_op60,
|
|
2#111101_00000# to 2#111101_11111# => INSN_op61,
|
|
others => INSN_illegal
|
|
);
|
|
|
|
constant row_predecode_rom : predecoder_rom_t := (
|
|
-- Major opcode 31
|
|
-- Address bits are 0, insn(10:1)
|
|
2#0_01000_01010# => INSN_add,
|
|
2#0_11000_01010# => INSN_add, -- addo
|
|
2#0_00000_01010# => INSN_addc,
|
|
2#0_10000_01010# => INSN_addc, -- addco
|
|
2#0_00100_01010# => INSN_adde,
|
|
2#0_10100_01010# => INSN_adde, -- addeo
|
|
2#0_00101_01010# => INSN_addex,
|
|
2#0_00010_01010# => INSN_addg6s,
|
|
2#0_00111_01010# => INSN_addme,
|
|
2#0_10111_01010# => INSN_addme, -- addmeo
|
|
2#0_00110_01010# => INSN_addze,
|
|
2#0_10110_01010# => INSN_addze, -- addzeo
|
|
2#0_00000_11100# => INSN_and,
|
|
2#0_00001_11100# => INSN_andc,
|
|
2#0_00111_11100# => INSN_bperm,
|
|
2#0_00110_11011# => INSN_brh,
|
|
2#0_00100_11011# => INSN_brw,
|
|
2#0_00101_11011# => INSN_brd,
|
|
2#0_01001_11010# => INSN_cbcdtd,
|
|
2#0_01000_11010# => INSN_cdtbcd,
|
|
2#0_00110_11100# => INSN_cfuged,
|
|
2#0_00000_00000# => INSN_cmp,
|
|
2#0_01111_11100# => INSN_cmpb,
|
|
2#0_00111_00000# => INSN_cmpeqb,
|
|
2#0_00001_00000# => INSN_cmpl,
|
|
2#0_00110_00000# => INSN_cmprb,
|
|
2#0_00001_11010# => INSN_cntlzd,
|
|
2#0_00000_11010# => INSN_cntlzw,
|
|
2#0_10001_11010# => INSN_cnttzd,
|
|
2#0_10000_11010# => INSN_cnttzw,
|
|
2#0_10111_10011# => INSN_darn,
|
|
2#0_00010_10110# => INSN_dcbf,
|
|
2#0_00001_10110# => INSN_dcbst,
|
|
2#0_01000_10110# => INSN_dcbt,
|
|
2#0_00111_10110# => INSN_dcbtst,
|
|
2#0_11111_10110# => INSN_dcbz,
|
|
2#0_01100_01001# => INSN_divdeu,
|
|
2#0_11100_01001# => INSN_divdeu, -- divdeuo
|
|
2#0_01100_01011# => INSN_divweu,
|
|
2#0_11100_01011# => INSN_divweu, -- divweuo
|
|
2#0_01101_01001# => INSN_divde,
|
|
2#0_11101_01001# => INSN_divde, -- divdeo
|
|
2#0_01101_01011# => INSN_divwe,
|
|
2#0_11101_01011# => INSN_divwe, -- divweo
|
|
2#0_01110_01001# => INSN_divdu,
|
|
2#0_11110_01001# => INSN_divdu, -- divduo
|
|
2#0_01110_01011# => INSN_divwu,
|
|
2#0_11110_01011# => INSN_divwu, -- divwuo
|
|
2#0_01111_01001# => INSN_divd,
|
|
2#0_11111_01001# => INSN_divd, -- divdo
|
|
2#0_01111_01011# => INSN_divw,
|
|
2#0_11111_01011# => INSN_divw, -- divwo
|
|
2#0_11001_10110# => INSN_rnop, -- dss
|
|
2#0_01010_10110# => INSN_rnop, -- dst
|
|
2#0_01011_10110# => INSN_rnop, -- dstst
|
|
2#0_11010_10110# => INSN_eieio,
|
|
2#0_01000_11100# => INSN_eqv,
|
|
2#0_11101_11010# => INSN_extsb,
|
|
2#0_11100_11010# => INSN_extsh,
|
|
2#0_11110_11010# => INSN_extsw,
|
|
2#0_11011_11010# => INSN_extswsli,
|
|
2#0_11011_11011# => INSN_extswsli,
|
|
2#0_11110_10110# => INSN_icbi,
|
|
2#0_00000_10110# => INSN_icbt,
|
|
2#0_00000_01111# => INSN_isel,
|
|
2#0_00001_01111# => INSN_isel,
|
|
2#0_00010_01111# => INSN_isel,
|
|
2#0_00011_01111# => INSN_isel,
|
|
2#0_00100_01111# => INSN_isel,
|
|
2#0_00101_01111# => INSN_isel,
|
|
2#0_00110_01111# => INSN_isel,
|
|
2#0_00111_01111# => INSN_isel,
|
|
2#0_01000_01111# => INSN_isel,
|
|
2#0_01001_01111# => INSN_isel,
|
|
2#0_01010_01111# => INSN_isel,
|
|
2#0_01011_01111# => INSN_isel,
|
|
2#0_01100_01111# => INSN_isel,
|
|
2#0_01101_01111# => INSN_isel,
|
|
2#0_01110_01111# => INSN_isel,
|
|
2#0_01111_01111# => INSN_isel,
|
|
2#0_10000_01111# => INSN_isel,
|
|
2#0_10001_01111# => INSN_isel,
|
|
2#0_10010_01111# => INSN_isel,
|
|
2#0_10011_01111# => INSN_isel,
|
|
2#0_10100_01111# => INSN_isel,
|
|
2#0_10101_01111# => INSN_isel,
|
|
2#0_10110_01111# => INSN_isel,
|
|
2#0_10111_01111# => INSN_isel,
|
|
2#0_11000_01111# => INSN_isel,
|
|
2#0_11001_01111# => INSN_isel,
|
|
2#0_11010_01111# => INSN_isel,
|
|
2#0_11011_01111# => INSN_isel,
|
|
2#0_11100_01111# => INSN_isel,
|
|
2#0_11101_01111# => INSN_isel,
|
|
2#0_11110_01111# => INSN_isel,
|
|
2#0_11111_01111# => INSN_isel,
|
|
2#0_00001_10100# => INSN_lbarx,
|
|
2#0_11010_10101# => INSN_lbzcix,
|
|
2#0_00011_10111# => INSN_lbzux,
|
|
2#0_00010_10111# => INSN_lbzx,
|
|
2#0_00010_10100# => INSN_ldarx,
|
|
2#0_10000_10100# => INSN_ldbrx,
|
|
2#0_11011_10101# => INSN_ldcix,
|
|
2#0_00001_10101# => INSN_ldux,
|
|
2#0_00000_10101# => INSN_ldx,
|
|
2#0_10010_10111# => INSN_lfdx,
|
|
2#0_10011_10111# => INSN_lfdux,
|
|
2#0_11010_10111# => INSN_lfiwax,
|
|
2#0_11011_10111# => INSN_lfiwzx,
|
|
2#0_10000_10111# => INSN_lfsx,
|
|
2#0_10001_10111# => INSN_lfsux,
|
|
2#0_00011_10100# => INSN_lharx,
|
|
2#0_01011_10111# => INSN_lhaux,
|
|
2#0_01010_10111# => INSN_lhax,
|
|
2#0_11000_10110# => INSN_lhbrx,
|
|
2#0_11001_10101# => INSN_lhzcix,
|
|
2#0_01001_10111# => INSN_lhzux,
|
|
2#0_01000_10111# => INSN_lhzx,
|
|
2#0_01000_10100# => INSN_lqarx,
|
|
2#0_00000_10100# => INSN_lwarx,
|
|
2#0_01011_10101# => INSN_lwaux,
|
|
2#0_01010_10101# => INSN_lwax,
|
|
2#0_10000_10110# => INSN_lwbrx,
|
|
2#0_11000_10101# => INSN_lwzcix,
|
|
2#0_00001_10111# => INSN_lwzux,
|
|
2#0_00000_10111# => INSN_lwzx,
|
|
2#0_10010_00000# => INSN_mcrxrx,
|
|
2#0_00000_10011# => INSN_mfcr,
|
|
2#0_00010_10011# => INSN_mfmsr,
|
|
2#0_01010_10011# => INSN_mfspr,
|
|
2#0_01000_01001# => INSN_modud,
|
|
2#0_01000_01011# => INSN_moduw,
|
|
2#0_11000_01001# => INSN_modsd,
|
|
2#0_11000_01011# => INSN_modsw,
|
|
2#0_00100_10000# => INSN_mtcrf,
|
|
2#0_00100_10010# => INSN_mtmsr,
|
|
2#0_00101_10010# => INSN_mtmsrd,
|
|
2#0_01110_10011# => INSN_mtspr,
|
|
2#0_00010_01001# => INSN_mulhd,
|
|
2#0_00000_01001# => INSN_mulhdu,
|
|
2#0_00010_01011# => INSN_mulhw,
|
|
2#0_00000_01011# => INSN_mulhwu,
|
|
-- next 4 have reserved bit set
|
|
2#0_10010_01001# => INSN_mulhd,
|
|
2#0_10000_01001# => INSN_mulhdu,
|
|
2#0_10010_01011# => INSN_mulhw,
|
|
2#0_10000_01011# => INSN_mulhwu,
|
|
2#0_00111_01001# => INSN_mulld,
|
|
2#0_10111_01001# => INSN_mulld, -- mulldo
|
|
2#0_00111_01011# => INSN_mullw,
|
|
2#0_10111_01011# => INSN_mullw, -- mullwo
|
|
2#0_01110_11100# => INSN_nand,
|
|
2#0_00011_01000# => INSN_neg,
|
|
2#0_10011_01000# => INSN_neg, -- nego
|
|
-- next 6 are reserved no-op instructions
|
|
2#0_10000_10010# => INSN_rnop,
|
|
2#0_10001_10010# => INSN_rnop,
|
|
2#0_10010_10010# => INSN_rnop,
|
|
2#0_10011_10010# => INSN_rnop,
|
|
2#0_10100_10010# => INSN_rnop,
|
|
2#0_10101_10010# => INSN_rnop,
|
|
2#0_10110_10010# => INSN_hashst,
|
|
2#0_10111_10010# => INSN_hashchk,
|
|
2#0_00011_11100# => INSN_nor,
|
|
2#0_01101_11100# => INSN_or,
|
|
2#0_01100_11100# => INSN_orc,
|
|
2#0_00100_11100# => INSN_pdepd,
|
|
2#0_00101_11100# => INSN_pextd,
|
|
2#0_00011_11010# => INSN_popcntb,
|
|
2#0_01111_11010# => INSN_popcntd,
|
|
2#0_01011_11010# => INSN_popcntw,
|
|
2#0_00101_11010# => INSN_prtyd,
|
|
2#0_00100_11010# => INSN_prtyw,
|
|
2#0_00100_00000# => INSN_setb,
|
|
2#0_01100_00000# => INSN_setb, -- setbc
|
|
2#0_01101_00000# => INSN_setb, -- setbcr
|
|
2#0_01110_00000# => INSN_setb, -- setnbc
|
|
2#0_01111_00000# => INSN_setb, -- setnbcr
|
|
2#0_01111_10010# => INSN_slbia,
|
|
2#0_00000_11011# => INSN_sld,
|
|
2#0_00000_11000# => INSN_slw,
|
|
2#0_11000_11010# => INSN_srad,
|
|
2#0_11001_11010# => INSN_sradi,
|
|
2#0_11001_11011# => INSN_sradi,
|
|
2#0_11000_11000# => INSN_sraw,
|
|
2#0_11001_11000# => INSN_srawi,
|
|
2#0_10000_11011# => INSN_srd,
|
|
2#0_10000_11000# => INSN_srw,
|
|
2#0_11110_10101# => INSN_stbcix,
|
|
2#0_10101_10110# => INSN_stbcx,
|
|
2#0_00111_10111# => INSN_stbux,
|
|
2#0_00110_10111# => INSN_stbx,
|
|
2#0_10100_10100# => INSN_stdbrx,
|
|
2#0_11111_10101# => INSN_stdcix,
|
|
2#0_00110_10110# => INSN_stdcx,
|
|
2#0_00101_10101# => INSN_stdux,
|
|
2#0_00100_10101# => INSN_stdx,
|
|
2#0_10110_10111# => INSN_stfdx,
|
|
2#0_10111_10111# => INSN_stfdux,
|
|
2#0_11110_10111# => INSN_stfiwx,
|
|
2#0_10100_10111# => INSN_stfsx,
|
|
2#0_10101_10111# => INSN_stfsux,
|
|
2#0_11100_10110# => INSN_sthbrx,
|
|
2#0_11101_10101# => INSN_sthcix,
|
|
2#0_10110_10110# => INSN_sthcx,
|
|
2#0_01101_10111# => INSN_sthux,
|
|
2#0_01100_10111# => INSN_sthx,
|
|
2#0_00101_10110# => INSN_stqcx,
|
|
2#0_10100_10110# => INSN_stwbrx,
|
|
2#0_11100_10101# => INSN_stwcix,
|
|
2#0_00100_10110# => INSN_stwcx,
|
|
2#0_00101_10111# => INSN_stwux,
|
|
2#0_00100_10111# => INSN_stwx,
|
|
2#0_00001_01000# => INSN_subf,
|
|
2#0_10001_01000# => INSN_subf, -- subfo
|
|
2#0_00000_01000# => INSN_subfc,
|
|
2#0_10000_01000# => INSN_subfc, -- subfco
|
|
2#0_00100_01000# => INSN_subfe,
|
|
2#0_10100_01000# => INSN_subfe, -- subfeo
|
|
2#0_00111_01000# => INSN_subfme,
|
|
2#0_10111_01000# => INSN_subfme, -- subfmeo
|
|
2#0_00110_01000# => INSN_subfze,
|
|
2#0_10110_01000# => INSN_subfze, -- subfzeo
|
|
2#0_10010_10110# => INSN_sync,
|
|
2#0_00010_00100# => INSN_td,
|
|
2#0_00000_00100# => INSN_tw,
|
|
2#0_01001_10010# => INSN_tlbie,
|
|
2#0_01000_10010# => INSN_tlbiel,
|
|
2#0_10001_10110# => INSN_tlbsync,
|
|
2#0_00000_11110# => INSN_wait,
|
|
2#0_01001_11100# => INSN_xor,
|
|
|
|
-- Major opcode 19
|
|
-- Columns with insn(4) = '1' are all illegal and not mapped here; to
|
|
-- fit into 2048 entries, the columns are remapped so that 16-24 are
|
|
-- stored here as 8-15; in other words the address bits are
|
|
-- 1, insn(10..6), 1, insn(5), insn(3..1)
|
|
-- Columns 16-17 here are opcode 19 columns 0-1
|
|
-- Columns 24-31 here are opcode 19 columns 16-23
|
|
2#1_10000_11000# => INSN_bcctr,
|
|
2#1_00000_11000# => INSN_bclr,
|
|
2#1_10001_11000# => INSN_bctar,
|
|
2#1_01000_10001# => INSN_crand,
|
|
2#1_00100_10001# => INSN_crandc,
|
|
2#1_01001_10001# => INSN_creqv,
|
|
2#1_00111_10001# => INSN_crnand,
|
|
2#1_00001_10001# => INSN_crnor,
|
|
2#1_01110_10001# => INSN_cror,
|
|
2#1_01101_10001# => INSN_crorc,
|
|
2#1_00110_10001# => INSN_crxor,
|
|
2#1_00100_11110# => INSN_isync,
|
|
2#1_00000_10000# => INSN_mcrf,
|
|
2#1_00000_11010# => INSN_rfid,
|
|
2#1_00010_11010# => INSN_rfscv,
|
|
2#1_01000_11010# => INSN_rfid, -- hrfid
|
|
|
|
-- Major opcode 59
|
|
-- Address bits are 1, insn(10..6), 1, 0, insn(3..1)
|
|
-- Only column 14 is valid here; columns 16-31 are handled in the major table
|
|
-- Column 14 is mapped to column 22.
|
|
-- Columns 20-23 here are opcode 59 columns 12-15
|
|
2#1_11010_10110# => INSN_fcfids,
|
|
2#1_11110_10110# => INSN_fcfidus,
|
|
|
|
-- Major opcode 63
|
|
-- Columns 0-15 are mapped here; columns 16-31 are in the major table.
|
|
-- Address bits are 1, insn(10:6), 0, insn(4:1)
|
|
-- Columns 0-15 here are opcode 63 columns 0-15
|
|
2#1_00000_00000# => INSN_fcmpu,
|
|
2#1_00001_00000# => INSN_fcmpo,
|
|
2#1_00010_00000# => INSN_mcrfs,
|
|
2#1_00100_00000# => INSN_ftdiv,
|
|
2#1_00101_00000# => INSN_ftsqrt,
|
|
2#1_00001_00110# => INSN_mtfsb,
|
|
2#1_00010_00110# => INSN_mtfsb,
|
|
2#1_00100_00110# => INSN_mtfsfi,
|
|
2#1_11010_00110# => INSN_fmrgow,
|
|
2#1_11110_00110# => INSN_fmrgew,
|
|
2#1_10010_00111# => INSN_mffs,
|
|
2#1_10110_00111# => INSN_mtfsf,
|
|
2#1_00000_01000# => INSN_fcpsgn,
|
|
2#1_00001_01000# => INSN_fneg,
|
|
2#1_00010_01000# => INSN_fmr,
|
|
2#1_00100_01000# => INSN_fnabs,
|
|
2#1_01000_01000# => INSN_fabs,
|
|
2#1_01100_01000# => INSN_frin,
|
|
2#1_01101_01000# => INSN_friz,
|
|
2#1_01110_01000# => INSN_frip,
|
|
2#1_01111_01000# => INSN_frim,
|
|
2#1_00000_01100# => INSN_frsp,
|
|
2#1_00000_01110# => INSN_fctiw,
|
|
2#1_00100_01110# => INSN_fctiwu,
|
|
2#1_11001_01110# => INSN_fctid,
|
|
2#1_11010_01110# => INSN_fcfid,
|
|
2#1_11101_01110# => INSN_fctidu,
|
|
2#1_11110_01110# => INSN_fcfidu,
|
|
2#1_00000_01111# => INSN_fctiwz,
|
|
2#1_00100_01111# => INSN_fctiwuz,
|
|
2#1_11001_01111# => INSN_fctidz,
|
|
2#1_11101_01111# => INSN_fctiduz,
|
|
|
|
others => INSN_illegal
|
|
);
|
|
|
|
constant IOUT_LEN : natural := ICODE_LEN + IMAGE_LEN;
|
|
|
|
type predec_t is record
|
|
image : std_ulogic_vector(31 downto 0);
|
|
maj_predecode : unsigned(ICODE_LEN - 1 downto 0);
|
|
row_predecode : unsigned(ICODE_LEN - 1 downto 0);
|
|
end record;
|
|
|
|
subtype index_t is integer range 0 to WIDTH-1;
|
|
type predec_array is array(index_t) of predec_t;
|
|
|
|
signal pred : predec_array;
|
|
signal valid : std_ulogic;
|
|
|
|
begin
|
|
predecode_0: process(clk)
|
|
variable majaddr : std_ulogic_vector(10 downto 0);
|
|
variable rowaddr : std_ulogic_vector(10 downto 0);
|
|
variable iword : std_ulogic_vector(31 downto 0);
|
|
variable majcode : insn_code;
|
|
variable rowcode : insn_code;
|
|
begin
|
|
if rising_edge(clk) then
|
|
valid <= valid_in;
|
|
for i in index_t loop
|
|
iword := insns_in(i * 32 + 31 downto i * 32);
|
|
pred(i).image <= iword;
|
|
|
|
if is_X(iword) then
|
|
pred(i).maj_predecode <= (others => 'X');
|
|
pred(i).row_predecode <= (others => 'X');
|
|
else
|
|
majaddr := iword(31 downto 26) & iword(4 downto 0);
|
|
|
|
-- row_predecode_rom is used for op 19, 31, 59, 63
|
|
-- addr bit 10 is 0 for op 31, 1 for 19, 59, 63
|
|
rowaddr(10) := iword(31) or not iword(29);
|
|
rowaddr(9 downto 5) := iword(10 downto 6);
|
|
if iword(28) = '0' then
|
|
-- op 19 and op 59
|
|
rowaddr(4 downto 3) := '1' & iword(5);
|
|
else
|
|
-- op 31 and 63; for 63 we only use this when iword(5) = '0'
|
|
rowaddr(4 downto 3) := iword(5 downto 4);
|
|
end if;
|
|
rowaddr(2 downto 0) := iword(3 downto 1);
|
|
|
|
majcode := major_predecode_rom(to_integer(unsigned(majaddr)));
|
|
pred(i).maj_predecode <= to_unsigned(insn_code'pos(majcode), ICODE_LEN);
|
|
rowcode := row_predecode_rom(to_integer(unsigned(rowaddr)));
|
|
pred(i).row_predecode <= to_unsigned(insn_code'pos(rowcode), ICODE_LEN);
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
end process;
|
|
|
|
predecode_1: process(all)
|
|
variable iword : std_ulogic_vector(31 downto 0);
|
|
variable use_row : std_ulogic;
|
|
variable illegal : std_ulogic;
|
|
variable ici : std_ulogic_vector(IOUT_LEN - 1 downto 0);
|
|
variable icode : unsigned(ICODE_LEN - 1 downto 0);
|
|
begin
|
|
for i in index_t loop
|
|
iword := pred(i).image;
|
|
icode := pred(i).maj_predecode;
|
|
use_row := '0';
|
|
illegal := '0';
|
|
|
|
case iword(31 downto 26) is
|
|
when "000100" => -- 4
|
|
-- major opcode 4, mostly VMX/VSX stuff but also some integer ops (madd*)
|
|
illegal := not iword(5);
|
|
|
|
when "010011" => -- 19
|
|
-- 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
|
|
-- 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.
|
|
illegal := iword(4);
|
|
use_row := iword(5) or (not iword(3) and not iword(2));
|
|
|
|
when "011000" => -- 24
|
|
-- ori, special-case the standard NOP
|
|
if std_match(iword, "01100000000000000000000000000000") then
|
|
icode := to_unsigned(insn_code'pos(INSN_nop), ICODE_LEN);
|
|
end if;
|
|
|
|
when "011111" => -- 31
|
|
-- major opcode 31, lots of things
|
|
-- Use the first half of the row table for all columns
|
|
use_row := '1';
|
|
|
|
when "111011" => -- 59
|
|
-- floating point operations, mostly single-precision
|
|
-- 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.
|
|
illegal := not iword(5) and (not iword(4) or not iword(3));
|
|
use_row := not iword(5);
|
|
|
|
when "111111" => -- 63
|
|
-- 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.
|
|
use_row := not iword(5);
|
|
|
|
when others =>
|
|
end case;
|
|
if use_row = '1' then
|
|
icode := pred(i).row_predecode;
|
|
end if;
|
|
|
|
-- Mark FP instructions as illegal if we don't have an FPU
|
|
if not HAS_FPU and not is_X(icode) and
|
|
to_integer(icode) >= insn_code'pos(INSN_first_frs) then
|
|
illegal := '1';
|
|
end if;
|
|
|
|
ici(31 downto 0) := iword;
|
|
ici(IOUT_LEN - 1 downto 32) := (others => '0');
|
|
if valid = '0' or illegal = '1' or is_X(icode) or
|
|
icode = to_unsigned(insn_code'pos(INSN_illegal), ICODE_LEN) then
|
|
-- Since an insn_code currently fits in 9 bits, use just
|
|
-- the most significant bit of ici to indicate illegal insns.
|
|
ici(IOUT_LEN - 1) := '1';
|
|
else
|
|
ici(IOUT_LEN - 1 downto IMAGE_LEN) := std_ulogic_vector(icode);
|
|
end if;
|
|
icodes_out(i * IOUT_LEN + IOUT_LEN - 1 downto i * IOUT_LEN) <= ici;
|
|
end loop;
|
|
end process;
|
|
|
|
end architecture behaviour;
|