mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-11 23:43:15 +00:00
This implements the hypervisor doorbell exception and interrupt and the msgsnd, msgclr and msgsync instructions (msgsync is a no-op). The msgsnd instruction can generate a hypervisor doorbell interrupt on any CPU in the system. To achieve this, each core sends its hypervisor doorbell messages to the soc level, which ORs together the bits for each CPU and sends it to that CPU. The privileged doorbell exception/interrupt and the msgsndp/msgclrp instructions are not required since we don't implement SMT. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
658 lines
30 KiB
VHDL
658 lines
30 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;
|
|
|
|
-- indexed by instruction bits 31..26 and 4..0
|
|
constant major_predecode_rom : predecoder_rom_t := (
|
|
2#001100_00000# to 2#001100_11111# => INSN_addic, -- 12
|
|
2#001101_00000# to 2#001101_11111# => INSN_addic_dot, -- 13
|
|
2#001110_00000# to 2#001110_11111# => INSN_addi, -- 14
|
|
2#001111_00000# to 2#001111_11111# => INSN_addis, -- 15
|
|
2#010011_00100# to 2#010011_00101# => INSN_addpcis, -- 19
|
|
2#011100_00000# to 2#011100_11111# => INSN_andi_dot, -- 28
|
|
2#011101_00000# to 2#011101_11111# => INSN_andis_dot, -- 29
|
|
2#000000_00000# => INSN_attn, -- 0
|
|
2#010010_00000# to 2#010010_00001# => INSN_brel, -- 18
|
|
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, -- 16
|
|
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, -- 11
|
|
2#001010_00000# to 2#001010_11111# => INSN_cmpli, -- 10
|
|
2#100010_00000# to 2#100010_11111# => INSN_lbz, -- 34
|
|
2#100011_00000# to 2#100011_11111# => INSN_lbzu, -- 35
|
|
2#110010_00000# to 2#110010_11111# => INSN_lfd, -- 50
|
|
2#110011_00000# to 2#110011_11111# => INSN_lfdu, -- 51
|
|
2#110000_00000# to 2#110000_11111# => INSN_lfs, -- 56
|
|
2#110001_00000# to 2#110001_11111# => INSN_lfsu, -- 57
|
|
2#101010_00000# to 2#101010_11111# => INSN_lha, -- 42
|
|
2#101011_00000# to 2#101011_11111# => INSN_lhau, -- 43
|
|
2#101000_00000# to 2#101000_11111# => INSN_lhz, -- 40
|
|
2#101001_00000# to 2#101001_11111# => INSN_lhzu, -- 41
|
|
2#100000_00000# to 2#100000_11111# => INSN_lwz, -- 32
|
|
2#100001_00000# to 2#100001_11111# => INSN_lwzu, -- 33
|
|
2#000111_00000# to 2#000111_11111# => INSN_mulli, -- 7
|
|
2#011000_00000# to 2#011000_11111# => INSN_ori, -- 24
|
|
2#011001_00000# to 2#011001_11111# => INSN_oris, -- 25
|
|
2#010100_00000# to 2#010100_11111# => INSN_rlwimi, -- 20
|
|
2#010101_00000# to 2#010101_11111# => INSN_rlwinm, -- 21
|
|
2#010111_00000# to 2#010111_11111# => INSN_rlwnm, -- 23
|
|
2#010001_00000# to 2#010001_11111# => INSN_sc, -- 17
|
|
2#100110_00000# to 2#100110_11111# => INSN_stb, -- 38
|
|
2#100111_00000# to 2#100111_11111# => INSN_stbu, -- 39
|
|
2#110110_00000# to 2#110110_11111# => INSN_stfd, -- 54
|
|
2#110111_00000# to 2#110111_11111# => INSN_stfdu, -- 55
|
|
2#110100_00000# to 2#110100_11111# => INSN_stfs, -- 52
|
|
2#110101_00000# to 2#110101_11111# => INSN_stfsu, -- 53
|
|
2#101100_00000# to 2#101100_11111# => INSN_sth, -- 44
|
|
2#101101_00000# to 2#101101_11111# => INSN_sthu, -- 45
|
|
2#100100_00000# to 2#100100_11111# => INSN_stw, -- 36
|
|
2#100101_00000# to 2#100101_11111# => INSN_stwu, -- 37
|
|
2#001000_00000# to 2#001000_11111# => INSN_subfic, -- 8
|
|
2#000010_00000# to 2#000010_11111# => INSN_tdi, -- 2
|
|
2#000011_00000# to 2#000011_11111# => INSN_twi, -- 3
|
|
2#011010_00000# to 2#011010_11111# => INSN_xori, -- 26
|
|
2#011011_00000# to 2#011011_11111# => INSN_xoris, -- 27
|
|
-- 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_11010_00110# => INSN_rnop, -- cpabort
|
|
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_00111_01110# => INSN_msgclr,
|
|
2#0_00110_01110# => INSN_msgsnd,
|
|
2#0_11011_10110# => INSN_msgsync,
|
|
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 4 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_10110_10010# => INSN_hashst,
|
|
2#0_10111_10010# => INSN_hashchk,
|
|
2#0_10100_10010# => INSN_hashstp,
|
|
2#0_10101_10010# => INSN_hashchkp,
|
|
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;
|