1
0
mirror of https://github.com/antonblanchard/microwatt.git synced 2026-01-13 15:18:09 +00:00
antonblanchard.microwatt/predecode.vhdl
Paul Mackerras 1c4b5def36 Improve timing of redirect_nia going from writeback to fetch1
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>
2023-09-19 17:30:54 +10:00

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;