From: Paul Mackerras Date: Mon, 6 Apr 2020 03:24:08 +0000 (+1000) Subject: Decode sc in the major opcode decode table X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6f7ef8b1b91d2d5e0ed52f0538a727c6f39aa899;p=microwatt.git 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 --- diff --git a/decode1.vhdl b/decode1.vhdl index 5ee5176..dbcea47 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -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 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 + 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 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 @@ -344,7 +345,6 @@ architecture behaviour of decode1 is -- 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 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 decode1_0: process(clk) @@ -402,9 +402,6 @@ begin elsif std_match(f_in.insn, "01100000000000000000000000000000") then report "PPC_nop"; 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 report "PPC_attn"; v.decode := attn_instr; diff --git a/execute1.vhdl b/execute1.vhdl index 0aff3df..dd5cb21 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -239,6 +239,7 @@ begin variable exception : std_ulogic; variable exception_nextpc : std_ulogic; variable trapval : std_ulogic_vector(4 downto 0); + variable illegal : std_ulogic; begin result := (others => '0'); result_with_carry := (others => '0'); @@ -388,6 +389,7 @@ begin ctrl_tmp.irq_state <= WRITE_SRR0; exception := '0'; + illegal := '0'; exception_nextpc := '0'; v.e.exc_write_enable := '0'; v.e.exc_write_reg := fast_spr_num(SPR_SRR0); @@ -426,22 +428,21 @@ begin when OP_ILLEGAL => -- we need two cycles to write srr0 and 1 -- will need more when we have to write DSISR, DAR and HIER - 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"; + illegal := '1'; 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 -- will need more when we have to write DSISR, DAR and HIER - exception := '1'; - exception_nextpc := '1'; - ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#C00#, 64)); - ctrl_tmp.srr1 <= msr_copy(ctrl.msr); - report "sc"; + if e_in.insn(1) = '1' then + exception := '1'; + exception_nextpc := '1'; + ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#C00#, 64)); + ctrl_tmp.srr1 <= msr_copy(ctrl.msr); + report "sc"; + else + illegal := '1'; + end if; when OP_ATTN => terminate_out <= '1'; report "ATTN"; @@ -836,6 +837,15 @@ begin 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 v.e.exc_write_enable := '1'; if exception_nextpc = '1' then