|
|
|
-- 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_11111# => INSN_b,
|
|
|
|
2#010000_00000# to 2#010000_11111# => INSN_bc,
|
|
|
|
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 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_00100# => INSN_std,
|
|
|
|
2#111110_00101# => INSN_stdu,
|
|
|
|
2#111110_01000# => INSN_std,
|
|
|
|
2#111110_01001# => INSN_stdu,
|
|
|
|
2#111110_01100# => INSN_std,
|
|
|
|
2#111110_01101# => INSN_stdu,
|
|
|
|
2#111110_10000# => INSN_std,
|
|
|
|
2#111110_10001# => INSN_stdu,
|
|
|
|
2#111110_10100# => INSN_std,
|
|
|
|
2#111110_10101# => INSN_stdu,
|
|
|
|
2#111110_11000# => INSN_std,
|
|
|
|
2#111110_11001# => INSN_stdu,
|
|
|
|
2#111110_11100# => INSN_std,
|
|
|
|
2#111110_11101# => INSN_stdu,
|
|
|
|
-- 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,
|
Decode prefixed instructions
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>
1 year ago
|
|
|
-- prefix word, PO1
|
|
|
|
2#000001_00000# to 2#000001_11111# => INSN_prefix,
|
|
|
|
-- Major opcodes 57 and 61 are SFFS load/store instructions when prefixed
|
|
|
|
2#111001_00000# to 2#111001_11111# => INSN_op57,
|
|
|
|
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_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
|
icache: Restore primary opcode to instruction word
The icache stores a predecoded insn_code value for each instruction,
and so as to fit in 36 bits, omits the primary opcode (the most
significant 6 bits) of each instruction. Previously, for valid
instructions, the primary opcode field of the instruction delivered to
decode1 was a part-representation of the insn_code value rather than
the actual primary opcode. This adds a lookup table to compute the
primary opcode from the insn_code and deliver it in the instruction
words supplied to decode1.
In order that each insn_code can be associated with a single primary
opcode value, the various no-operation instructions with primary
opcode 31 (the reserved no-ops and dss, dst and dstst) have been given
a new insn_code, INSN_rnop, leaving INSN_nop for the preferred no-op
(ori r0,r0,0).
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
1 year ago
|
|
|
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_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 8 are reserved no-op instructions
|
icache: Restore primary opcode to instruction word
The icache stores a predecoded insn_code value for each instruction,
and so as to fit in 36 bits, omits the primary opcode (the most
significant 6 bits) of each instruction. Previously, for valid
instructions, the primary opcode field of the instruction delivered to
decode1 was a part-representation of the insn_code value rather than
the actual primary opcode. This adds a lookup table to compute the
primary opcode from the insn_code and deliver it in the instruction
words supplied to decode1.
In order that each insn_code can be associated with a single primary
opcode value, the various no-operation instructions with primary
opcode 31 (the reserved no-ops and dss, dst and dstst) have been given
a new insn_code, INSN_rnop, leaving INSN_nop for the preferred no-op
(ori r0,r0,0).
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
1 year ago
|
|
|
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_rnop,
|
|
|
|
2#0_10111_10010# => INSN_rnop,
|
|
|
|
2#0_00011_11100# => INSN_nor,
|
|
|
|
2#0_01101_11100# => INSN_or,
|
|
|
|
2#0_01100_11100# => INSN_orc,
|
|
|
|
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_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,
|
|
|
|
|
|
|
|
-- 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;
|