From 00e9f801f664e1240cd43cd73c9881d1c6fa1922 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sun, 29 Sep 2019 16:26:07 +1000 Subject: [PATCH] decode: Index minor op table with insn bits for opcode 19 This changes the decoding of major opcode 19 from using the ppc_insn_t index to using bits of the instruction word directly. Opcode 19 has a 10-bit minor opcode field (bits 10..1) but the space is sparsely filled. Therefore we index a table of single-bit entries with the 10-bit minor opcode to filter out the illegal minor opcodes, and index a table using just 3 bits -- 5, 3 and 2 -- of the instruction to get the decode entry. This groups together all the instructions in 4 columns of the opcode map as a single entry. That means that mcrf and all the CR logical ops get grouped together, and bcctr, bclr and bctar get grouped together. At present the CR logical ops are not implemented, so their grouping has no impact. The code for bclr and bcctr in execute1 is now common, using a single op, and it now determines the branch address by looking at bit 10 of the instruction word at execute time. Signed-off-by: Paul Mackerras --- decode1.vhdl | 113 +++++++++++++++++++--------------------------- decode_types.vhdl | 5 +- execute1.vhdl | 16 +++---- 3 files changed, 57 insertions(+), 77 deletions(-) diff --git a/decode1.vhdl b/decode1.vhdl index 25bd597..ee5e6eb 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -24,6 +24,8 @@ architecture behaviour of decode1 is subtype major_opcode_t is unsigned(5 downto 0); type major_rom_array_t is array(0 to 63) of decode_rom_t; + type minor_valid_array_t is array(0 to 1023) of std_ulogic; + type op_19_subop_array_t is array(0 to 7) of decode_rom_t; type minor_rom_array_2_t is array(0 to 3) of decode_rom_t; type decode_rom_array_t is array(ppc_insn_t) of decode_rom_t; @@ -72,25 +74,42 @@ architecture behaviour of decode1 is others => illegal_inst ); - constant decode_op_19_array : decode_rom_array_t := ( - -- unit internal in1 in2 in3 out const const const CR CR cry cry ldst BR sgn upd rsrv mul mul rc lk sgl - -- op 1 2 3 in out in out len ext 32 sgn pipe - PPC_ILLEGAL => (ALU, OP_ILLEGAL, NONE, NONE, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - --PPC_ADDPCIS - PPC_BCCTR => (ALU, OP_BCCTR, NONE, NONE, NONE, NONE, BO, BI, BH, '1', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '1'), - PPC_BCLR => (ALU, OP_BCLR, NONE, NONE, NONE, NONE, BO, BI, BH, '1', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '1'), - --PPC_BCTAR - --PPC_CRAND - --PPC_CRANDC - --PPC_CREQV - --PPC_CRNAND - --PPC_CRNOR - --PPC_CROR - --PPC_CRORC - --PPC_CRXOR - PPC_ISYNC => (ALU, OP_NOP, NONE, NONE, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_MCRF => (ALU, OP_MCRF, NONE, NONE, NONE, NONE, BF, BFA, NONE, '1', '1', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - others => decode_rom_init + -- indexed by bits 10..1 of instruction word + constant decode_op_19_valid : minor_valid_array_t := ( + -- addpcis, 5 upper bits are part of constant + 2#0000000010# => '1', 2#0000100010# => '1', 2#0001000010# => '1', 2#0001100010# => '1', 2#0010000010# => '1', 2#0010100010# => '1', 2#0011000010# => '1', 2#0011100010# => '1', + 2#0100000010# => '1', 2#0100100010# => '1', 2#0101000010# => '1', 2#0101100010# => '1', 2#0110000010# => '1', 2#0110100010# => '1', 2#0111000010# => '1', 2#0111100010# => '1', + 2#1000000010# => '1', 2#1000100010# => '1', 2#1001000010# => '1', 2#1001100010# => '1', 2#1010000010# => '1', 2#1010100010# => '1', 2#1011000010# => '1', 2#1011100010# => '1', + 2#1100000010# => '1', 2#1100100010# => '1', 2#1101000010# => '1', 2#1101100010# => '1', 2#1110000010# => '1', 2#1110100010# => '1', 2#1111000010# => '1', 2#1111100010# => '1', + 2#1000010000# => '1', -- bcctr + 2#0000010000# => '1', -- bclr + 2#1000110000# => '0', -- bctar + 2#0100000001# => '0', -- crand + 2#0010000001# => '0', -- crandc + 2#0100100001# => '0', -- creqv + 2#0011100001# => '0', -- crnand + 2#0000100001# => '0', -- crnor + 2#0111000001# => '0', -- cror + 2#0011000001# => '0', -- crorc + 2#0110100001# => '0', -- crxor + 2#0010010110# => '1', -- isync + 2#0000000000# => '1', -- mcrf + others => '0' + ); + + -- indexed by bits 5, 3, 2 of instruction word + constant decode_op_19_array : op_19_subop_array_t := ( + -- unit internal in1 in2 in3 out const const const CR CR cry cry ldst BR sgn upd rsrv mul mul rc lk sgl + -- op 1 2 3 in out in out len ext 32 sgn pipe + -- mcrf; cr logical ops not implemented yet + 2#000# => (ALU, OP_MCRF, NONE, NONE, NONE, NONE, BF, BFA, NONE, '1', '1', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), + -- addpcis not implemented yet + 2#001# => (ALU, OP_ILLEGAL, NONE, NONE, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), + -- bclr, bcctr, bctar + 2#100# => (ALU, OP_BCREG, NONE, NONE, NONE, NONE, BO, BI, BH, '1', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '1'), + -- isync + 2#111# => (ALU, OP_NOP, NONE, NONE, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), + others => illegal_inst ); constant decode_op_30_array : decode_rom_array_t := ( @@ -260,6 +279,7 @@ begin variable v : Decode1ToDecode2Type; variable ppc_insn: ppc_insn_t; variable majorop : major_opcode_t; + variable op_19_bits: std_ulogic_vector(2 downto 0); begin v := r; @@ -615,53 +635,14 @@ begin v.decode := decode_op_31_array(ppc_insn); elsif majorop = "010011" then - if std_match(f_in.insn, "--------------------------00010-") then - report "PPC_addpcis"; - ppc_insn := PPC_ADDPCIS; - elsif std_match(f_in.insn, "---------------------1000010000-") then - report "PPC_bcctr"; - ppc_insn := PPC_BCCTR; - elsif std_match(f_in.insn, "---------------------0000010000-") then - report "PPC_bclr"; - ppc_insn := PPC_BCLR; - elsif std_match(f_in.insn, "---------------------1000110000-") then - report "PPC_bctar"; - ppc_insn := PPC_BCTAR; - elsif std_match(f_in.insn, "---------------------0100000001-") then - report "PPC_crand"; - ppc_insn := PPC_CRAND; - elsif std_match(f_in.insn, "---------------------0010000001-") then - report "PPC_crandc"; - ppc_insn := PPC_CRANDC; - elsif std_match(f_in.insn, "---------------------0100100001-") then - report "PPC_creqv"; - ppc_insn := PPC_CREQV; - elsif std_match(f_in.insn, "---------------------0011100001-") then - report "PPC_crnand"; - ppc_insn := PPC_CRNAND; - elsif std_match(f_in.insn, "---------------------0000100001-") then - report "PPC_crnor"; - ppc_insn := PPC_CRNOR; - elsif std_match(f_in.insn, "---------------------0111000001-") then - report "PPC_cror"; - ppc_insn := PPC_CROR; - elsif std_match(f_in.insn, "---------------------0110100001-") then - report "PPC_crorc"; - ppc_insn := PPC_CRORC; - elsif std_match(f_in.insn, "---------------------0011000001-") then - report "PPC_crxor"; - ppc_insn := PPC_CRXOR; - elsif std_match(f_in.insn, "---------------------0010010110-") then - report "PPC_isync"; - ppc_insn := PPC_ISYNC; - elsif std_match(f_in.insn, "---------------------0000000000-") then - report "PPC_mcrf"; - ppc_insn := PPC_MCRF; - else - report "PPC_illegal"; - ppc_insn := PPC_ILLEGAL; - end if; - v.decode := decode_op_19_array(ppc_insn); + if decode_op_19_valid(to_integer(unsigned(f_in.insn(10 downto 1)))) = '0' then + report "op 19 illegal subcode"; + v.decode := illegal_inst; + else + op_19_bits := f_in.insn(5) & f_in.insn(3) & f_in.insn(2); + v.decode := decode_op_19_array(to_integer(unsigned(op_19_bits))); + report "op 19 sub " & to_hstring(op_19_bits); + end if; elsif majorop = "011110" then if std_match(f_in.insn, "---------------------------1000-") then diff --git a/decode_types.vhdl b/decode_types.vhdl index 1437bf0..aab59cf 100644 --- a/decode_types.vhdl +++ b/decode_types.vhdl @@ -39,9 +39,8 @@ package decode_types is PPC_SIM_CONFIG); type insn_type_t is (OP_ILLEGAL, OP_NOP, OP_ADD, OP_ADDE, OP_ADDEX, OP_ADDME, - OP_ADDPCIS, OP_AND, OP_ANDC, OP_ATTN, OP_B, OP_BC, - OP_BCCTR, OP_BCLR, OP_BCTAR, OP_BPERM, OP_CMP, - OP_CMPB, OP_CMPEQB, OP_CMPL, OP_CMPRB, + OP_ADDPCIS, OP_AND, OP_ANDC, OP_ATTN, OP_B, OP_BC, OP_BCREG, + OP_BPERM, OP_CMP, OP_CMPB, OP_CMPEQB, OP_CMPL, OP_CMPRB, OP_CNTLZD, OP_CNTLZW, OP_CNTTZD, OP_CNTTZW, OP_CRAND, OP_CRANDC, OP_CREQV, OP_CRNAND, OP_CRNOR, OP_CROR, OP_CRORC, OP_CRXOR, OP_DARN, OP_DCBF, OP_DCBST, OP_DCBT, OP_DCBTST, diff --git a/execute1.vhdl b/execute1.vhdl index 0d85e71..efbba14 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -120,18 +120,18 @@ begin f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2)); end if; end if; - when OP_BCLR => - if e_in.const1(4-2) = '0' then + when OP_BCREG => + -- bits 10 and 6 distinguish between bclr, bcctr and bctar + if e_in.const1(4-2) = '0' and e_in.insn(10) = '0' then ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1); end if; if ppc_bc_taken(e_in.const1(4 downto 0), e_in.const2(4 downto 0), e_in.cr, ctrl.ctr) = 1 then f_out.redirect <= '1'; - f_out.redirect_nia <= ctrl.lr(63 downto 2) & "00"; - end if; - when OP_BCCTR => - if ppc_bcctr_taken(e_in.const1(4 downto 0), e_in.const2(4 downto 0), e_in.cr) = 1 then - f_out.redirect <= '1'; - f_out.redirect_nia <= ctrl.ctr(63 downto 2) & "00"; + if e_in.insn(10) = '0' then + f_out.redirect_nia <= ctrl.lr(63 downto 2) & "00"; + else + f_out.redirect_nia <= ctrl.ctr(63 downto 2) & "00"; + end if; end if; when OP_CMPB => result := ppc_cmpb(e_in.read_data1, e_in.read_data2);