mirror of
https://github.com/j-core/j-core-ice40.git
synced 2026-01-11 23:52:49 +00:00
3644 lines
134 KiB
VHDL
3644 lines
134 KiB
VHDL
-- ******************************************************************
|
|
-- ******************************************************************
|
|
-- ******************************************************************
|
|
-- This file is generated. Changing this file directly is probably
|
|
-- not what you want to do. Any changes will be overwritten next time
|
|
-- the generator is run.
|
|
-- ******************************************************************
|
|
-- ******************************************************************
|
|
-- ******************************************************************
|
|
use work.cpu2j0_pack.all;
|
|
architecture simple_logic of decode_table is
|
|
signal imm_enum : immval_t;
|
|
signal mac_busy : mac_busy_t;
|
|
signal imms_12_1 : std_logic_vector(31 downto 0);
|
|
signal imms_8_0 : std_logic_vector(31 downto 0);
|
|
signal imms_8_1 : std_logic_vector(31 downto 0);
|
|
begin
|
|
-- Immediate value mux
|
|
with imm_enum select
|
|
ex.imm_val <=
|
|
x"fffffff0" when IMM_N16,
|
|
x"fffffff8" when IMM_N8,
|
|
x"fffffffe" when IMM_N2,
|
|
x"ffffffff" when IMM_N1,
|
|
x"00000000" when IMM_ZERO,
|
|
x"00000001" when IMM_P1,
|
|
x"00000002" when IMM_P2,
|
|
x"00000004" when IMM_P4,
|
|
x"00000008" when IMM_P8,
|
|
x"00000010" when IMM_P16,
|
|
imms_8_0 when IMM_S_8_0,
|
|
imms_8_1 when IMM_S_8_1,
|
|
imms_12_1 when IMM_S_12_1,
|
|
x"0000000" & op.code(3 downto 0) when IMM_U_4_0,
|
|
"000000000000000000000000000" & op.code(3 downto 0) & "0" when IMM_U_4_1,
|
|
"00000000000000000000000000" & op.code(3 downto 0) & "00" when IMM_U_4_2,
|
|
x"000000" & op.code(7 downto 0) when IMM_U_8_0,
|
|
"00000000000000000000000" & op.code(7 downto 0) & "0" when IMM_U_8_1,
|
|
"0000000000000000000000" & op.code(7 downto 0) & "00" when IMM_U_8_2;
|
|
-- Sign extend parts of opcode
|
|
process(op)
|
|
begin
|
|
-- Sign extend 8 right-most bits
|
|
for i in 8 to 31 loop
|
|
imms_8_0(i) <= op.code(7);
|
|
end loop;
|
|
imms_8_0(7 downto 0) <= op.code(7 downto 0);
|
|
-- Sign extend 8 right-most bits shifted by 1
|
|
for i in 9 to 31 loop
|
|
imms_8_1(i) <= op.code(7);
|
|
end loop;
|
|
imms_8_1(8 downto 1) <= op.code(7 downto 0);
|
|
imms_8_1(0) <= '0';
|
|
-- Sign extend 12 right-most bits shifted by 1
|
|
for i in 13 to 31 loop
|
|
imms_12_1(i) <= op.code(11);
|
|
end loop;
|
|
imms_12_1(12 downto 1) <= op.code(11 downto 0);
|
|
imms_12_1(0) <= '0';
|
|
end process;
|
|
-- Mac busy muxes
|
|
with mac_busy select
|
|
ex.mac_busy <=
|
|
'0' when NOT_BUSY,
|
|
not next_id_stall when EX_NOT_STALL,
|
|
'0' when WB_NOT_STALL,
|
|
'1' when EX_BUSY,
|
|
'0' when WB_BUSY;
|
|
with mac_busy select
|
|
wb.mac_busy <=
|
|
'0' when NOT_BUSY,
|
|
'0' when EX_NOT_STALL,
|
|
not next_id_stall when WB_NOT_STALL,
|
|
'0' when EX_BUSY,
|
|
'1' when WB_BUSY;
|
|
process(t_bcc, op)
|
|
variable cond : std_logic_vector(16 downto 0);
|
|
variable fmt : isa_type_t;
|
|
variable rm : std_logic_vector(4 downto 0);
|
|
variable rn : std_logic_vector(4 downto 0);
|
|
begin
|
|
cond := std_logic_vector(TO_UNSIGNED(instruction_plane_t'pos(op.plane), 1)) & op.code;
|
|
fmt := isa_fmt(op.code);
|
|
rn := '0' & cond(11 downto 8);
|
|
rm := '0' & cond(7 downto 4);
|
|
-- Set default values for outputs
|
|
ilevel_cap <= '0';
|
|
mac_stall_sense <= '0';
|
|
dispatch <= '0';
|
|
event_ack_0 <= '0';
|
|
slp <= '0';
|
|
mac_s_latch <= '0';
|
|
ex_stall <= ('0', '0', '0', '0', SEL_ARITH, SEL_PREV, SEL_CLEAR, SEL_ZBUS, SEL_YBUS, '0', '0', '0', LOGIC, '0', NOP, SEL_XBUS, SEL_YBUS);
|
|
debug <= '0';
|
|
wb_stall <= ('0', '0', '0', '0', '0', SEL_XBUS, SEL_YBUS, NOP);
|
|
delay_jump <= '0';
|
|
id <= ('0', '0', '0');
|
|
maskint_next <= '0';
|
|
ex.arith_func <= ADD;
|
|
ex.aluinx_sel <= SEL_XBUS;
|
|
ex.alumanip <= SWAP_BYTE;
|
|
ex.aluiny_sel <= SEL_YBUS;
|
|
ex.arith_ci_en <= '0';
|
|
ex.xbus_sel <= SEL_REG;
|
|
wb.regnum_w <= rn;
|
|
ex.regnum_x <= rn;
|
|
ex.mem_size <= LONG;
|
|
ex.regnum_y <= rm;
|
|
ex.regnum_z <= rn;
|
|
ex.ma_wr <= '0';
|
|
ex.logic_sr_func <= ZERO;
|
|
ex.logic_func <= LOGIC_XOR;
|
|
ex.ybus_sel <= SEL_REG;
|
|
ex.mem_lock <= '0';
|
|
ex.arith_sr_func <= ZERO;
|
|
imm_enum <= IMM_P4;
|
|
mac_busy <= NOT_BUSY;
|
|
|
|
-- if fmt.fmt = NMX and
|
|
-- ((fmt.ln = "0000" and fmt.op(0) = '1') or
|
|
-- ((fmt.ln = "0010" or fmt.ln = "0110") and fmt.op(1 downto 0) = "00"))
|
|
if (std_match(cond, "00000---------1--") or std_match(cond, "00-10--------00--") or std_match(cond, "00010--------01--"))
|
|
and cond(1 downto 0) /= "11" then
|
|
-- MOV.B Rm,@-Rn [2nm4]
|
|
-- MOV.BWL Rm, @Rn [2nm0]
|
|
-- MOV.BWL @Rm, Rn [6nm0]
|
|
-- MOV.BWL Rm, @(R0, Rn) [0nm4]
|
|
-- MOV.BWL @(R0, Rm), Rn [0nmC]
|
|
-- (R0 +Rm)->sign extension -> Rn
|
|
-- X = Rm
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
if (cond(3) or cond(14)) = '1' then ex.regnum_x <= rm; end if;
|
|
-- ex.regnum_x <= rn; end if;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = X + R0
|
|
if cond(13) = '1' then ex.aluiny_sel <= SEL_IMM; ex.arith_func <= SUB;
|
|
else ex.aluiny_sel <= SEL_R0; end if;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
if cond(1 downto 0) = "00" then imm_enum <= IMM_P1;
|
|
elsif cond(1 downto 0) = "01" then imm_enum <= IMM_P2; end if;
|
|
-- else imm_enum <= IMM_P4; end if;
|
|
-- ex.arith_func <= ADD;
|
|
-- W = MEM[Z] or MEM[X]
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= not (cond(3) or cond(14));
|
|
if cond(13) = '1' and cond(2) = '0' then ex_stall.mem_addr_sel <= SEL_XBUS;
|
|
-- else ex_stall.mem_addr_sel <= SEL_ZBUS; end if;
|
|
end if;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
ex.mem_size <= fmt.sz;
|
|
-- Rn = W
|
|
if (cond(2) and cond(13)) = '1' then ex_stall.wrreg_z <= '1';
|
|
elsif (cond(3) or cond(14)) = '1' then wb_stall.wrreg_w <= '1'; end if;
|
|
-- ex.regnum_z <= rn;
|
|
-- wb.regnum_w <= rn;
|
|
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00110--------01--") and cond(1 downto 0) /= "11" then
|
|
-- MOV.BWL @Rm+, Rn [6nm4]
|
|
-- (Rm) -> sign extension -> Rn, Rm +1 ->Rm : Note: add first in case Rm=Rn
|
|
if cond(1 downto 0) = "00" then imm_enum <= IMM_P1;
|
|
elsif cond(1 downto 0) = "01" then imm_enum <= IMM_P2; end if;
|
|
-- else imm_enum <= IMM_P4; end if;
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = Rm
|
|
--- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= rm;
|
|
-- Z = X + 1
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- Rm = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= rm;
|
|
|
|
when x"1" =>
|
|
-- X = Rm
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= rm;
|
|
-- Z = X - 1
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- W = MEM[Z] byte
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
ex.mem_size <= fmt.sz;
|
|
-- Rn = W
|
|
wb_stall.wrreg_w <= '1';
|
|
-- wb.regnum_w <= rn;
|
|
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
|
|
elsif std_match(cond, "011000-----------") and cond(10 downto 8) /= "011" then
|
|
-- MOV.BWL R0, @(disp, GBR) [C0dd]
|
|
-- MOV.BWL @(disp, GBR), R0 [C4dd]
|
|
-- MOVA @(disp, PC), R0 [C7dd]
|
|
-- R0-> (disp + GBR)
|
|
-- X = GBR
|
|
if cond(10 downto 8) = "111" then ex.xbus_sel <= SEL_PC; end if;
|
|
-- else ex.xbus_sel <= SEL_REG; end if;
|
|
ex.regnum_x <= "10000";
|
|
-- if MOVA, use PC
|
|
if cond(9 downto 8) = "11" then ex.aluinx_sel <= SEL_FC; end if;
|
|
-- Y = R0
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "00000";
|
|
-- Z = X + [:u 8 0]
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
if cond(9 downto 8) = "00" then imm_enum <= IMM_U_8_0;
|
|
elsif cond(9 downto 8) = "01" then imm_enum <= IMM_U_8_1;
|
|
else imm_enum <= IMM_U_8_2; end if;
|
|
|
|
-- MEM[Z] = Y byte W = MEM[Z] byte
|
|
ex_stall.ma_issue <= not (cond(10) and cond(9) and cond(8));
|
|
ex.ma_wr <= not cond(10);
|
|
wb_stall.wrreg_w <= cond(10) and not (cond(9) and cond(8));
|
|
ex_stall.wrreg_z <= cond(10) and cond(9) and cond(8);
|
|
wb.regnum_w <= "00000";
|
|
ex.regnum_z <= "00000";
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
ex.mem_size <= fmt.sz;
|
|
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "01101------------") then
|
|
-- MOV.L @(disp, PC), Rn [Dndd]
|
|
-- (disp x 4 + PC) -> Rn
|
|
-- X = PC
|
|
ex.xbus_sel <= SEL_PC;
|
|
-- Y = UCONST * 4
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = (X & FC) + Y
|
|
ex.aluinx_sel <= SEL_FC;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_U_8_2;
|
|
-- W = MEM[Z] long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- Rn = W
|
|
wb_stall.wrreg_w <= '1';
|
|
-- wb.regnum_w <= rn;
|
|
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
-- set control signals for each opcode
|
|
elsif std_match(cond, "00000000000001000") then
|
|
-- CLRT [0008]
|
|
-- 0 -> T
|
|
ex_stall.sr_sel <= SEL_SET_T;
|
|
ex_stall.t_sel <= SEL_CLEAR;
|
|
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00000000000101000") then
|
|
-- CLRMAC [0028]
|
|
-- 0 -> MACH, MACL
|
|
-- X = TEMP1
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "10100";
|
|
-- Y = TEMP1
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "10100";
|
|
-- Z = X xor Y
|
|
ex_stall.zbus_sel <= SEL_LOGIC;
|
|
-- ex.logic_func <= LOGIC_XOR;
|
|
ex_stall.macsel1 <= SEL_ZBUS;
|
|
ex_stall.macsel2 <= SEL_ZBUS;
|
|
ex_stall.wrmacl <= '1';
|
|
ex_stall.wrmach <= '1';
|
|
mac_stall_sense <= '1';
|
|
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00000000000011001") then
|
|
-- DIV0U [0019]
|
|
-- 0 -> M/Q/T
|
|
ex_stall.sr_sel <= SEL_DIV0U;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00000000000001001") then
|
|
-- NOP [0009]
|
|
-- no operation
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00000000000101011") then
|
|
-- RTE [002B]
|
|
-- Delayed branch, stack -> PC/SR
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = R15
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "01111";
|
|
-- Z = X + 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- imm_enum <= IMM_P4;
|
|
-- W = MEM[X] long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
ex_stall.mem_addr_sel <= SEL_XBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- R15 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "01111";
|
|
id.incpc <= '1';
|
|
|
|
when x"1" =>
|
|
-- X = R15
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "01111";
|
|
-- Z = X + 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
wb_stall.wrsr_w <= '1';
|
|
-- imm_enum <= IMM_P4;
|
|
-- W = MEM[X] long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
ex_stall.mem_addr_sel <= SEL_XBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- R15 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "01111";
|
|
|
|
when x"2" =>
|
|
ex_stall.zbus_sel <= SEL_WBUS;
|
|
-- PC = Z
|
|
ex_stall.wrpc_z <= '1';
|
|
|
|
when x"3" =>
|
|
id.ifadsel <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
delay_jump <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "00000000000001011") then
|
|
-- RTS [000B]
|
|
-- Delayed branch, PR -> PC
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- Y = PR
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "10010";
|
|
ex_stall.zbus_sel <= SEL_YBUS;
|
|
-- PC = Z
|
|
ex_stall.wrpc_z <= '1';
|
|
|
|
when x"1" =>
|
|
id.ifadsel <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
delay_jump <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "00000000000011000") then
|
|
-- SETT [0018]
|
|
-- 1 -> T
|
|
ex_stall.sr_sel <= SEL_SET_T;
|
|
ex_stall.t_sel <= SEL_SET;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00000000000011011") then
|
|
-- SLEEP [001B]
|
|
-- Sleep
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
|
|
when x"1" =>
|
|
slp <= '1';
|
|
|
|
when x"2" =>
|
|
|
|
when x"3" =>
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "00000000000111011") then
|
|
-- BGND [003B]
|
|
-- Sleep
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
debug <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00010101") then
|
|
-- CMP/PL Rn [4n15]
|
|
-- Rn > 0, 1 -> T
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = 0
|
|
ex.ybus_sel <= SEL_IMM;
|
|
ex.arith_sr_func <= SGRTER;
|
|
ex.arith_func <= SUB;
|
|
ex_stall.sr_sel <= SEL_ARITH;
|
|
imm_enum <= IMM_ZERO;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00010001") then
|
|
-- CMP/PZ Rn [4n11]
|
|
-- Rn >= 0, 1->T
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = 0
|
|
ex.ybus_sel <= SEL_IMM;
|
|
ex.arith_sr_func <= SGRTER_EQ;
|
|
ex.arith_func <= SUB;
|
|
ex_stall.sr_sel <= SEL_ARITH;
|
|
imm_enum <= IMM_ZERO;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00010000") then
|
|
-- DT Rn [4n10]
|
|
-- Rn-1 ->Rn; If Rn is 0, 1 -> T, if Rn is nonzero, 0 -> T
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = 1
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X - Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_sr_func <= ZERO;
|
|
ex.arith_func <= SUB;
|
|
ex_stall.sr_sel <= SEL_ARITH;
|
|
imm_enum <= IMM_P1;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00000----00101001") then
|
|
-- MOVT Rn [0n29]
|
|
-- T->Rn
|
|
-- X = 1
|
|
ex.xbus_sel <= SEL_IMM;
|
|
-- Y = SR
|
|
ex.ybus_sel <= SEL_SR;
|
|
-- Z = X and Y
|
|
ex_stall.zbus_sel <= SEL_LOGIC;
|
|
ex.logic_func <= LOGIC_AND;
|
|
imm_enum <= IMM_P1;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00000100") then
|
|
-- ROTL Rn [4n04]
|
|
-- T<-Rn<-MSB
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = 1
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X shift rotate Y
|
|
ex_stall.zbus_sel <= SEL_SHIFT;
|
|
ex_stall.shiftfunc <= ROTATE;
|
|
ex_stall.sr_sel <= SEL_SET_T;
|
|
ex_stall.t_sel <= SEL_SHIFT;
|
|
imm_enum <= IMM_P1;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00000101") then
|
|
-- ROTR Rn [4n05]
|
|
-- LSB->Rn->T
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = -1
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X shift rotate Y
|
|
ex_stall.zbus_sel <= SEL_SHIFT;
|
|
ex_stall.shiftfunc <= ROTATE;
|
|
ex_stall.sr_sel <= SEL_SET_T;
|
|
ex_stall.t_sel <= SEL_SHIFT;
|
|
imm_enum <= IMM_N1;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00100100") then
|
|
-- ROTCL Rn [4n24]
|
|
-- T<-Rn<-T
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = 1
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X shift rotatec Y
|
|
ex_stall.zbus_sel <= SEL_SHIFT;
|
|
ex_stall.shiftfunc <= ROTC;
|
|
ex_stall.sr_sel <= SEL_SET_T;
|
|
ex_stall.t_sel <= SEL_SHIFT;
|
|
imm_enum <= IMM_P1;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00100101") then
|
|
-- ROTCR Rn [4n25]
|
|
-- T->Rn->T
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = -1
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X shift rotatec Y
|
|
ex_stall.zbus_sel <= SEL_SHIFT;
|
|
ex_stall.shiftfunc <= ROTC;
|
|
ex_stall.sr_sel <= SEL_SET_T;
|
|
ex_stall.t_sel <= SEL_SHIFT;
|
|
imm_enum <= IMM_N1;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00100000") then
|
|
-- SHAL Rn [4n20]
|
|
-- T<-Rn<-0
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = 1
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X shift logic Y
|
|
ex_stall.zbus_sel <= SEL_SHIFT;
|
|
-- ex_stall.shiftfunc <= LOGIC;
|
|
ex_stall.sr_sel <= SEL_SET_T;
|
|
ex_stall.t_sel <= SEL_SHIFT;
|
|
imm_enum <= IMM_P1;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00100001") then
|
|
-- SHAR Rn [4n21]
|
|
-- MSB->Rn->T
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = -1
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X shift arith Y
|
|
ex_stall.zbus_sel <= SEL_SHIFT;
|
|
ex_stall.shiftfunc <= ARITH;
|
|
ex_stall.sr_sel <= SEL_SET_T;
|
|
ex_stall.t_sel <= SEL_SHIFT;
|
|
imm_enum <= IMM_N1;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00000000") then
|
|
-- SHLL Rn [4n00]
|
|
-- T<-Rn<-0
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = 1
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X shift logic Y
|
|
ex_stall.zbus_sel <= SEL_SHIFT;
|
|
-- ex_stall.shiftfunc <= LOGIC;
|
|
ex_stall.sr_sel <= SEL_SET_T;
|
|
ex_stall.t_sel <= SEL_SHIFT;
|
|
imm_enum <= IMM_P1;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00000001") then
|
|
-- SHLR Rn [4n01]
|
|
-- 0->Rn->T
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = -1
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X shift logic Y
|
|
ex_stall.zbus_sel <= SEL_SHIFT;
|
|
-- ex_stall.shiftfunc <= LOGIC;
|
|
ex_stall.sr_sel <= SEL_SET_T;
|
|
ex_stall.t_sel <= SEL_SHIFT;
|
|
imm_enum <= IMM_N1;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00001000") then
|
|
-- SHLL2 Rn [4n08]
|
|
-- Rn<<2 -> Rn
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = 2
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X shift logic Y
|
|
ex_stall.zbus_sel <= SEL_SHIFT;
|
|
-- ex_stall.shiftfunc <= LOGIC;
|
|
imm_enum <= IMM_P2;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00001001") then
|
|
-- SHLR2 Rn [4n09]
|
|
-- Rn>>2 -> Rn
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = -2
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X shift logic Y
|
|
ex_stall.zbus_sel <= SEL_SHIFT;
|
|
-- ex_stall.shiftfunc <= LOGIC;
|
|
imm_enum <= IMM_N2;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00011000") then
|
|
-- SHLL8 Rn [4n18]
|
|
-- Rn<<8 -> Rn
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = 8
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X shift logic Y
|
|
ex_stall.zbus_sel <= SEL_SHIFT;
|
|
-- ex_stall.shiftfunc <= LOGIC;
|
|
imm_enum <= IMM_P8;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00011001") then
|
|
-- SHLR8 Rn [4n19]
|
|
-- Rn>>8 -> Rn
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = -8
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X shift logic Y
|
|
ex_stall.zbus_sel <= SEL_SHIFT;
|
|
-- ex_stall.shiftfunc <= LOGIC;
|
|
imm_enum <= IMM_N8;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00101000") then
|
|
-- SHLL16 Rn [4n28]
|
|
-- Rn<<16 -> Rn
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = 16
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X shift logic Y
|
|
ex_stall.zbus_sel <= SEL_SHIFT;
|
|
-- ex_stall.shiftfunc <= LOGIC;
|
|
imm_enum <= IMM_P16;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00101001") then
|
|
-- SHLR16 Rn [4n29]
|
|
-- Rn>>16 -> Rn
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = -16
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X shift logic Y
|
|
ex_stall.zbus_sel <= SEL_SHIFT;
|
|
-- ex_stall.shiftfunc <= LOGIC;
|
|
imm_enum <= IMM_N16;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00000----00000010") then
|
|
-- STC SR, Rn [0n02]
|
|
-- SR->Rn
|
|
-- Y = SR
|
|
ex.ybus_sel <= SEL_SR;
|
|
ex_stall.zbus_sel <= SEL_YBUS;
|
|
maskint_next <= '1';
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00000----00010010") then
|
|
-- STC GBR, Rn [0n12]
|
|
-- GBR->Rn
|
|
-- Y = GBR
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "10000";
|
|
ex_stall.zbus_sel <= SEL_YBUS;
|
|
maskint_next <= '1';
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00000----00100010") then
|
|
-- STC VBR, Rn [0n22]
|
|
-- VBR->Rn
|
|
-- Y = VBR
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "10001";
|
|
ex_stall.zbus_sel <= SEL_YBUS;
|
|
maskint_next <= '1';
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00000----00001010") then
|
|
-- STS MACH, Rn [0n0A]
|
|
-- MACH->Rn
|
|
-- Y = MACH
|
|
ex.ybus_sel <= SEL_MACH;
|
|
ex_stall.zbus_sel <= SEL_YBUS;
|
|
mac_stall_sense <= '1';
|
|
maskint_next <= '1';
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00000----00011010") then
|
|
-- STS MACL, Rn [0n1A]
|
|
-- MACL->Rn
|
|
-- Y = MACL
|
|
ex.ybus_sel <= SEL_MACL;
|
|
ex_stall.zbus_sel <= SEL_YBUS;
|
|
mac_stall_sense <= '1';
|
|
maskint_next <= '1';
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00000----00101010") then
|
|
-- STS PR, Rn [0n2A]
|
|
-- PR->Rn
|
|
-- Y = PR
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "10010";
|
|
ex_stall.zbus_sel <= SEL_YBUS;
|
|
maskint_next <= '1';
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00011011") then
|
|
-- TAS.B @Rn [4n1B]
|
|
-- When (Rn) is 0, 1 -> T, 1 -> MSB of (Rn)
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- W = MEM[X] byte
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
ex_stall.mem_addr_sel <= SEL_XBUS;
|
|
ex.mem_size <= BYTE;
|
|
ex.mem_lock <= '1';
|
|
-- TEMP0 = W
|
|
wb_stall.wrreg_w <= '1';
|
|
wb.regnum_w <= "10011";
|
|
|
|
when x"1" =>
|
|
ex.mem_lock <= '1';
|
|
|
|
when x"2" =>
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = TEMP0
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "10011";
|
|
-- Z = 0 :bit7 Y
|
|
ex.aluinx_sel <= SEL_ZERO;
|
|
ex_stall.zbus_sel <= SEL_MANIP;
|
|
ex.alumanip <= SET_BIT_7;
|
|
-- ex.arith_sr_func <= ZERO;
|
|
-- ex.arith_func <= ADD;
|
|
ex_stall.sr_sel <= SEL_ARITH;
|
|
-- MEM[X] = Z byte
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
ex_stall.mem_addr_sel <= SEL_XBUS;
|
|
ex_stall.mem_wdata_sel <= SEL_ZBUS;
|
|
ex.mem_size <= BYTE;
|
|
ex.mem_lock <= '1';
|
|
|
|
when x"3" =>
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "00100----00000011") then
|
|
-- STC.L SR, @-Rn [4n03]
|
|
-- Rn-4 ->Rn,SR ->(Rn)
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = SR
|
|
ex.ybus_sel <= SEL_SR;
|
|
-- Z = X - 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- imm_enum <= IMM_P4;
|
|
maskint_next <= '1';
|
|
-- MEM[Z] = Y long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00010011") then
|
|
-- STC.L GBR, @-Rn [4n13]
|
|
-- Rn-4 ->Rn,GBR ->(Rn)
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = GBR
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "10000";
|
|
-- Z = X - 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- imm_enum <= IMM_P4;
|
|
maskint_next <= '1';
|
|
-- MEM[Z] = Y long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00100011") then
|
|
-- STC.L VBR, @-Rn [4n23]
|
|
-- Rn - 4 -> Rn, VBR -> (Rn)
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = VBR
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "10001";
|
|
-- Z = X - 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- imm_enum <= IMM_P4;
|
|
maskint_next <= '1';
|
|
-- MEM[Z] = Y long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00000010") then
|
|
-- STS.L MACH, @-Rn [4n02]
|
|
-- Rn - 4 -> Rn, MACH -> (Rn)
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = MACH
|
|
ex.ybus_sel <= SEL_MACH;
|
|
-- Z = X - 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- imm_enum <= IMM_P4;
|
|
mac_stall_sense <= '1';
|
|
maskint_next <= '1';
|
|
-- MEM[Z] = Y long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00010010") then
|
|
-- STS.L MACL, @-Rn [4n12]
|
|
-- Rn-4->Rn,MACL->(Rn)
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = MACL
|
|
ex.ybus_sel <= SEL_MACL;
|
|
-- Z = X - 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- imm_enum <= IMM_P4;
|
|
mac_stall_sense <= '1';
|
|
maskint_next <= '1';
|
|
-- MEM[Z] = Y long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00100010") then
|
|
-- STS.L PR, @-Rn [4n22]
|
|
-- Rn-4->Rn,PR->(Rn)
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = PR
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "10010";
|
|
-- Z = X - 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- imm_enum <= IMM_P4;
|
|
maskint_next <= '1';
|
|
-- MEM[Z] = Y long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00001110") then
|
|
-- LDC Rm, SR [4m0E]
|
|
-- Rm -> SR
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= rn;
|
|
ex_stall.zbus_sel <= SEL_YBUS;
|
|
ex_stall.sr_sel <= SEL_ZBUS;
|
|
maskint_next <= '1';
|
|
-- SR = Z
|
|
ex_stall.wrsr_z <= '1';
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00011110") then
|
|
-- LDC, Rm, GBR [4m1E]
|
|
-- Rm -> GBR
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= rn;
|
|
ex_stall.zbus_sel <= SEL_YBUS;
|
|
maskint_next <= '1';
|
|
-- GBR = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "10000";
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00101110") then
|
|
-- LDC Rm, VBR [4m2E]
|
|
-- Rm -> VBR
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= rn;
|
|
ex_stall.zbus_sel <= SEL_YBUS;
|
|
maskint_next <= '1';
|
|
-- VBR = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "10001";
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00001010") then
|
|
-- LDS Rm, MACH [4m0A]
|
|
-- Rm-> MACH
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= rn;
|
|
ex_stall.zbus_sel <= SEL_YBUS;
|
|
ex_stall.macsel1 <= SEL_ZBUS;
|
|
ex_stall.wrmach <= '1';
|
|
mac_stall_sense <= '1';
|
|
maskint_next <= '1';
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00011010") then
|
|
-- LDS Rm, MACL [4m1A]
|
|
-- Rm -> MACL
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= rn;
|
|
ex_stall.zbus_sel <= SEL_YBUS;
|
|
ex_stall.macsel2 <= SEL_ZBUS;
|
|
ex_stall.wrmacl <= '1';
|
|
mac_stall_sense <= '1';
|
|
maskint_next <= '1';
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00101010") then
|
|
-- LDS Rm, PR [4m2A]
|
|
-- Rm -> PR
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= rn;
|
|
ex_stall.zbus_sel <= SEL_YBUS;
|
|
maskint_next <= '1';
|
|
-- PR = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "10010";
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00101011") then
|
|
-- JMP @Rm [4m2B]
|
|
-- Rm -> PC
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = Rm
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Z = X + 0
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_ZERO;
|
|
-- PC = Z
|
|
ex_stall.wrpc_z <= '1';
|
|
id.incpc <= '1';
|
|
|
|
when x"1" =>
|
|
id.ifadsel <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
delay_jump <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "00100----00001011") then
|
|
-- JSR @Rm [4m0B]
|
|
-- PC -> PR, Rm -> PC
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = Rm
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Z = X + 0
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_ZERO;
|
|
-- PC = Z
|
|
ex_stall.wrpc_z <= '1';
|
|
-- PR = PC
|
|
ex_stall.wrpr_pc <= '1';
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "10010";
|
|
id.incpc <= '1';
|
|
|
|
when x"1" =>
|
|
id.ifadsel <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
delay_jump <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "00100----00000111") then
|
|
-- LDC.L @Rm+, SR [4m07]
|
|
-- (Rm)->SR,Rm+4->Rm
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = Rm
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
wb_stall.wrsr_w <= '1';
|
|
-- W = MEM[X] long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
ex_stall.mem_addr_sel <= SEL_XBUS;
|
|
-- ex.mem_size <= LONG;
|
|
|
|
when x"1" =>
|
|
-- X = Rm
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Z = X + 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- imm_enum <= IMM_P4;
|
|
-- Rm = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
|
|
when x"2" =>
|
|
maskint_next <= '1';
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "00100----00010111") then
|
|
-- LDC.L @Rm+, GBR [4m17]
|
|
-- (Rm)->GBR,Rm+4->Rm
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = Rm
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- W = MEM[X] long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
ex_stall.mem_addr_sel <= SEL_XBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- GBR = W
|
|
wb_stall.wrreg_w <= '1';
|
|
wb.regnum_w <= "10000";
|
|
|
|
when x"1" =>
|
|
-- X = Rm
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Z = X + 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- imm_enum <= IMM_P4;
|
|
-- Rm = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
|
|
when x"2" =>
|
|
maskint_next <= '1';
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "00100----00100111") then
|
|
-- LDC.L @Rm+, VBR [4m27]
|
|
-- (Rm)->VBR,Rm+4->Rm
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = Rm
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- W = MEM[X] long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
ex_stall.mem_addr_sel <= SEL_XBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- VBR = W
|
|
wb_stall.wrreg_w <= '1';
|
|
wb.regnum_w <= "10001";
|
|
|
|
when x"1" =>
|
|
-- X = Rm
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Z = X + 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- imm_enum <= IMM_P4;
|
|
-- Rm = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
|
|
when x"2" =>
|
|
maskint_next <= '1';
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "00100----00000110") then
|
|
-- LDS.L @Rm+, MACH [4m06]
|
|
-- (Rm)->MACH,Rm+4->Rm
|
|
-- X = Rm
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Z = X + 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- imm_enum <= IMM_P4;
|
|
wb_stall.macsel1 <= SEL_WBUS;
|
|
wb_stall.wrmach <= '1';
|
|
mac_busy <= WB_NOT_STALL;
|
|
mac_stall_sense <= '1';
|
|
maskint_next <= '1';
|
|
-- W = MEM[X] long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
ex_stall.mem_addr_sel <= SEL_XBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- Rm = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00010110") then
|
|
-- LDS.L @Rm+, MACL [4m16]
|
|
-- (Rm)->MACL,Rm+4->Rm
|
|
-- X = Rm
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Z = X + 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- imm_enum <= IMM_P4;
|
|
wb_stall.macsel2 <= SEL_WBUS;
|
|
wb_stall.wrmacl <= '1';
|
|
mac_busy <= WB_NOT_STALL;
|
|
mac_stall_sense <= '1';
|
|
maskint_next <= '1';
|
|
-- W = MEM[X] long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
ex_stall.mem_addr_sel <= SEL_XBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- Rm = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100----00100110") then
|
|
-- LDS.L @Rm+, PR [4m26]
|
|
-- (Rm)->PR,Rm+4->Rm
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = Rm
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
maskint_next <= '1';
|
|
-- W = MEM[X] long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
ex_stall.mem_addr_sel <= SEL_XBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- PR = W
|
|
wb_stall.wrreg_w <= '1';
|
|
wb.regnum_w <= "10010";
|
|
|
|
when x"1" =>
|
|
-- X = Rm
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Z = X + 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- imm_enum <= IMM_P4;
|
|
maskint_next <= '1';
|
|
-- Rm = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "00000----00100011") then
|
|
-- BRAF Rm [0m23]
|
|
-- Delayed branch, Rm + PC -> PC
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = PC
|
|
ex.xbus_sel <= SEL_PC;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= rn;
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- PC = Z
|
|
ex_stall.wrpc_z <= '1';
|
|
id.incpc <= '1';
|
|
|
|
when x"1" =>
|
|
id.ifadsel <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
delay_jump <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "00000----00000011") then
|
|
-- BSRF Rm [0m03]
|
|
-- Delayed branch, PC -> PR, Rm + PC -> PC
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = PC
|
|
ex.xbus_sel <= SEL_PC;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= rn;
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- PC = Z
|
|
ex_stall.wrpc_z <= '1';
|
|
-- PR = PC
|
|
ex_stall.wrpr_pc <= '1';
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "10010";
|
|
id.incpc <= '1';
|
|
|
|
when x"1" =>
|
|
id.ifadsel <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
delay_jump <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "00011--------1100") then
|
|
-- ADD Rm, Rn [3nmC]
|
|
-- Rn+Rm->Rn
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00011--------1110") then
|
|
-- ADDC Rm, Rn [3nmE]
|
|
-- Rn + Rm + T -> Rn, carry ->T
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
ex.arith_ci_en <= '1';
|
|
ex_stall.sr_sel <= SEL_SET_T;
|
|
ex_stall.t_sel <= SEL_CARRY;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00011--------1111") then
|
|
-- ADDV Rm, Rn [3nmF]
|
|
-- Rn + Rm -> Rn, overflow ->T
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_sr_func <= OVERUNDERFLOW;
|
|
-- ex.arith_func <= ADD;
|
|
ex_stall.sr_sel <= SEL_ARITH;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00010--------1001") then
|
|
-- AND Rm, Rn [2nm9]
|
|
-- Rn&Rm->Rn
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = X and Y
|
|
ex_stall.zbus_sel <= SEL_LOGIC;
|
|
ex.logic_func <= LOGIC_AND;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00011--------0000") then
|
|
-- CMP /EQ Rm, Rn [3nm0]
|
|
-- When Rn=Rm,1->T
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- ex.logic_sr_func <= ZERO;
|
|
-- ex.logic_func <= LOGIC_XOR;
|
|
ex_stall.sr_sel <= SEL_LOGIC;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00011--------0010") then
|
|
-- CMP /HS Rm, Rn [3nm2]
|
|
-- When unsigned and Rn >= Rm,1->T
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
ex.arith_sr_func <= UGRTER_EQ;
|
|
ex.arith_func <= SUB;
|
|
ex_stall.sr_sel <= SEL_ARITH;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00011--------0011") then
|
|
-- CMP /GE Rm, Rn [3nm3]
|
|
-- When signed and Rn >= Rm,1->T
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
ex.arith_sr_func <= SGRTER_EQ;
|
|
ex.arith_func <= SUB;
|
|
ex_stall.sr_sel <= SEL_ARITH;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00011--------0110") then
|
|
-- CMP /HI Rm, Rn [3nm6]
|
|
-- When unsigned and Rn > Rm,1->T
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
ex.arith_sr_func <= UGRTER;
|
|
ex.arith_func <= SUB;
|
|
ex_stall.sr_sel <= SEL_ARITH;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00011--------0111") then
|
|
-- CMP /GT Rm, Rn [3nm7]
|
|
-- When signed and Rn > Rm,1->T
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
ex.arith_sr_func <= SGRTER;
|
|
ex.arith_func <= SUB;
|
|
ex_stall.sr_sel <= SEL_ARITH;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00010--------1100") then
|
|
-- CMP /STR Rm, Rn [2nmC]
|
|
-- When a byte in Rn equals a byte in Rm, 1-> T
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
ex.logic_sr_func <= BYTE_EQ;
|
|
-- ex.logic_func <= LOGIC_XOR;
|
|
ex_stall.sr_sel <= SEL_LOGIC;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00010--------0011") then
|
|
-- CAS Rm, Rn, @R0 [2nm3]
|
|
-- When a byte in Rn equals a byte in Rm, 1-> T
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- Y = Rn
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= rn;
|
|
ex_stall.zbus_sel <= SEL_YBUS;
|
|
-- TEMP0 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "10011";
|
|
|
|
when x"1" =>
|
|
-- X = R0
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "00000";
|
|
-- W = MEM[X] long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
ex_stall.mem_addr_sel <= SEL_XBUS;
|
|
-- ex.mem_size <= LONG;
|
|
ex.mem_lock <= '1';
|
|
-- Rn = W
|
|
wb_stall.wrreg_w <= '1';
|
|
-- wb.regnum_w <= rn;
|
|
|
|
when x"2" =>
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- ex.logic_sr_func <= ZERO;
|
|
-- ex.logic_func <= LOGIC_XOR;
|
|
ex_stall.sr_sel <= SEL_LOGIC;
|
|
ex.mem_lock <= '1';
|
|
|
|
when x"3" =>
|
|
ex.mem_lock <= '1';
|
|
id.incpc <= '1';
|
|
dispatch <= not t_bcc;
|
|
id.if_issue <= not t_bcc;
|
|
|
|
when x"4" =>
|
|
-- X = R0
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "00000";
|
|
-- Y = TEMP0
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "10011";
|
|
-- MEM[X] = Y long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
ex_stall.mem_addr_sel <= SEL_XBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
-- ex.mem_size <= LONG;
|
|
ex.mem_lock <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "00011--------0100") then
|
|
-- DIV1 Rm, Rn [3nm4]
|
|
-- 1-step division (Rn ÷ Rm)
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = (2*X + T) + Y
|
|
ex.aluinx_sel <= SEL_ROTCL;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_sr_func <= DIV1;
|
|
-- ex.arith_func <= ADD;
|
|
ex_stall.sr_sel <= SEL_ARITH;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00010--------0111") then
|
|
-- DIV0S Rm, Rn [2nm7]
|
|
-- MSB of Rn-> Q, MSB of Rm->M,M^Q->T
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
ex.arith_sr_func <= DIV0S;
|
|
-- ex.arith_func <= ADD;
|
|
ex_stall.sr_sel <= SEL_ARITH;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00011--------1101") then
|
|
-- DMULS.L Rm, Rn [3nmD]
|
|
-- Signed, Rn x Rm, MACH, MACL
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- ex_stall.macsel1 <= SEL_XBUS;
|
|
ex_stall.mulcom1 <= '1';
|
|
-- ex_stall.macsel2 <= SEL_YBUS;
|
|
ex_stall.mulcom2 <= DMULSL;
|
|
mac_busy <= EX_NOT_STALL;
|
|
mac_stall_sense <= '1';
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00011--------0101") then
|
|
-- DMULU.L Rm, Rn [3nm5]
|
|
-- Unsigned, Rn x Rm, MACH, MACL
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- ex_stall.macsel1 <= SEL_XBUS;
|
|
ex_stall.mulcom1 <= '1';
|
|
-- ex_stall.macsel2 <= SEL_YBUS;
|
|
ex_stall.mulcom2 <= DMULUL;
|
|
mac_busy <= EX_NOT_STALL;
|
|
mac_stall_sense <= '1';
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00110--------1110") then
|
|
-- EXTS.B Rm, Rn [6nmE]
|
|
-- Sign-extends Rm from byte -> Rn
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm);
|
|
-- Z = (int8) Y
|
|
ex_stall.zbus_sel <= SEL_MANIP;
|
|
ex.alumanip <= EXTEND_SBYTE;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00110--------1111") then
|
|
-- EXTS.W Rm, Rn [6nmF]
|
|
-- Sign-extends Rm from word -> Rn
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = (int16) Y
|
|
ex_stall.zbus_sel <= SEL_MANIP;
|
|
ex.alumanip <= EXTEND_SWORD;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00110--------1100") then
|
|
-- EXTU.B Rm, Rn [6nmC]
|
|
-- Zero-extends Rm from byte -> Rn
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = (uint8) Y
|
|
ex_stall.zbus_sel <= SEL_MANIP;
|
|
ex.alumanip <= EXTEND_UBYTE;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00110--------1101") then
|
|
-- EXTU.W Rm, Rn [6nmD]
|
|
-- Zero-extends Rm from word -> Rn
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = (uint16) Y
|
|
ex_stall.zbus_sel <= SEL_MANIP;
|
|
ex.alumanip <= EXTEND_UWORD;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00110--------0011") then
|
|
-- MOV Rm, Rn [6nm3]
|
|
-- Rm->Rn
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
ex_stall.zbus_sel <= SEL_YBUS;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00000--------0111") then
|
|
-- MUL.L Rm, Rn [0nm7]
|
|
-- RnxRm->MACL
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- ex_stall.macsel1 <= SEL_XBUS;
|
|
ex_stall.mulcom1 <= '1';
|
|
-- ex_stall.macsel2 <= SEL_YBUS;
|
|
ex_stall.mulcom2 <= MULL;
|
|
mac_busy <= EX_NOT_STALL;
|
|
mac_stall_sense <= '1';
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00010--------1111") then
|
|
-- MULS.W Rm, Rn [2nmF]
|
|
-- Signed, Rn x Rm -> MAC
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- ex_stall.macsel1 <= SEL_XBUS;
|
|
ex_stall.mulcom1 <= '1';
|
|
-- ex_stall.macsel2 <= SEL_YBUS;
|
|
ex_stall.mulcom2 <= MULSW;
|
|
mac_busy <= EX_NOT_STALL;
|
|
mac_stall_sense <= '1';
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00010--------1110") then
|
|
-- MULU.W Rm, Rn [2nmE]
|
|
-- Unsigned, Rn x Rm -> MAC
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- ex_stall.macsel1 <= SEL_XBUS;
|
|
ex_stall.mulcom1 <= '1';
|
|
-- ex_stall.macsel2 <= SEL_YBUS;
|
|
ex_stall.mulcom2 <= MULUW;
|
|
mac_busy <= EX_NOT_STALL;
|
|
mac_stall_sense <= '1';
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00110--------1011") then
|
|
-- NEG Rm, Rn [6nmB]
|
|
-- 0-Rm->Rn
|
|
-- X = 0
|
|
ex.xbus_sel <= SEL_IMM;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = X - Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
imm_enum <= IMM_ZERO;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00110--------1010") then
|
|
-- NEGC Rm, Rn [6nmA]
|
|
-- 0-Rm-T -> Rn, borrow ->T
|
|
-- X = 0
|
|
ex.xbus_sel <= SEL_IMM;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = X - Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
ex.arith_ci_en <= '1';
|
|
ex_stall.sr_sel <= SEL_SET_T;
|
|
ex_stall.t_sel <= SEL_CARRY;
|
|
imm_enum <= IMM_ZERO;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00110--------0111") then
|
|
-- NOT Rm, Rn [6nm7]
|
|
-- ~Rm->Rn
|
|
-- X = 0
|
|
ex.xbus_sel <= SEL_IMM;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = X not Y
|
|
ex_stall.zbus_sel <= SEL_LOGIC;
|
|
ex.logic_func <= LOGIC_NOT;
|
|
imm_enum <= IMM_ZERO;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00010--------1011") then
|
|
-- OR Rm, Rn [2nmB]
|
|
-- Rn | Rm-> Rn
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = X or Y
|
|
ex_stall.zbus_sel <= SEL_LOGIC;
|
|
ex.logic_func <= LOGIC_OR;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00011--------1000") then
|
|
-- SUB Rm, Rn [3nm8]
|
|
-- Rn - Rm ->Rn
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = X - Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00011--------1010") then
|
|
-- SUBC Rm, Rn [3nmA]
|
|
-- Rn - Rm-T ->Rn, borrow -> T
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = X - Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
ex.arith_ci_en <= '1';
|
|
ex_stall.sr_sel <= SEL_SET_T;
|
|
ex_stall.t_sel <= SEL_CARRY;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00011--------1011") then
|
|
-- SUBV Rm, Rn [3nmB]
|
|
-- Rn - Rm -> Rn, underflow ->T
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = X - Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_sr_func <= OVERUNDERFLOW;
|
|
ex.arith_func <= SUB;
|
|
ex_stall.sr_sel <= SEL_ARITH;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00110--------1000") then
|
|
-- SWAP.B Rm, Rn [6nm8]
|
|
-- Rm -> Swap upper and lower halves of lower 2 bytes -> Rn
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = X [:swap :b] Y
|
|
ex_stall.zbus_sel <= SEL_MANIP;
|
|
-- ex.alumanip <= SWAP_BYTE;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00110--------1001") then
|
|
-- SWAP.W Rm, Rn [6nm9]
|
|
-- Rm -> Swap upper and lower word -> Rn
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = X [:swap :w] Y
|
|
ex_stall.zbus_sel <= SEL_MANIP;
|
|
ex.alumanip <= SWAP_WORD;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00010--------1000") then
|
|
-- TST Rm, Rn [2nm8]
|
|
-- Rn & Rm, when result is 0, 1 -> T
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- ex.logic_sr_func <= ZERO;
|
|
ex.logic_func <= LOGIC_AND;
|
|
ex_stall.sr_sel <= SEL_LOGIC;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00010--------1010") then
|
|
-- XOR Rm, Rn [2nmA]
|
|
-- Rn ^ Rm-> Rn
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = X xor Y
|
|
ex_stall.zbus_sel <= SEL_LOGIC;
|
|
-- ex.logic_func <= LOGIC_XOR;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00010--------1101") then
|
|
-- XTRACT Rm, Rn [2nmD]
|
|
-- Centre 32 bits of Rm and Rn -> Rn
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = X :xtract Y
|
|
ex_stall.zbus_sel <= SEL_MANIP;
|
|
ex.alumanip <= EXTRACT;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100--------1100") then
|
|
-- SHAD Rm, Rn [4nmC]
|
|
--
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = X shift arith Y
|
|
ex_stall.zbus_sel <= SEL_SHIFT;
|
|
ex_stall.shiftfunc <= ARITH;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00100--------1101") then
|
|
-- SHLD Rm, Rn [4nmD]
|
|
--
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = X shift logic Y
|
|
ex_stall.zbus_sel <= SEL_SHIFT;
|
|
-- ex_stall.shiftfunc <= LOGIC;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
|
|
elsif std_match(cond, "00000--------1111") then
|
|
-- MAC.L @Rm+, @Rn+ [0nmF]
|
|
-- Signed, (Rn) x (Rm) + MAC -> MAC
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Z = X + 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- imm_enum <= IMM_P4;
|
|
wb_stall.macsel1 <= SEL_WBUS;
|
|
wb_stall.mulcom1 <= '1';
|
|
-- W = MEM[X] long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
ex_stall.mem_addr_sel <= SEL_XBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
|
|
when x"1" =>
|
|
-- X = Rm
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= rm;
|
|
-- Z = X + 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- imm_enum <= IMM_P4;
|
|
wb_stall.macsel2 <= SEL_WBUS;
|
|
wb_stall.mulcom2 <= MACL;
|
|
mac_busy <= WB_BUSY;
|
|
mac_s_latch <= '1';
|
|
-- W = MEM[X] long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
ex_stall.mem_addr_sel <= SEL_XBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- Rm = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= rm;
|
|
|
|
when x"2" =>
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "00100--------1111") then
|
|
-- MAC.W @Rm+, @Rn+ [4nmF]
|
|
-- Signed, (Rn) x (Rm) + MAC -> MAC
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Z = X + 2
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_P2;
|
|
wb_stall.macsel1 <= SEL_WBUS;
|
|
wb_stall.mulcom1 <= '1';
|
|
-- W = MEM[X] word
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
ex_stall.mem_addr_sel <= SEL_XBUS;
|
|
ex.mem_size <= WORD;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
|
|
when x"1" =>
|
|
-- X = Rm
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= rm;
|
|
-- Z = X + 2
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_P2;
|
|
wb_stall.macsel2 <= SEL_WBUS;
|
|
wb_stall.mulcom2 <= MACW;
|
|
mac_busy <= WB_BUSY;
|
|
mac_s_latch <= '1';
|
|
-- W = MEM[X] word
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
ex_stall.mem_addr_sel <= SEL_XBUS;
|
|
ex.mem_size <= WORD;
|
|
-- Rm = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= rm;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
|
|
|
|
elsif std_match(cond, "010000100--------") then
|
|
-- MOV.B @(disp, Rm), R0 [84md]
|
|
-- (disp + Rm) -> sign extension -> R0
|
|
-- X = Rm
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= rm;
|
|
-- Z = X + [:u 4 0]
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_U_4_0;
|
|
-- W = MEM[Z] byte
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
ex.mem_size <= BYTE;
|
|
-- R0 = W
|
|
wb_stall.wrreg_w <= '1';
|
|
wb.regnum_w <= "00000";
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "010000101--------") then
|
|
-- MOV.W @(disp, Rm), R0 [85md]
|
|
-- (disp x2 +Rm)-> sign extension -> R0
|
|
-- X = Rm
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= rm;
|
|
-- Z = X + [:u 4 1]
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_U_4_1;
|
|
-- W = MEM[Z] word
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
ex.mem_size <= WORD;
|
|
-- R0 = W
|
|
wb_stall.wrreg_w <= '1';
|
|
wb.regnum_w <= "00000";
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "010000000--------") then
|
|
-- MOV.B R0, @(disp, Rn) [80nd]
|
|
-- R0 -> (disp + Rn)
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= rm;
|
|
-- Y = R0
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "00000";
|
|
-- Z = X + [:u 4 0]
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_U_4_0;
|
|
-- MEM[Z] = Y byte
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
ex.mem_size <= BYTE;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "010000001--------") then
|
|
-- MOV.W R0, @(disp, Rn) [81nd]
|
|
-- R0 -> (disp x 2+ Rn)
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= rm;
|
|
-- Y = R0
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "00000";
|
|
-- Z = X + [:u 4 1]
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_U_4_1;
|
|
-- MEM[Z] = Y word
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
ex.mem_size <= WORD;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00001------------") then
|
|
-- MOV.L Rm, @(disp, Rn) [1nmd]
|
|
-- Rm -> (disp x 4 + Rn)
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = Rm
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
-- ex.regnum_y <= rm;
|
|
-- Z = X + [:u 4 2]
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_U_4_2;
|
|
-- MEM[Z] = Y long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
-- ex.mem_size <= LONG;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "00101------------") then
|
|
-- MOV.L @(disp, Rm), Rn [5nmd]
|
|
-- (disp x 4+ Rm) -> Rn
|
|
-- X = Rm
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= rm;
|
|
-- Z = X + [:u 4 2]
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_U_4_2;
|
|
-- W = MEM[Z] long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- Rn = W
|
|
wb_stall.wrreg_w <= '1';
|
|
-- wb.regnum_w <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "010001011--------") then
|
|
-- BF label [8Bdd]
|
|
-- When T=0, disp x2+PC-> PC; When T = 1, nop
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = PC
|
|
ex.xbus_sel <= SEL_PC;
|
|
-- Y = CONST * 2
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_S_8_1;
|
|
-- if (not T) PC = Z
|
|
ex_stall.wrpc_z <= not t_bcc;
|
|
id.incpc <= '1';
|
|
dispatch <= t_bcc;
|
|
id.if_issue <= '1';
|
|
|
|
when x"1" =>
|
|
id.ifadsel <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when x"2" =>
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "010001111--------") then
|
|
-- BF /S label [8Fdd]
|
|
-- When T=0, disp x2+PC-> PC; When T = 1, nop
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = PC
|
|
ex.xbus_sel <= SEL_PC;
|
|
-- Y = CONST * 2
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_S_8_1;
|
|
-- if (not T) PC = Z
|
|
ex_stall.wrpc_z <= not t_bcc;
|
|
id.incpc <= '1';
|
|
dispatch <= t_bcc;
|
|
id.if_issue <= t_bcc;
|
|
|
|
when x"1" =>
|
|
id.ifadsel <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
delay_jump <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "010001001--------") then
|
|
-- BT label [89dd]
|
|
-- When T=1, disp x2+PC-> PC; When T = 0, nop
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = PC
|
|
ex.xbus_sel <= SEL_PC;
|
|
-- Y = CONST * 2
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_S_8_1;
|
|
-- if (T) PC = Z
|
|
ex_stall.wrpc_z <= t_bcc;
|
|
id.incpc <= '1';
|
|
dispatch <= not t_bcc;
|
|
id.if_issue <= '1';
|
|
|
|
when x"1" =>
|
|
id.ifadsel <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when x"2" =>
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "010001101--------") then
|
|
-- BT /S label [8Ddd]
|
|
-- When T=1, disp x2+PC-> PC; When T = 0, nop
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = PC
|
|
ex.xbus_sel <= SEL_PC;
|
|
-- Y = CONST * 2
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_S_8_1;
|
|
-- if (T) PC = Z
|
|
ex_stall.wrpc_z <= t_bcc;
|
|
id.incpc <= '1';
|
|
dispatch <= not t_bcc;
|
|
id.if_issue <= not t_bcc;
|
|
|
|
when x"1" =>
|
|
id.ifadsel <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
delay_jump <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "01010------------") then
|
|
-- BRA label [Addd]
|
|
-- Delayed branch, disp x 2+ PC -> PC
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = PC
|
|
ex.xbus_sel <= SEL_PC;
|
|
-- Y = CONST * 2
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_S_12_1;
|
|
-- PC = Z
|
|
ex_stall.wrpc_z <= '1';
|
|
id.incpc <= '1';
|
|
|
|
when x"1" =>
|
|
id.ifadsel <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
delay_jump <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "01011------------") then
|
|
-- BSR label [Bddd]
|
|
-- Delayed branching, PC -> PR, disp x 2 + PC -> PC
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = PC
|
|
ex.xbus_sel <= SEL_PC;
|
|
-- Y = CONST * 2
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_S_12_1;
|
|
-- PC = Z
|
|
ex_stall.wrpc_z <= '1';
|
|
-- PR = PC
|
|
ex_stall.wrpr_pc <= '1';
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "10010";
|
|
id.incpc <= '1';
|
|
|
|
when x"1" =>
|
|
id.ifadsel <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
delay_jump <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "01001------------") then
|
|
-- MOV.W @(disp, PC), Rn [9ndd]
|
|
-- (disp x 2 + PC) -> sign extension -> Rn
|
|
-- X = PC
|
|
ex.xbus_sel <= SEL_PC;
|
|
-- Y = UCONST * 2
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_U_8_1;
|
|
-- W = MEM[Z] word
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
ex.mem_size <= WORD;
|
|
-- Rn = W
|
|
wb_stall.wrreg_w <= '1';
|
|
-- wb.regnum_w <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "011001101--------") then
|
|
-- AND.B #imm, @(R0, GBR) [CDii]
|
|
-- (R0 + GBR) & imm -> (R0 + GBR)
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = GBR
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "10000";
|
|
-- Y = R0
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "00000";
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- W = MEM[Z] byte
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
ex.mem_size <= BYTE;
|
|
-- TEMP1 = W
|
|
wb_stall.wrreg_w <= '1';
|
|
wb.regnum_w <= "10100";
|
|
|
|
when x"1" =>
|
|
-- X = GBR
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "10000";
|
|
-- Y = R0
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "00000";
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- TEMP0 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "10011";
|
|
|
|
when x"2" =>
|
|
-- X = TEMP1
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "10100";
|
|
-- Y = TEMP0
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "10011";
|
|
-- Z = X and [:u 8 0]
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
ex_stall.zbus_sel <= SEL_LOGIC;
|
|
ex.logic_func <= LOGIC_AND;
|
|
imm_enum <= IMM_U_8_0;
|
|
-- MEM[Y] = Z byte
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
ex_stall.mem_addr_sel <= SEL_YBUS;
|
|
ex_stall.mem_wdata_sel <= SEL_ZBUS;
|
|
ex.mem_size <= BYTE;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "011001111--------") then
|
|
-- OR.B #imm, @(R0, GBR) [CFii]
|
|
-- (R0 + GBR) | imm -> (R0 + GBR)
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = GBR
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "10000";
|
|
-- Y = R0
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "00000";
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- W = MEM[Z] byte
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
ex.mem_size <= BYTE;
|
|
-- TEMP1 = W
|
|
wb_stall.wrreg_w <= '1';
|
|
wb.regnum_w <= "10100";
|
|
|
|
when x"1" =>
|
|
-- X = GBR
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "10000";
|
|
-- Y = R0
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "00000";
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- TEMP0 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "10011";
|
|
|
|
when x"2" =>
|
|
-- X = TEMP1
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "10100";
|
|
-- Y = TEMP0
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "10011";
|
|
-- Z = X or [:u 8 0]
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
ex_stall.zbus_sel <= SEL_LOGIC;
|
|
ex.logic_func <= LOGIC_OR;
|
|
imm_enum <= IMM_U_8_0;
|
|
-- MEM[Y] = Z byte
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
ex_stall.mem_addr_sel <= SEL_YBUS;
|
|
ex_stall.mem_wdata_sel <= SEL_ZBUS;
|
|
ex.mem_size <= BYTE;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "011001100--------") then
|
|
-- TST.B #imm, @(R0, GBR) [CCii]
|
|
-- (R0 + GBR) & imm, when result is 0, 1 -> T
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = GBR
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "10000";
|
|
-- Y = R0
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "00000";
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- W = MEM[Z] byte
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
ex.mem_size <= BYTE;
|
|
-- TEMP1 = W
|
|
wb_stall.wrreg_w <= '1';
|
|
wb.regnum_w <= "10100";
|
|
|
|
when x"1" =>
|
|
|
|
when x"2" =>
|
|
-- X = TEMP1
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "10100";
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex.logic_sr_func <= ZERO;
|
|
ex.logic_func <= LOGIC_AND;
|
|
ex_stall.sr_sel <= SEL_LOGIC;
|
|
imm_enum <= IMM_U_8_0;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "011001110--------") then
|
|
-- XOR.B #imm, @(R0, GBR) [CEii]
|
|
-- (R0 + GBR) ^ imm -> (R0 + GBR)
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = GBR
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "10000";
|
|
-- Y = R0
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "00000";
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- W = MEM[Z] byte
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
ex.mem_size <= BYTE;
|
|
-- TEMP1 = W
|
|
wb_stall.wrreg_w <= '1';
|
|
wb.regnum_w <= "10100";
|
|
|
|
when x"1" =>
|
|
-- X = GBR
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "10000";
|
|
-- Y = R0
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "00000";
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- TEMP0 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "10011";
|
|
|
|
when x"2" =>
|
|
-- X = TEMP1
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "10100";
|
|
-- Y = TEMP0
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "10011";
|
|
-- Z = X xor [:u 8 0]
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
ex_stall.zbus_sel <= SEL_LOGIC;
|
|
-- ex.logic_func <= LOGIC_XOR;
|
|
imm_enum <= IMM_U_8_0;
|
|
-- MEM[Y] = Z byte
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
ex_stall.mem_addr_sel <= SEL_YBUS;
|
|
ex_stall.mem_wdata_sel <= SEL_ZBUS;
|
|
ex.mem_size <= BYTE;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "011001001--------") then
|
|
-- AND #imm, R0 [C9ii]
|
|
-- R0 & imm->R0
|
|
-- X = R0
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "00000";
|
|
-- Y = UCONST
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X and Y
|
|
ex_stall.zbus_sel <= SEL_LOGIC;
|
|
ex.logic_func <= LOGIC_AND;
|
|
imm_enum <= IMM_U_8_0;
|
|
-- R0 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "00000";
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "010001000--------") then
|
|
-- CMP /EQ #imm, R0 [88ii]
|
|
-- When R0=imm,1->T
|
|
-- X = R0
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "00000";
|
|
-- Y = CONST
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- ex.logic_sr_func <= ZERO;
|
|
-- ex.logic_func <= LOGIC_XOR;
|
|
ex_stall.sr_sel <= SEL_LOGIC;
|
|
imm_enum <= IMM_S_8_0;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "011001011--------") then
|
|
-- OR #imm, R0 [CBii]
|
|
-- R0 | imm->R0
|
|
-- X = R0
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "00000";
|
|
-- Y = UCONST
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X or Y
|
|
ex_stall.zbus_sel <= SEL_LOGIC;
|
|
ex.logic_func <= LOGIC_OR;
|
|
imm_enum <= IMM_U_8_0;
|
|
-- R0 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "00000";
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "011001000--------") then
|
|
-- TST #imm, R0 [C8ii]
|
|
-- R0 & imm, when result is 0, 1 -> T
|
|
-- X = R0
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "00000";
|
|
-- Y = UCONST
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- ex.logic_sr_func <= ZERO;
|
|
ex.logic_func <= LOGIC_AND;
|
|
ex_stall.sr_sel <= SEL_LOGIC;
|
|
imm_enum <= IMM_U_8_0;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "011001010--------") then
|
|
-- XOR #imm, R0 [CAii]
|
|
-- R0 ^ imm->R0
|
|
-- X = R0
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "00000";
|
|
-- Y = UCONST
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X xor Y
|
|
ex_stall.zbus_sel <= SEL_LOGIC;
|
|
-- ex.logic_func <= LOGIC_XOR;
|
|
imm_enum <= IMM_U_8_0;
|
|
-- R0 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "00000";
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "011000011--------") then
|
|
-- TRAPA #imm [C3ii]
|
|
-- PC/SR -> Stack area, (imm x 4 + VBR) -> PC
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = R15
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "01111";
|
|
-- Y = SR
|
|
ex.ybus_sel <= SEL_SR;
|
|
-- Z = X - 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- imm_enum <= IMM_P4;
|
|
-- MEM[Z] = Y long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- R15 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "01111";
|
|
|
|
when x"1" =>
|
|
-- X = R15
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "01111";
|
|
-- Y = PC
|
|
ex.ybus_sel <= SEL_PC;
|
|
-- Z = X - 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- imm_enum <= IMM_P4;
|
|
-- MEM[Z] = Y long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- R15 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "01111";
|
|
|
|
when x"2" =>
|
|
-- X = UCONST * 4
|
|
ex.xbus_sel <= SEL_IMM;
|
|
-- Y = VBR
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "10001";
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_U_8_2;
|
|
-- W = MEM[Z] long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex.mem_size <= LONG;
|
|
|
|
when x"3" =>
|
|
|
|
when x"4" =>
|
|
ex_stall.zbus_sel <= SEL_WBUS;
|
|
-- PC = Z
|
|
ex_stall.wrpc_z <= '1';
|
|
|
|
when x"5" =>
|
|
id.ifadsel <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when x"6" =>
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "00111------------") then
|
|
-- ADD #imm, Rn [7nii]
|
|
-- Rn + imm -> Rn
|
|
-- X = Rn
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
-- ex.regnum_x <= rn;
|
|
-- Y = CONST
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_S_8_0;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "01110------------") then
|
|
-- MOV #imm, Rn [Enii]
|
|
-- imm -> sign extension -> Rn
|
|
-- Y = CONST
|
|
ex.ybus_sel <= SEL_IMM;
|
|
ex_stall.zbus_sel <= SEL_YBUS;
|
|
imm_enum <= IMM_S_8_0;
|
|
-- Rn = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
-- ex.regnum_z <= rn;
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
elsif std_match(cond, "1-----111--------") then
|
|
-- General Illegal [-(-111)dd]
|
|
--
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = PC
|
|
ex.xbus_sel <= SEL_PC;
|
|
-- Z = X - 2
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
imm_enum <= IMM_P2;
|
|
-- PC = Z
|
|
ex_stall.wrpc_z <= '1';
|
|
|
|
when x"1" =>
|
|
-- X = R15
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "01111";
|
|
-- Y = SR
|
|
ex.ybus_sel <= SEL_SR;
|
|
-- Z = X - 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- imm_enum <= IMM_P4;
|
|
-- MEM[Z] = Y long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- R15 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "01111";
|
|
|
|
when x"2" =>
|
|
-- X = R15
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "01111";
|
|
-- Y = PC
|
|
ex.ybus_sel <= SEL_PC;
|
|
-- Z = X - 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- imm_enum <= IMM_P4;
|
|
-- MEM[Z] = Y long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- R15 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "01111";
|
|
|
|
when x"3" =>
|
|
-- X = UCONST * 4
|
|
ex.xbus_sel <= SEL_IMM;
|
|
-- Y = VBR
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "10001";
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_U_8_2;
|
|
-- W = MEM[Z] long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex.mem_size <= LONG;
|
|
|
|
when x"4" =>
|
|
|
|
when x"5" =>
|
|
ex_stall.zbus_sel <= SEL_WBUS;
|
|
-- PC = Z
|
|
ex_stall.wrpc_z <= '1';
|
|
|
|
when x"6" =>
|
|
id.ifadsel <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when x"7" =>
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "1-----110--------") then
|
|
-- Slot Illegal [-(-110)dd]
|
|
--
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = PC
|
|
ex.xbus_sel <= SEL_PC;
|
|
-- Z = X + 0
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_ZERO;
|
|
-- PC = Z
|
|
ex_stall.wrpc_z <= '1';
|
|
|
|
when x"1" =>
|
|
-- X = R15
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "01111";
|
|
-- Y = SR
|
|
ex.ybus_sel <= SEL_SR;
|
|
-- Z = X - 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- imm_enum <= IMM_P4;
|
|
-- MEM[Z] = Y long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- R15 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "01111";
|
|
|
|
when x"2" =>
|
|
-- X = R15
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "01111";
|
|
-- Y = PC
|
|
ex.ybus_sel <= SEL_PC;
|
|
-- Z = X - 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- imm_enum <= IMM_P4;
|
|
-- MEM[Z] = Y long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- R15 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "01111";
|
|
|
|
when x"3" =>
|
|
-- X = UCONST * 4
|
|
ex.xbus_sel <= SEL_IMM;
|
|
-- Y = VBR
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "10001";
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_U_8_2;
|
|
-- W = MEM[Z] long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex.mem_size <= LONG;
|
|
|
|
when x"4" =>
|
|
|
|
when x"5" =>
|
|
ex_stall.zbus_sel <= SEL_WBUS;
|
|
-- PC = Z
|
|
ex_stall.wrpc_z <= '1';
|
|
|
|
when x"6" =>
|
|
id.ifadsel <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when x"7" =>
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "1-----011--------") then
|
|
-- Reset [-(-011)dd]
|
|
--
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
|
|
when x"1" =>
|
|
event_ack_0 <= '1';
|
|
|
|
when x"2" =>
|
|
-- Y = UCONST * 4
|
|
ex.ybus_sel <= SEL_IMM;
|
|
ex_stall.zbus_sel <= SEL_YBUS;
|
|
imm_enum <= IMM_U_8_2;
|
|
-- W = MEM[Z] long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- TEMP0 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "10011";
|
|
|
|
when x"3" =>
|
|
-- X = TEMP0
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "10011";
|
|
-- Z = X + 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
-- imm_enum <= IMM_P4;
|
|
-- W = MEM[Z] long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- R15 = W
|
|
wb_stall.wrreg_w <= '1';
|
|
wb.regnum_w <= "01111";
|
|
|
|
when x"4" =>
|
|
ex_stall.zbus_sel <= SEL_WBUS;
|
|
-- PC = Z
|
|
ex_stall.wrpc_z <= '1';
|
|
|
|
when x"5" =>
|
|
-- X = TEMP1
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "10100";
|
|
-- Y = TEMP1
|
|
-- ex.ybus_sel <= SEL_REG;
|
|
ex.regnum_y <= "10100";
|
|
-- Z = X xor Y
|
|
ex_stall.zbus_sel <= SEL_LOGIC;
|
|
-- ex.logic_func <= LOGIC_XOR;
|
|
-- VBR = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "10001";
|
|
id.ifadsel <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when x"6" =>
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "1-----000--------") then
|
|
-- Interrupt [-(-000)dd]
|
|
--
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = PC
|
|
ex.xbus_sel <= SEL_PC;
|
|
-- Z = X - 2
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
imm_enum <= IMM_P2;
|
|
event_ack_0 <= '1';
|
|
ilevel_cap <= '1';
|
|
-- PC = Z
|
|
ex_stall.wrpc_z <= '1';
|
|
|
|
when x"1" =>
|
|
-- X = R15
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "01111";
|
|
-- Z = (X & FC) + 0
|
|
ex.aluinx_sel <= SEL_FC;
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_ZERO;
|
|
-- TEMP0 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "10011";
|
|
|
|
when x"2" =>
|
|
-- X = TEMP0
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "10011";
|
|
-- Y = SR
|
|
ex.ybus_sel <= SEL_SR;
|
|
-- Z = X - 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- imm_enum <= IMM_P4;
|
|
-- MEM[Z] = Y long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- TEMP0 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "10011";
|
|
|
|
when x"3" =>
|
|
-- X = TEMP0
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "10011";
|
|
-- Y = PC
|
|
ex.ybus_sel <= SEL_PC;
|
|
-- Z = X - 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- imm_enum <= IMM_P4;
|
|
-- MEM[Z] = Y long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- TEMP0 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "10011";
|
|
|
|
when x"4" =>
|
|
-- X = VBR
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "10001";
|
|
-- Y = UCONST * 4
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_U_8_2;
|
|
-- W = MEM[Z] long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex.mem_size <= LONG;
|
|
|
|
when x"5" =>
|
|
-- X = R15
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "01111";
|
|
-- Z = X - 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
ex_stall.sr_sel <= SEL_INT_MASK;
|
|
-- imm_enum <= IMM_P4;
|
|
-- R15 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "01111";
|
|
|
|
when x"6" =>
|
|
ex_stall.zbus_sel <= SEL_WBUS;
|
|
-- PC = Z
|
|
ex_stall.wrpc_z <= '1';
|
|
|
|
when x"7" =>
|
|
-- X = R15
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "01111";
|
|
-- Z = X - 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- imm_enum <= IMM_P4;
|
|
-- R15 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "01111";
|
|
id.ifadsel <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when x"8" =>
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "1-----001--------") then
|
|
-- Error [-(-001)dd]
|
|
--
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
-- X = PC
|
|
ex.xbus_sel <= SEL_PC;
|
|
-- Z = X - 2
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
imm_enum <= IMM_P2;
|
|
event_ack_0 <= '1';
|
|
ilevel_cap <= '1';
|
|
-- PC = Z
|
|
ex_stall.wrpc_z <= '1';
|
|
|
|
when x"1" =>
|
|
-- X = R15
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "01111";
|
|
-- Z = (X & FC) + 0
|
|
ex.aluinx_sel <= SEL_FC;
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_ZERO;
|
|
-- TEMP0 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "10011";
|
|
|
|
when x"2" =>
|
|
-- X = TEMP0
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "10011";
|
|
-- Y = SR
|
|
ex.ybus_sel <= SEL_SR;
|
|
-- Z = X - 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- imm_enum <= IMM_P4;
|
|
-- MEM[Z] = Y long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- TEMP0 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "10011";
|
|
|
|
when x"3" =>
|
|
-- X = TEMP0
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "10011";
|
|
-- Y = PC
|
|
ex.ybus_sel <= SEL_PC;
|
|
-- Z = X - 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- imm_enum <= IMM_P4;
|
|
-- MEM[Z] = Y long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '1';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex_stall.mem_wdata_sel <= SEL_YBUS;
|
|
-- ex.mem_size <= LONG;
|
|
-- TEMP0 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "10011";
|
|
|
|
when x"4" =>
|
|
-- X = VBR
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "10001";
|
|
-- Y = UCONST * 4
|
|
ex.ybus_sel <= SEL_IMM;
|
|
-- Z = X + Y
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
-- ex.arith_func <= ADD;
|
|
imm_enum <= IMM_U_8_2;
|
|
-- W = MEM[Z] long
|
|
ex_stall.ma_issue <= '1';
|
|
ex.ma_wr <= '0';
|
|
-- ex_stall.mem_addr_sel <= SEL_ZBUS;
|
|
-- ex.mem_size <= LONG;
|
|
|
|
when x"5" =>
|
|
-- X = R15
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "01111";
|
|
-- Z = X - 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- imm_enum <= IMM_P4;
|
|
-- R15 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "01111";
|
|
|
|
when x"6" =>
|
|
ex_stall.zbus_sel <= SEL_WBUS;
|
|
-- PC = Z
|
|
ex_stall.wrpc_z <= '1';
|
|
|
|
when x"7" =>
|
|
-- X = R15
|
|
-- ex.xbus_sel <= SEL_REG;
|
|
ex.regnum_x <= "01111";
|
|
-- Z = X - 4
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
-- imm_enum <= IMM_P4;
|
|
-- R15 = Z
|
|
ex_stall.wrreg_z <= '1';
|
|
ex.regnum_z <= "01111";
|
|
id.ifadsel <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when x"8" =>
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
elsif std_match(cond, "1-----010--------") then
|
|
-- Break [-(-010)dd]
|
|
--
|
|
case op.addr(3 downto 0) is
|
|
when x"0" =>
|
|
|
|
when x"1" =>
|
|
-- X = PC
|
|
ex.xbus_sel <= SEL_PC;
|
|
-- Z = X - 2
|
|
ex.aluiny_sel <= SEL_IMM;
|
|
-- ex_stall.zbus_sel <= SEL_ARITH;
|
|
ex.arith_func <= SUB;
|
|
imm_enum <= IMM_P2;
|
|
-- PC = Z
|
|
ex_stall.wrpc_z <= '1';
|
|
debug <= '1';
|
|
|
|
when x"2" =>
|
|
id.ifadsel <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when x"3" =>
|
|
id.incpc <= '1';
|
|
dispatch <= '1';
|
|
id.if_issue <= '1';
|
|
|
|
when others =>
|
|
|
|
end case;
|
|
end if;
|
|
end process;
|
|
end;
|