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);