mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-13 15:18:09 +00:00
This gets rid of the adder in writeback that computes redirect_nia. Instead, the main adder in the ALU is used to compute the branch target for relative branches. We now decode b and bc differently depending on the AA field, generating INSN_brel, INSN_babs, INSN_bcrel or INSN_bcabs as appropriate. Each one has a separate entry in the decode table in decode1; the *rel versions use CIA as the A input. The bclr/bcctr/bctar and rfid instructions now select ramspr_result for the main result mux to get the redirect address into ex1.e.write_data. For branches which are predicted taken but not actually taken, we need to redirect to the following instruction. We also need to do that for isync. We do this in the execute2 stage since whether or not to do it depends on the branch result. The next_nia computation is moved to the execute2 stage and comes in via a new leg on the secondary result multiplexer, making next_nia available ultimately in ex2.e.write_data. This also means that the next_nia leg of the primary result multiplexer is gone. Incrementing last_nia by 4 for sc (so that SRR0 points to the following instruction) is also moved to execute2. Writing CIA+4 to LR was previously done through the main result multiplexer. Now it comes in explicitly in the ramspr write logic. Overall this removes the br_offset and abs_br fields and the logic to add br_offset and next_nia, and one leg of the primary result multiplexer, at the cost of a few extra control signals between execute1 and execute2 and some multiplexing for the ramspr write side and an extra input on the secondary result multiplexer. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
635 lines
28 KiB
VHDL
635 lines
28 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 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,
|
|
-- 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
|
|
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
|
|
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;
|