Decode sc in the major opcode decode table

This decodes sc using entry 17 of the major_decode_rom_array table
instead of a special case in the decode1_1 process.  This means that
only the major opcode (the top 6 bits) is checked at decode time.
To make sure that the instruction is sc not scv, we now check bit
1 of the instruction at execute time and generate an illegal
instruction interrupt if it is 0 (indicating scv).  The level field
of the sc instruction is now ignored.

This reduces LUT consumption by 31 LUTs on the Arty A7-100.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
jtag-port
Paul Mackerras 5 years ago
parent 278ac5e0eb
commit 6f7ef8b1b9

@ -60,6 +60,7 @@ architecture behaviour of decode1 is
20 => (ALU, OP_RLC, RA, CONST_SH32, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0'), -- rlwimi 20 => (ALU, OP_RLC, RA, CONST_SH32, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0'), -- rlwimi
21 => (ALU, OP_RLC, NONE, CONST_SH32, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0'), -- rlwinm 21 => (ALU, OP_RLC, NONE, CONST_SH32, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0'), -- rlwinm
23 => (ALU, OP_RLC, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0'), -- rlwnm 23 => (ALU, OP_RLC, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0'), -- rlwnm
17 => (ALU, OP_SC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- sc
38 => (LDST, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- stb 38 => (LDST, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- stb
39 => (LDST, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0'), -- stbu 39 => (LDST, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0'), -- stbu
44 => (LDST, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- sth 44 => (LDST, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- sth
@ -344,7 +345,6 @@ architecture behaviour of decode1 is
-- op in out A out in out len ext pipe -- op in out A out in out len ext pipe
constant attn_instr : decode_rom_t := (ALU, OP_ATTN, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'); constant attn_instr : decode_rom_t := (ALU, OP_ATTN, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1');
constant nop_instr : decode_rom_t := (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'); constant nop_instr : decode_rom_t := (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0');
constant sc_instr : decode_rom_t := (ALU, OP_SC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0');


begin begin
decode1_0: process(clk) decode1_0: process(clk)
@ -402,9 +402,6 @@ begin
elsif std_match(f_in.insn, "01100000000000000000000000000000") then elsif std_match(f_in.insn, "01100000000000000000000000000000") then
report "PPC_nop"; report "PPC_nop";
v.decode := nop_instr; v.decode := nop_instr;
elsif std_match(f_in.insn, "010001--------------0000000---1-") then
report "PPC_sc";
v.decode := sc_instr;
elsif std_match(f_in.insn, "000000---------------0100000000-") then elsif std_match(f_in.insn, "000000---------------0100000000-") then
report "PPC_attn"; report "PPC_attn";
v.decode := attn_instr; v.decode := attn_instr;

@ -239,6 +239,7 @@ begin
variable exception : std_ulogic; variable exception : std_ulogic;
variable exception_nextpc : std_ulogic; variable exception_nextpc : std_ulogic;
variable trapval : std_ulogic_vector(4 downto 0); variable trapval : std_ulogic_vector(4 downto 0);
variable illegal : std_ulogic;
begin begin
result := (others => '0'); result := (others => '0');
result_with_carry := (others => '0'); result_with_carry := (others => '0');
@ -388,6 +389,7 @@ begin


ctrl_tmp.irq_state <= WRITE_SRR0; ctrl_tmp.irq_state <= WRITE_SRR0;
exception := '0'; exception := '0';
illegal := '0';
exception_nextpc := '0'; exception_nextpc := '0';
v.e.exc_write_enable := '0'; v.e.exc_write_enable := '0';
v.e.exc_write_reg := fast_spr_num(SPR_SRR0); v.e.exc_write_reg := fast_spr_num(SPR_SRR0);
@ -426,22 +428,21 @@ begin
when OP_ILLEGAL => when OP_ILLEGAL =>
-- we need two cycles to write srr0 and 1 -- we need two cycles to write srr0 and 1
-- will need more when we have to write DSISR, DAR and HIER -- will need more when we have to write DSISR, DAR and HIER
exception := '1'; illegal := '1';
ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#700#, 64));
ctrl_tmp.srr1 <= msr_copy(ctrl.msr);
-- Since we aren't doing Hypervisor emulation assist (0xe40) we
-- set bit 44 to indicate we have an illegal
ctrl_tmp.srr1(63 - 44) <= '1';
report "illegal";
when OP_SC => when OP_SC =>
-- FIXME Assume everything is SC (not SCV) for now -- check bit 1 of the instruction is 1 so we know this is sc;
-- 0 would mean scv, so generate an illegal instruction interrupt
-- we need two cycles to write srr0 and 1 -- we need two cycles to write srr0 and 1
-- will need more when we have to write DSISR, DAR and HIER -- will need more when we have to write DSISR, DAR and HIER
exception := '1'; if e_in.insn(1) = '1' then
exception_nextpc := '1'; exception := '1';
ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#C00#, 64)); exception_nextpc := '1';
ctrl_tmp.srr1 <= msr_copy(ctrl.msr); ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#C00#, 64));
report "sc"; ctrl_tmp.srr1 <= msr_copy(ctrl.msr);
report "sc";
else
illegal := '1';
end if;
when OP_ATTN => when OP_ATTN =>
terminate_out <= '1'; terminate_out <= '1';
report "ATTN"; report "ATTN";
@ -836,6 +837,15 @@ begin
end if; end if;
end if; end if;


if illegal = '1' then
exception := '1';
ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#700#, 64));
ctrl_tmp.srr1 <= msr_copy(ctrl.msr);
-- Since we aren't doing Hypervisor emulation assist (0xe40) we
-- set bit 44 to indicate we have an illegal
ctrl_tmp.srr1(63 - 44) <= '1';
report "illegal";
end if;
if exception = '1' then if exception = '1' then
v.e.exc_write_enable := '1'; v.e.exc_write_enable := '1';
if exception_nextpc = '1' then if exception_nextpc = '1' then

Loading…
Cancel
Save