diff --git a/Makefile b/Makefile index 13d245e..7b28b31 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,8 @@ GHDL=ghdl GHDLFLAGS=--std=08 -Psim-unisim CFLAGS=-O2 -Wall -all = core_tb simple_ram_behavioural_tb soc_reset_tb icache_tb multiply_tb dmi_dtm_tb divider_tb +all = core_tb simple_ram_behavioural_tb soc_reset_tb icache_tb multiply_tb dmi_dtm_tb divider_tb \ + rotator_tb # XXX # loadstore_tb fetch_tb @@ -22,7 +23,7 @@ crhelpers.o: common.o decode1.o: common.o decode_types.o decode2.o: decode_types.o common.o helpers.o insn_helpers.o decode_types.o: -execute1.o: decode_types.o common.o helpers.o crhelpers.o ppc_fx_insns.o +execute1.o: decode_types.o common.o helpers.o crhelpers.o ppc_fx_insns.o insn_helpers.o rotator.o execute2.o: common.o crhelpers.o ppc_fx_insns.o fetch1.o: common.o fetch2.o: common.o wishbone_types.o @@ -40,6 +41,8 @@ divider_tb.o: decode_types.o common.o glibc_random.o ppc_fx_insns.o divider.o divider.o: common.o decode_types.o crhelpers.o ppc_fx_insns.o: helpers.o register_file.o: common.o +rotator.o: common.o +rotator_tb.o: common.o glibc_random.o ppc_fx_insns.o insn_helpers.o rotator.o sim_console.o: simple_ram_behavioural_helpers.o: simple_ram_behavioural_tb.o: wishbone_types.o simple_ram_behavioural.o @@ -81,6 +84,9 @@ multiply_tb: multiply_tb.o divider_tb: divider_tb.o $(GHDL) -e $(GHDLFLAGS) $@ +rotator_tb: rotator_tb.o + $(GHDL) -e $(GHDLFLAGS) $@ + simple_ram_tb: simple_ram_tb.o $(GHDL) -e $(GHDLFLAGS) $@ diff --git a/common.vhdl b/common.vhdl index 380c9be..fc6d888 100644 --- a/common.vhdl +++ b/common.vhdl @@ -52,18 +52,23 @@ package common is read_reg2: std_ulogic_vector(4 downto 0); read_data1: std_ulogic_vector(63 downto 0); read_data2: std_ulogic_vector(63 downto 0); - const1: std_ulogic_vector(7 downto 0); - const2: std_ulogic_vector(5 downto 0); - const3: std_ulogic_vector(4 downto 0); + read_data3: std_ulogic_vector(63 downto 0); cr: std_ulogic_vector(31 downto 0); lr: std_ulogic; rc: std_ulogic; - input_carry: std_ulogic; + invert_a: std_ulogic; + input_carry: carry_in_t; output_carry: std_ulogic; input_cr: std_ulogic; output_cr: std_ulogic; - end record; - constant Decode2ToExecute1Init : Decode2ToExecute1Type := (valid => '0', insn_type => OP_ILLEGAL, lr => '0', rc => '0', input_carry => '0', output_carry => '0', input_cr => '0', output_cr => '0', others => (others => '0')); + is_32bit: std_ulogic; + is_signed: std_ulogic; + insn: std_ulogic_vector(31 downto 0); + end record; + constant Decode2ToExecute1Init : Decode2ToExecute1Type := + (valid => '0', insn_type => OP_ILLEGAL, lr => '0', rc => '0', invert_a => '0', + input_carry => ZERO, output_carry => '0', input_cr => '0', output_cr => '0', + is_32bit => '0', is_signed => '0', others => (others => '0')); type Decode2ToMultiplyType is record valid: std_ulogic; diff --git a/decode1.vhdl b/decode1.vhdl index 7c29781..8ad123f 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -22,202 +22,296 @@ end entity decode1; architecture behaviour of decode1 is signal r, rin : Decode1ToDecode2Type; - type decode_rom_array_t is array(ppc_insn_t) of decode_rom_t; + 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 op_30_subop_array_t is array(0 to 15) of decode_rom_t; + type op_31_subop_array_t is array(0 to 1023) of decode_rom_t; + type minor_rom_array_2_t is array(0 to 3) of decode_rom_t; - -- Note: reformat with column -t -o ' ' - constant decode_rom_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_ADD => (ALU, OP_ADD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_ADDC => (ALU, OP_ADDE, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_ADDE => (ALU, OP_ADDE, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '1', '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - --PPC_ADDEX - PPC_ADDI => (ALU, OP_ADD, RA_OR_ZERO, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_ADDIC => (ALU, OP_ADDE, RA, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '1', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_ADDIC_RC => (ALU, OP_ADDE, RA, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '1', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '1'), - PPC_ADDIS => (ALU, OP_ADD, RA_OR_ZERO, CONST_SI_HI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '1', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - --PPC_ADDME - --PPC_ADDPCIS - PPC_ADDZE => (ALU, OP_ADDE, RA, NONE, NONE, RT, NONE, NONE, NONE, '0', '0', '1', '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_AND => (ALU, OP_AND, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_ANDC => (ALU, OP_ANDC, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_ANDI_RC => (ALU, OP_AND, RS, CONST_UI, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '1'), - PPC_ANDIS_RC => (ALU, OP_AND, RS, CONST_UI_HI, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '1'), - PPC_ATTN => (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_B => (ALU, OP_B, NONE, CONST_LI, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '1'), - --PPC_BA - PPC_BC => (ALU, OP_BC, NONE, CONST_BD, NONE, NONE, BO, BI, NONE, '1', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '1'), - --PPC_BCA - 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_BCLA - 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_BPERM - PPC_CMP => (ALU, OP_CMP, RA, RB, NONE, NONE, BF, L, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_CMPB => (ALU, OP_CMPB, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - --PPC_CMPEQB - PPC_CMPI => (ALU, OP_CMP, RA, CONST_SI, NONE, NONE, BF, L, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_CMPL => (ALU, OP_CMPL, RA, RB, NONE, NONE, BF, L, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_CMPLI => (ALU, OP_CMPL, RA, CONST_UI, NONE, NONE, BF, L, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - --PPC_CMPRB - PPC_CNTLZD => (ALU, OP_CNTLZD, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_CNTLZW => (ALU, OP_CNTLZW, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_CNTTZD => (ALU, OP_CNTTZD, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_CNTTZW => (ALU, OP_CNTTZW, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - --PPC_CRAND - --PPC_CRANDC - --PPC_CREQV - --PPC_CRNAND - --PPC_CRNOR - --PPC_CROR - --PPC_CRORC - --PPC_CRXOR - --PPC_DARN - PPC_DCBF => (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_DCBST => (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_DCBT => (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_DCBTST => (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_DCBZ - PPC_DIV => (DIV, OP_DIV, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_EQV => (ALU, OP_EQV, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_EXTSB => (ALU, OP_EXTSB, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_EXTSH => (ALU, OP_EXTSH, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_EXTSW => (ALU, OP_EXTSW, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - --PPC_EXTSWSLI - --PPC_ICBI - PPC_ICBT => (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_ISEL => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, BC, NONE, NONE, '1', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - 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_LBARX => (LDST, OP_LOAD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is1B, '0', '0', '0', '1', '0', '0', NONE, '0', '1'), - --CONST_LI matches CONST_SI, so reuse it - PPC_LBZ => (LDST, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_LBZU => (LDST, OP_LOAD, RA, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), - PPC_LBZUX => (LDST, OP_LOAD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), - PPC_LBZX => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_LD => (LDST, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_LDARX => (LDST, OP_LOAD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '0', '0', '0', '1', '0', '0', NONE, '0', '1'), - PPC_LDBRX => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '1', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_LDU => (LDST, OP_LOAD, RA, CONST_DS, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), - PPC_LDUX => (LDST, OP_LOAD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), - PPC_LDX => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_LHA => (LDST, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '1', '0', '0', '0', '0', NONE, '0', '1'), - PPC_LHARX => (LDST, OP_LOAD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '0', '0', '1', '0', '0', NONE, '0', '1'), - PPC_LHAU => (LDST, OP_LOAD, RA, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '1', '1', '0', '0', '0', NONE, '0', '1'), - PPC_LHAUX => (LDST, OP_LOAD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '1', '1', '0', '0', '0', NONE, '0', '1'), - PPC_LHAX => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '1', '0', '0', '0', '0', NONE, '0', '1'), - PPC_LHBRX => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '1', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_LHZ => (LDST, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_LHZU => (LDST, OP_LOAD, RA, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), - PPC_LHZUX => (LDST, OP_LOAD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), - PPC_LHZX => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_LWA => (LDST, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '1'), - PPC_LWARX => (LDST, OP_LOAD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '0', '0', '1', '0', '0', NONE, '0', '1'), - PPC_LWAUX => (LDST, OP_LOAD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '1', '1', '0', '0', '0', NONE, '0', '1'), - PPC_LWAX => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '1'), - PPC_LWBRX => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '1', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_LWZ => (LDST, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_LWZU => (LDST, OP_LOAD, RA, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), - PPC_LWZUX => (LDST, OP_LOAD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), - PPC_LWZX => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - --PPC_MADDHD - --PPC_MADDHDU - --PPC_MADDLD - --PPC_MCRF - --PPC_MCRXR - --PPC_MCRXRX - PPC_MFCR => (ALU, OP_MFCR, NONE, NONE, NONE, RT, NONE, NONE, NONE, '1', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_MFOCRF => (ALU, OP_MFOCRF, NONE, NONE, NONE, RT, FXM, NONE, NONE, '1', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_MFCTR => (ALU, OP_MFCTR, NONE, NONE, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_MFLR => (ALU, OP_MFLR, NONE, NONE, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_MFTB => (ALU, OP_MFTB, NONE, NONE, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_MTCTR => (ALU, OP_MTCTR, RS, NONE, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_MTLR => (ALU, OP_MTLR, RS, NONE, NONE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - --PPC_MFSPR - PPC_MOD => (DIV, OP_MOD, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_MTCRF => (ALU, OP_MTCRF, RS, NONE, NONE, NONE, FXM, NONE, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_MTOCRF => (ALU, OP_MTOCRF, RS, NONE, NONE, NONE, FXM, NONE, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - --PPC_MTSPR - PPC_MULHD => (MUL, OP_MUL_H64, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '1'), - PPC_MULHDU => (MUL, OP_MUL_H64, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_MULHW => (MUL, OP_MUL_H32, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '1'), - PPC_MULHWU => (MUL, OP_MUL_H32, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '1'), - PPC_MULLD => (MUL, OP_MUL_L64, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '1'), - PPC_MULLI => (MUL, OP_MUL_L64, RA, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '1'), - PPC_MULLW => (MUL, OP_MUL_L64, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '1', '0', '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '1'), - PPC_NAND => (ALU, OP_NAND, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_NEG => (ALU, OP_NEG, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_NOP => (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_NOR => (ALU, OP_NOR, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_OR => (ALU, OP_OR, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_ORC => (ALU, OP_ORC, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_ORI => (ALU, OP_OR, RS, CONST_UI, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_ORIS => (ALU, OP_OR, RS, CONST_UI_HI, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_POPCNTB => (ALU, OP_POPCNTB, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_POPCNTD => (ALU, OP_POPCNTD, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_POPCNTW => (ALU, OP_POPCNTW, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_PRTYD => (ALU, OP_PRTYD, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_PRTYW => (ALU, OP_PRTYW, RS, NONE, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_RLDCL => (ALU, OP_RLDCL, RS, RB, NONE, RA, NONE, MB, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_RLDCR => (ALU, OP_RLDCR, RS, RB, NONE, RA, NONE, MB, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_RLDIC => (ALU, OP_RLDIC, RS, NONE, NONE, RA, SH, MB, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_RLDICL => (ALU, OP_RLDICL, RS, NONE, NONE, RA, SH, MB, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_RLDICR => (ALU, OP_RLDICR, RS, NONE, NONE, RA, SH, ME, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_RLDIMI => (ALU, OP_RLDIMI, RA, RS, NONE, RA, SH, MB, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_RLWIMI => (ALU, OP_RLWIMI, RA, RS, NONE, RA, SH32, MB32, ME32, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_RLWINM => (ALU, OP_RLWINM, RS, NONE, NONE, RA, SH32, MB32, ME32, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_RLWNM => (ALU, OP_RLWNM, RS, RB, NONE, RA, NONE, MB32, ME32, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - --PPC_SETB - PPC_SLD => (ALU, OP_SLD, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_SLW => (ALU, OP_SLW, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_SRAD => (ALU, OP_SRAD, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_SRADI => (ALU, OP_SRADI, RS, NONE, NONE, RA, SH, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_SRAW => (ALU, OP_SRAW, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_SRAWI => (ALU, OP_SRAWI, RS, NONE, NONE, RA, SH, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_SRD => (ALU, OP_SRD, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_SRW => (ALU, OP_SRW, RS, RB, RS, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_STB => (LDST, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is1B, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_STBCX => (LDST, OP_STORE, RA, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is1B, '0', '0', '0', '1', '0', '0', RC, '0', '1'), - PPC_STBU => (LDST, OP_STORE, RA, CONST_SI, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is1B, '0', '0', '1', '0', '0', '0', RC, '0', '1'), - PPC_STBUX => (LDST, OP_STORE, RA, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is1B, '0', '0', '1', '0', '0', '0', RC, '0', '1'), - PPC_STBX => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is1B, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_STD => (LDST, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_STDBRX => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '1', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_STDCX => (LDST, OP_STORE, RA, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '0', '0', '0', '1', '0', '0', NONE, '0', '1'), - PPC_STDU => (LDST, OP_STORE, RA, CONST_DS, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), - PPC_STDUX => (LDST, OP_STORE, RA, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), - PPC_STDX => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_STH => (LDST, OP_STORE, RA, CONST_SI, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_STHBRX => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '1', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_STHCX => (LDST, OP_STORE, RA, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '0', '0', '1', '0', '0', NONE, '0', '1'), - PPC_STHU => (LDST, OP_STORE, RA, CONST_SI, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), - PPC_STHUX => (LDST, OP_STORE, RA, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), - PPC_STHX => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_STW => (LDST, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_STWBRX => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '1', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_STWCX => (LDST, OP_STORE, RA, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '0', '0', '1', '0', '0', NONE, '0', '1'), - PPC_STWU => (LDST, OP_STORE, RA, CONST_SI, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), - PPC_STWUX => (LDST, OP_STORE, RA, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), - PPC_STWX => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, NONE, NONE, NONE, '0', '0', '0', '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_SUBF => (ALU, OP_SUBF, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_SUBFC => (ALU, OP_SUBFE, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_SUBFE => (ALU, OP_SUBFE, RA, RB, NONE, RT, NONE, NONE, NONE, '0', '0', '1', '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_SUBFIC => (ALU, OP_SUBFE, RA, CONST_SI, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '1', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - --PPC_SUBFME - PPC_SUBFZE => (ALU, OP_SUBFE, RA, NONE, NONE, RT, NONE, NONE, NONE, '0', '0', '1', '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_SYNC => (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_TD - PPC_TDI => (ALU, OP_TDI, RA, CONST_SI, NONE, NONE, TOO, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_TW => (ALU, OP_TW, RA, RB, NONE, NONE, TOO, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - --PPC_TWI - PPC_XOR => (ALU, OP_XOR, RS, RB, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), - PPC_XORI => (ALU, OP_XOR, RS, CONST_UI, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_XORIS => (ALU, OP_XOR, RS, CONST_UI_HI, NONE, RA, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), - PPC_SIM_CONFIG => (ALU, OP_SIM_CONFIG,NONE, NONE, NONE, RT, NONE, NONE, NONE, '0', '0', '0', '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), + constant illegal_inst : decode_rom_t := + (ALU, OP_ILLEGAL, NONE, NONE, NONE, NONE, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'); + + constant major_decode_rom_array : major_rom_array_t := ( + -- unit internal in1 in2 in3 out CR CR inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl + -- op in out A in out len ext pipe + 12 => (ALU, OP_ADD, RA, CONST_SI, NONE, RT, '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- addic + 13 => (ALU, OP_ADD, RA, CONST_SI, NONE, RT, '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '1'), -- addic. + 14 => (ALU, OP_ADD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- addi + 15 => (ALU, OP_ADD, RA_OR_ZERO, CONST_SI_HI, NONE, RT, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- addis + 28 => (ALU, OP_AND, NONE, CONST_UI, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '1'), -- andi. + 29 => (ALU, OP_AND, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '1'), -- andis. + 18 => (ALU, OP_B, NONE, CONST_LI, NONE, NONE, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '1'), -- b + 16 => (ALU, OP_BC, NONE, CONST_BD, NONE, NONE, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '1'), -- bc + 11 => (ALU, OP_CMP, RA, CONST_SI, NONE, NONE, '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- cmpi + 10 => (ALU, OP_CMPL, RA, CONST_UI, NONE, NONE, '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- cmpli + 34 => (LDST, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- lbz + 35 => (LDST, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), -- lbzu + 42 => (LDST, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', ZERO, '0', is2B, '0', '1', '0', '0', '0', '0', NONE, '0', '1'), -- lha + 43 => (LDST, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', ZERO, '0', is2B, '0', '1', '1', '0', '0', '0', NONE, '0', '1'), -- lhau + 40 => (LDST, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- lhz + 41 => (LDST, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), -- lhzu + 32 => (LDST, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- lwz + 33 => (LDST, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), -- lwzu + 7 => (MUL, OP_MUL_L64, RA, CONST_SI, NONE, RT, '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '1'), -- mulli + 24 => (ALU, OP_OR, NONE, CONST_UI, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- ori + 25 => (ALU, OP_OR, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- oris + 20 => (ALU, OP_RLC, RA, CONST_SH32, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '1'), -- rlwimi + 21 => (ALU, OP_RLC, NONE, CONST_SH32, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '1'), -- rlwinm + 23 => (ALU, OP_RLC, NONE, RB, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '1'), -- rlwnm + 38 => (LDST, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- stb + 39 => (LDST, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', RC, '0', '1'), -- stbu + 44 => (LDST, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- sth + 45 => (LDST, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), -- sthu + 36 => (LDST, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- stw + 37 => (LDST, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), -- stwu + 8 => (ALU, OP_ADD, RA, CONST_SI, NONE, RT, '0', '0', '1', ONE, '1', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- subfic + 2 => (ALU, OP_TDI, RA, CONST_SI, NONE, NONE, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- tdi + --PPC_TWI 3 + 26 => (ALU, OP_XOR, NONE, CONST_UI, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- xori + 27 => (ALU, OP_XOR, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- xoris + others => illegal_inst + ); + + -- 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 CR CR inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl + -- op in out A in out len ext pipe + -- mcrf; cr logical ops not implemented yet + 2#000# => (ALU, OP_MCRF, NONE, NONE, NONE, NONE, '1', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), + -- addpcis not implemented yet + 2#001# => (ALU, OP_ILLEGAL, NONE, NONE, NONE, NONE, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), + -- bclr, bcctr, bctar + 2#100# => (ALU, OP_BCREG, NONE, NONE, NONE, NONE, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '1'), + -- isync + 2#111# => (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), + others => illegal_inst + ); - others => decode_rom_init + constant decode_op_30_array : op_30_subop_array_t := ( + -- unit internal in1 in2 in3 out CR CR inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl + -- op in out A in out len ext pipe + 2#0100# => (ALU, OP_RLC, NONE, CONST_SH, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- rldic + 2#0101# => (ALU, OP_RLC, NONE, CONST_SH, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- rldic + 2#0000# => (ALU, OP_RLCL, NONE, CONST_SH, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- rldicl + 2#0001# => (ALU, OP_RLCL, NONE, CONST_SH, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- rldicl + 2#0010# => (ALU, OP_RLCR, NONE, CONST_SH, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- rldicr + 2#0011# => (ALU, OP_RLCR, NONE, CONST_SH, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- rldicr + 2#0110# => (ALU, OP_RLC, RA, CONST_SH, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- rldimi + 2#0111# => (ALU, OP_RLC, RA, CONST_SH, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- rldimi + 2#1000# => (ALU, OP_RLCL, NONE, RB, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- rldcl + 2#1001# => (ALU, OP_RLCR, NONE, RB, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- rldcr + others => illegal_inst + ); + + -- Note: reformat with column -t -o ' ' + constant decode_op_31_array : op_31_subop_array_t := ( + -- unit internal in1 in2 in3 out CR CR inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl + -- op in out A in out len ext pipe + 2#0100001010# => (ALU, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- add + 2#0000001010# => (ALU, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- addc + 2#0010001010# => (ALU, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- adde + 2#0011101010# => (ALU, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- addme + 2#0011001010# => (ALU, OP_ADD, RA, NONE, NONE, RT, '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- addze + 2#0000011100# => (ALU, OP_AND, NONE, RB, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- and + 2#0000111100# => (ALU, OP_ANDC, NONE, RB, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- andc + -- 2#0011111100# bperm + 2#0000000000# => (ALU, OP_CMP, RA, RB, NONE, NONE, '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- cmp + 2#0111111100# => (ALU, OP_CMPB, NONE, RB, RS, RA, '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- cmpb + -- 2#0011100000# cmpeqb + 2#0000100000# => (ALU, OP_CMPL, RA, RB, NONE, NONE, '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- cmpl + -- 2#0011000000# cmprb + 2#0000111010# => (ALU, OP_CNTLZD, NONE, NONE, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- cntlzd + 2#0000011010# => (ALU, OP_CNTLZW, NONE, NONE, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- cntlzw + 2#1000111010# => (ALU, OP_CNTTZD, NONE, NONE, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- cnttzd + 2#1000011010# => (ALU, OP_CNTTZW, NONE, NONE, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- cnttzw + -- 2#1011110011# darn + 2#0001010110# => (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbf + 2#0000110110# => (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbst + 2#0100010110# => (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbt + 2#0011110110# => (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbtst + -- 2#1111110110# dcbz + 2#0110001001# => (DIV, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- divdeu + 2#0110001011# => (DIV, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- divweu + 2#0110101001# => (DIV, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- divde + 2#0110101011# => (DIV, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- divwe + 2#0111001001# => (DIV, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- divdu + 2#0111001011# => (DIV, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- divwu + 2#0111101001# => (DIV, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- divd + 2#0111101011# => (DIV, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- divw + 2#0100011100# => (ALU, OP_EQV, NONE, RB, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- eqv + 2#1110111010# => (ALU, OP_EXTSB, NONE, NONE, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- extsb + 2#1110011010# => (ALU, OP_EXTSH, NONE, NONE, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- extsh + 2#1111011010# => (ALU, OP_EXTSW, NONE, NONE, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- extsw + -- 2#110111101-# extswsli + -- 2#1111010110# icbi + 2#0000010110# => (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- icbt + 2#0000001111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#0000101111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#0001001111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#0001101111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#0010001111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#0010101111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#0011001111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#0011101111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#0100001111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#0100101111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#0101001111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#0101101111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#0110001111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#0110101111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#0111001111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#0111101111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#1000001111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#1000101111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#1001001111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#1001101111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#1010001111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#1010101111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#1011001111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#1011101111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#1100001111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#1100101111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#1101001111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#1101101111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#1110001111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#1110101111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#1111001111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#1111101111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel + 2#0000110100# => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '1', '0', '0', NONE, '0', '1'), -- lbarx + 2#0001110111# => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), -- lbzux + 2#0001010111# => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- lbzx + 2#0001010100# => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '1', '0', '0', NONE, '0', '1'), -- ldarx + 2#1000010100# => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', ZERO, '0', is8B, '1', '0', '0', '0', '0', '0', NONE, '0', '1'), -- ldbrx + 2#0000110101# => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), -- ldux + 2#0000010101# => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- ldx + 2#0001110100# => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '1', '0', '0', NONE, '0', '1'), -- lharx + 2#0101110111# => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', ZERO, '0', is2B, '0', '1', '1', '0', '0', '0', NONE, '0', '1'), -- lhaux + 2#0101010111# => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', ZERO, '0', is2B, '0', '1', '0', '0', '0', '0', NONE, '0', '1'), -- lhax + 2#1100010110# => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', ZERO, '0', is2B, '1', '0', '0', '0', '0', '0', NONE, '0', '1'), -- lhbrx + 2#0100110111# => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), -- lhzux + 2#0100010111# => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- lhzx + 2#0000010100# => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '1', '0', '0', NONE, '0', '1'), -- lwarx + 2#0101110101# => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', ZERO, '0', is4B, '0', '1', '1', '0', '0', '0', NONE, '0', '1'), -- lwaux + 2#0101010101# => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '1'), -- lwax + 2#1000010110# => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', ZERO, '0', is4B, '1', '0', '0', '0', '0', '0', NONE, '0', '1'), -- lwbrx + 2#0000110111# => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), -- lwzux + 2#0000010111# => (LDST, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- lwzx + -- 2#1000000000# mcrxr + -- 2#1001000000# mcrxrx + 2#0000010011# => (ALU, OP_MFCR, NONE, NONE, NONE, RT, '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- mfcr/mfocrf + 2#0101010011# => (ALU, OP_MFSPR, NONE, NONE, NONE, RT, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- mfspr + 2#0100001001# => (DIV, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- modud + 2#0100001011# => (DIV, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- moduw + 2#1100001001# => (DIV, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- modsd + 2#1100001011# => (DIV, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- modsw + 2#0010010000# => (ALU, OP_MTCRF, NONE, NONE, RS, NONE, '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- mtcrf/mtocrf + 2#0111010011# => (ALU, OP_MTSPR, NONE, NONE, RS, NONE, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- mtspr + 2#0001001001# => (MUL, OP_MUL_H64, RA, RB, NONE, RT, '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '1'), -- mulhd + 2#0000001001# => (MUL, OP_MUL_H64, RA, RB, NONE, RT, '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- mulhdu + 2#0001001011# => (MUL, OP_MUL_H32, RA, RB, NONE, RT, '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '1'), -- mulhw + 2#0000001011# => (MUL, OP_MUL_H32, RA, RB, NONE, RT, '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '1'), -- mulhwu + -- next 4 have reserved bit set + 2#1001001001# => (MUL, OP_MUL_H64, RA, RB, NONE, RT, '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '1'), -- mulhd + 2#1000001001# => (MUL, OP_MUL_H64, RA, RB, NONE, RT, '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- mulhdu + 2#1001001011# => (MUL, OP_MUL_H32, RA, RB, NONE, RT, '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '1'), -- mulhw + 2#1000001011# => (MUL, OP_MUL_H32, RA, RB, NONE, RT, '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '1'), -- mulhwu + 2#0011101001# => (MUL, OP_MUL_L64, RA, RB, NONE, RT, '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '1'), -- mulld + 2#0011101011# => (MUL, OP_MUL_L64, RA, RB, NONE, RT, '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '1'), -- mullw + 2#0111011100# => (ALU, OP_NAND, NONE, RB, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- nand + 2#0001101000# => (ALU, OP_NEG, RA, RB, NONE, RT, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- neg + 2#0001111100# => (ALU, OP_NOR, NONE, RB, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- nor + 2#0110111100# => (ALU, OP_OR, NONE, RB, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- or + 2#0110011100# => (ALU, OP_ORC, NONE, RB, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- orc + 2#0001111010# => (ALU, OP_POPCNTB, NONE, NONE, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- popcntb + 2#0111111010# => (ALU, OP_POPCNTD, NONE, NONE, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- popcntd + 2#0101111010# => (ALU, OP_POPCNTW, NONE, NONE, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- popcntw + 2#0010111010# => (ALU, OP_PRTYD, NONE, NONE, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- prtyd + 2#0010011010# => (ALU, OP_PRTYW, NONE, NONE, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- prtyw + -- 2#0010000000# setb + 2#0000011011# => (ALU, OP_SHL, NONE, RB, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- sld + 2#0000011000# => (ALU, OP_SHL, NONE, RB, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '1'), -- slw + 2#1100011010# => (ALU, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '1'), -- srad + 2#1100111010# => (ALU, OP_SHR, NONE, CONST_SH, RS, RA, '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '1'), -- sradi + 2#1100111011# => (ALU, OP_SHR, NONE, CONST_SH, RS, RA, '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '1'), -- sradi + 2#1100011000# => (ALU, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '1'), -- sraw + 2#1100111000# => (ALU, OP_SHR, NONE, CONST_SH32, RS, RA, '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '1'), -- srawi + 2#1000011011# => (ALU, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- srd + 2#1000011000# => (ALU, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '1'), -- srw + 2#1010110110# => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '1', '0', '0', RC, '0', '1'), -- stbcx + 2#0011110111# => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', RC, '0', '1'), -- stbux + 2#0011010111# => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- stbx + 2#1010010100# => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', ZERO, '0', is8B, '1', '0', '0', '0', '0', '0', NONE, '0', '1'), -- stdbrx + 2#0011010110# => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '1', '0', '0', NONE, '0', '1'), -- stdcx + 2#0010110101# => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), -- stdux + 2#0010010101# => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- stdx + 2#1110010110# => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', ZERO, '0', is2B, '1', '0', '0', '0', '0', '0', NONE, '0', '1'), -- sthbrx + 2#1011010110# => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '1', '0', '0', NONE, '0', '1'), -- sthcx + 2#0110110111# => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), -- sthux + 2#0110010111# => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- sthx + 2#1010010110# => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', ZERO, '0', is4B, '1', '0', '0', '0', '0', '0', NONE, '0', '1'), -- stwbrx + 2#0010010110# => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '1', '0', '0', NONE, '0', '1'), -- stwcx + 2#0010110111# => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), -- stwux + 2#0010010111# => (LDST, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- stwx + 2#0000101000# => (ALU, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- subf + 2#0000001000# => (ALU, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', ONE, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- subfc + 2#0010001000# => (ALU, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- subfe + 2#0011101000# => (ALU, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '1', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- subfme + 2#0011001000# => (ALU, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- subfze + 2#1001010110# => (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- sync + -- 2#0001000100# td + 2#0000000100# => (ALU, OP_TW, RA, RB, NONE, NONE, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- tw + 2#0100111100# => (ALU, OP_XOR, NONE, RB, RS, RA, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- xor + others => illegal_inst ); + constant decode_op_58_array : minor_rom_array_2_t := ( + -- unit internal in1 in2 in3 out CR CR inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl + -- op in out A in out len ext pipe + 0 => (LDST, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- ld + 1 => (LDST, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), -- ldu + 2 => (LDST, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '1'), -- lwa + others => decode_rom_init + ); + + constant decode_op_62_array : minor_rom_array_2_t := ( + -- unit internal in1 in2 in3 out CR CR inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl + -- op in out A in out len ext pipe + 0 => (LDST, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- std + 1 => (LDST, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '1'), -- stdu + others => decode_rom_init + ); + + -- unit internal in1 in2 in3 out CR CR inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl + -- op in out A in out len ext pipe + constant attn_instr : decode_rom_t := (ALU, OP_ILLEGAL, NONE, NONE, NONE, NONE, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'); + constant nop_instr : decode_rom_t := (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'); + constant sim_cfg_instr : decode_rom_t := (ALU, OP_SIM_CONFIG,NONE, NONE, NONE, RT, '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'); + begin decode1_0: process(clk) begin @@ -231,7 +325,8 @@ begin decode1_1: process(all) 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; @@ -240,571 +335,46 @@ begin v.insn := f_in.insn; v.stop_mark := f_in.stop_mark; - ppc_insn := PPC_ILLEGAL; - if f_in.valid = '1' then report "Decode insn " & to_hstring(f_in.insn) & " at " & to_hstring(f_in.nia); + end if; - if std_match(f_in.insn, "011111---------------0100001010-") then - report "PPC_add"; - ppc_insn := PPC_ADD; - elsif std_match(f_in.insn, "011111---------------0000001010-") then - report "PPC_addc"; - ppc_insn := PPC_ADDC; - elsif std_match(f_in.insn, "011111---------------0010001010-") then - report "PPC_adde"; - ppc_insn := PPC_ADDE; - elsif std_match(f_in.insn, "011111---------------0010101010-") then - report "PPC_addex"; - ppc_insn := PPC_ADDEX; - elsif std_match(f_in.insn, "001110--------------------------") then - report "PPC_addi"; - ppc_insn := PPC_ADDI; - elsif std_match(f_in.insn, "001100--------------------------") then - report "PPC_addic"; - ppc_insn := PPC_ADDIC; - elsif std_match(f_in.insn, "001101--------------------------") then - report "PPC_addic."; - ppc_insn := PPC_ADDIC_RC; - elsif std_match(f_in.insn, "001111--------------------------") then - report "PPC_addis"; - ppc_insn := PPC_ADDIS; - elsif std_match(f_in.insn, "011111---------------0011101010-") then - report "PPC_addme"; - ppc_insn := PPC_ADDME; - elsif std_match(f_in.insn, "010011--------------------00010-") then - report "PPC_addpcis"; - ppc_insn := PPC_ADDPCIS; - elsif std_match(f_in.insn, "011111---------------0011001010-") then - report "PPC_addze"; - ppc_insn := PPC_ADDZE; - elsif std_match(f_in.insn, "011111---------------0000011100-") then - report "PPC_and"; - ppc_insn := PPC_AND; - elsif std_match(f_in.insn, "011111---------------0000111100-") then - report "PPC_andc"; - ppc_insn := PPC_ANDC; - elsif std_match(f_in.insn, "011100--------------------------") then - report "PPC_andi."; - ppc_insn := PPC_ANDI_RC; - elsif std_match(f_in.insn, "011101--------------------------") then - report "PPC_andis."; - ppc_insn := PPC_ANDIS_RC; - elsif std_match(f_in.insn, "000000---------------0100000000-") then - report "PPC_attn"; - ppc_insn := PPC_ATTN; - elsif std_match(f_in.insn, "010010------------------------0-") then - report "PPC_b"; - ppc_insn := PPC_B; - elsif std_match(f_in.insn, "010010------------------------1-") then - report "PPC_ba"; - ppc_insn := PPC_BA; - elsif std_match(f_in.insn, "010000------------------------0-") then - report "PPC_bc"; - ppc_insn := PPC_BC; - elsif std_match(f_in.insn, "010000------------------------10") then - report "PPC_bca"; - ppc_insn := PPC_BCA; - elsif std_match(f_in.insn, "010011---------------1000010000-") then - report "PPC_bcctr"; - ppc_insn := PPC_BCCTR; - elsif std_match(f_in.insn, "010000------------------------11") then - report "PPC_bcla"; - ppc_insn := PPC_BCLA; - elsif std_match(f_in.insn, "010011---------------0000010000-") then - report "PPC_bclr"; - ppc_insn := PPC_BCLR; - elsif std_match(f_in.insn, "010011---------------1000110000-") then - report "PPC_bctar"; - ppc_insn := PPC_BCTAR; - elsif std_match(f_in.insn, "011111---------------0011111100-") then - report "PPC_bperm"; - ppc_insn := PPC_BPERM; - elsif std_match(f_in.insn, "011111---------------0000000000-") then - report "PPC_cmp"; - ppc_insn := PPC_CMP; - elsif std_match(f_in.insn, "011111---------------0111111100-") then - report "PPC_cmpb"; - ppc_insn := PPC_CMPB; - elsif std_match(f_in.insn, "011111---------------0011100000-") then - report "PPC_cmpeqb"; - ppc_insn := PPC_CMPEQB; - elsif std_match(f_in.insn, "001011--------------------------") then - report "PPC_cmpi"; - ppc_insn := PPC_CMPI; - elsif std_match(f_in.insn, "011111---------------0000100000-") then - report "PPC_cmpl"; - ppc_insn := PPC_CMPL; - elsif std_match(f_in.insn, "001010--------------------------") then - report "PPC_cmpli"; - ppc_insn := PPC_CMPLI; - elsif std_match(f_in.insn, "011111---------------0011000000-") then - report "PPC_cmprb"; - ppc_insn := PPC_CMPRB; - elsif std_match(f_in.insn, "011111---------------0000111010-") then - report "PPC_cntlzd"; - ppc_insn := PPC_CNTLZD; - elsif std_match(f_in.insn, "011111---------------0000011010-") then - report "PPC_cntlzw"; - ppc_insn := PPC_CNTLZW; - elsif std_match(f_in.insn, "011111---------------1000111010-") then - report "PPC_cnttzd"; - ppc_insn := PPC_CNTTZD; - elsif std_match(f_in.insn, "011111---------------1000011010-") then - report "PPC_cnttzw"; - ppc_insn := PPC_CNTTZW; - elsif std_match(f_in.insn, "010011---------------0100000001-") then - report "PPC_crand"; - ppc_insn := PPC_CRAND; - elsif std_match(f_in.insn, "010011---------------0010000001-") then - report "PPC_crandc"; - ppc_insn := PPC_CRANDC; - elsif std_match(f_in.insn, "010011---------------0100100001-") then - report "PPC_creqv"; - ppc_insn := PPC_CREQV; - elsif std_match(f_in.insn, "010011---------------0011100001-") then - report "PPC_crnand"; - ppc_insn := PPC_CRNAND; - elsif std_match(f_in.insn, "010011---------------0000100001-") then - report "PPC_crnor"; - ppc_insn := PPC_CRNOR; - elsif std_match(f_in.insn, "010011---------------0111000001-") then - report "PPC_cror"; - ppc_insn := PPC_CROR; - elsif std_match(f_in.insn, "010011---------------0110100001-") then - report "PPC_crorc"; - ppc_insn := PPC_CRORC; - elsif std_match(f_in.insn, "010011---------------0011000001-") then - report "PPC_crxor"; - ppc_insn := PPC_CRXOR; - elsif std_match(f_in.insn, "011111---------------1011110011-") then - report "PPC_darn"; - ppc_insn := PPC_DARN; - elsif std_match(f_in.insn, "011111---------------0001010110-") then - report "PPC_dcbf"; - ppc_insn := PPC_DCBF; - elsif std_match(f_in.insn, "011111---------------0000110110-") then - report "PPC_dcbst"; - ppc_insn := PPC_DCBST; - elsif std_match(f_in.insn, "011111---------------0100010110-") then - report "PPC_dcbt"; - ppc_insn := PPC_DCBT; - elsif std_match(f_in.insn, "011111---------------0011110110-") then - report "PPC_dcbtst"; - ppc_insn := PPC_DCBTST; - elsif std_match(f_in.insn, "011111---------------1111110110-") then - report "PPC_dcbz"; - ppc_insn := PPC_DCBZ; - elsif std_match(f_in.insn, "011111----------------11--010-1-") then - report "PPC_div"; - ppc_insn := PPC_DIV; - elsif std_match(f_in.insn, "011111---------------0100011100-") then - report "PPC_eqv"; - ppc_insn := PPC_EQV; - elsif std_match(f_in.insn, "011111---------------1110111010-") then - report "PPC_extsb"; - ppc_insn := PPC_EXTSB; - elsif std_match(f_in.insn, "011111---------------1110011010-") then - report "PPC_extsh"; - ppc_insn := PPC_EXTSH; - elsif std_match(f_in.insn, "011111---------------1111011010-") then - report "PPC_extsw"; - ppc_insn := PPC_EXTSW; - elsif std_match(f_in.insn, "011111---------------110111101--") then - report "PPC_extswsli"; - ppc_insn := PPC_EXTSWSLI; - elsif std_match(f_in.insn, "011111---------------1111010110-") then - report "PPC_icbi"; - ppc_insn := PPC_ICBI; - elsif std_match(f_in.insn, "011111---------------0000010110-") then - report "PPC_icbt"; - ppc_insn := PPC_ICBT; - elsif std_match(f_in.insn, "011111--------------------01111-") then - report "PPC_isel"; - ppc_insn := PPC_ISEL; - elsif std_match(f_in.insn, "010011---------------0010010110-") then - report "PPC_isync"; - ppc_insn := PPC_ISYNC; - elsif std_match(f_in.insn, "011111---------------0000110100-") then - report "PPC_lbarx"; - ppc_insn := PPC_LBARX; - elsif std_match(f_in.insn, "100010--------------------------") then - report "PPC_lbz"; - ppc_insn := PPC_LBZ; - elsif std_match(f_in.insn, "100011--------------------------") then - report "PPC_lbzu"; - ppc_insn := PPC_LBZU; - elsif std_match(f_in.insn, "011111---------------0001110111-") then - report "PPC_lbzux"; - ppc_insn := PPC_LBZUX; - elsif std_match(f_in.insn, "011111---------------0001010111-") then - report "PPC_lbzx"; - ppc_insn := PPC_LBZX; - elsif std_match(f_in.insn, "111010------------------------00") then - report "PPC_ld"; - ppc_insn := PPC_LD; - elsif std_match(f_in.insn, "011111---------------0001010100-") then - report "PPC_ldarx"; - ppc_insn := PPC_LDARX; - elsif std_match(f_in.insn, "011111---------------1000010100-") then - report "PPC_ldbrx"; - ppc_insn := PPC_LDBRX; - elsif std_match(f_in.insn, "111010------------------------01") then - report "PPC_ldu"; - ppc_insn := PPC_LDU; - elsif std_match(f_in.insn, "011111---------------0000110101-") then - report "PPC_ldux"; - ppc_insn := PPC_LDUX; - elsif std_match(f_in.insn, "011111---------------0000010101-") then - report "PPC_ldx"; - ppc_insn := PPC_LDX; - elsif std_match(f_in.insn, "101010--------------------------") then - report "PPC_lha"; - ppc_insn := PPC_LHA; - elsif std_match(f_in.insn, "011111---------------0001110100-") then - report "PPC_lharx"; - ppc_insn := PPC_LHARX; - elsif std_match(f_in.insn, "101011--------------------------") then - report "PPC_lhau"; - ppc_insn := PPC_LHAU; - elsif std_match(f_in.insn, "011111---------------0101110111-") then - report "PPC_lhaux"; - ppc_insn := PPC_LHAUX; - elsif std_match(f_in.insn, "011111---------------0101010111-") then - report "PPC_lhax"; - ppc_insn := PPC_LHAX; - elsif std_match(f_in.insn, "011111---------------1100010110-") then - report "PPC_lhbrx"; - ppc_insn := PPC_LHBRX; - elsif std_match(f_in.insn, "101000--------------------------") then - report "PPC_lhz"; - ppc_insn := PPC_LHZ; - elsif std_match(f_in.insn, "101001--------------------------") then - report "PPC_lhzu"; - ppc_insn := PPC_LHZU; - elsif std_match(f_in.insn, "011111---------------0100110111-") then - report "PPC_lhzux"; - ppc_insn := PPC_LHZUX; - elsif std_match(f_in.insn, "011111---------------0100010111-") then - report "PPC_lhzx"; - ppc_insn := PPC_LHZX; - elsif std_match(f_in.insn, "111010------------------------10") then - report "PPC_lwa"; - ppc_insn := PPC_LWA; - elsif std_match(f_in.insn, "011111---------------0000010100-") then - report "PPC_lwarx"; - ppc_insn := PPC_LWARX; - elsif std_match(f_in.insn, "011111---------------0101110101-") then - report "PPC_lwaux"; - ppc_insn := PPC_LWAUX; - elsif std_match(f_in.insn, "011111---------------0101010101-") then - report "PPC_lwax"; - ppc_insn := PPC_LWAX; - elsif std_match(f_in.insn, "011111---------------1000010110-") then - report "PPC_lwbrx"; - ppc_insn := PPC_LWBRX; - elsif std_match(f_in.insn, "100000--------------------------") then - report "PPC_lwz"; - ppc_insn := PPC_LWZ; - elsif std_match(f_in.insn, "100001--------------------------") then - report "PPC_lwzu"; - ppc_insn := PPC_LWZU; - elsif std_match(f_in.insn, "011111---------------0000110111-") then - report "PPC_lwzux"; - ppc_insn := PPC_LWZUX; - elsif std_match(f_in.insn, "011111---------------0000010111-") then - report "PPC_lwzx"; - ppc_insn := PPC_LWZX; - elsif std_match(f_in.insn, "000100--------------------110000") then - report "PPC_maddhd"; - ppc_insn := PPC_MADDHD; - elsif std_match(f_in.insn, "000100--------------------110001") then - report "PPC_maddhdu"; - ppc_insn := PPC_MADDHDU; - elsif std_match(f_in.insn, "000100--------------------110011") then - report "PPC_maddld"; - ppc_insn := PPC_MADDLD; - elsif std_match(f_in.insn, "010011---------------0000000000-") then - report "PPC_mcrf"; - ppc_insn := PPC_MCRF; - elsif std_match(f_in.insn, "011111---------------1000000000-") then - report "PPC_mcrxr"; - ppc_insn := PPC_MCRXR; - elsif std_match(f_in.insn, "011111---------------1001000000-") then - report "PPC_mcrxrx"; - ppc_insn := PPC_MCRXRX; - elsif std_match(f_in.insn, "011111-----0---------0000010011-") then - report "PPC_mfcr"; - ppc_insn := PPC_MFCR; - elsif std_match(f_in.insn, "011111-----1---------0000010011-") then - report "PPC_mfocrf"; - ppc_insn := PPC_MFOCRF; - -- Specific MF/MT SPR encodings first - elsif std_match(f_in.insn, "011111-----01001000000101010011-") then - report "PPC_mfctr"; - ppc_insn := PPC_MFCTR; - elsif std_match(f_in.insn, "011111-----01000000000101010011-") then - report "PPC_mflr"; - ppc_insn := PPC_MFLR; - elsif std_match(f_in.insn, "011111-----01100010000101010011-") then - report "PPC_mftb"; - ppc_insn := PPC_MFTB; - elsif std_match(f_in.insn, "011111-----01001000000111010011-") then - report "PPC_mtctr"; - ppc_insn := PPC_MTCTR; - elsif std_match(f_in.insn, "011111-----01000000000111010011-") then - report "PPC_mtlr"; - ppc_insn := PPC_MTLR; - elsif std_match(f_in.insn, "011111---------------0101010011-") then - report "PPC_mfspr"; - ppc_insn := PPC_MFSPR; - elsif std_match(f_in.insn, "011111----------------1000010-1-") then - report "PPC_mod"; - ppc_insn := PPC_MOD; - elsif std_match(f_in.insn, "011111-----0---------0010010000-") then - report "PPC_mtcrf"; - ppc_insn := PPC_MTCRF; - elsif std_match(f_in.insn, "011111-----1---------0010010000-") then - report "PPC_mtocrf"; - ppc_insn := PPC_MTOCRF; - elsif std_match(f_in.insn, "011111---------------0111010011-") then - report "PPC_mtspr"; - ppc_insn := PPC_MTSPR; - elsif std_match(f_in.insn, "011111----------------001001001-") then - report "PPC_mulhd"; - ppc_insn := PPC_MULHD; - elsif std_match(f_in.insn, "011111----------------000001001-") then - report "PPC_mulhdu"; - ppc_insn := PPC_MULHDU; - elsif std_match(f_in.insn, "011111----------------001001011-") then - report "PPC_mulhw"; - ppc_insn := PPC_MULHW; - elsif std_match(f_in.insn, "011111----------------000001011-") then - report "PPC_mulhwu"; - ppc_insn := PPC_MULHWU; - elsif std_match(f_in.insn, "011111---------------0011101001-") then - report "PPC_mulld"; - ppc_insn := PPC_MULLD; - elsif std_match(f_in.insn, "000111--------------------------") then - report "PPC_mulli"; - ppc_insn := PPC_MULLI; - elsif std_match(f_in.insn, "011111---------------0011101011-") then - report "PPC_mullw"; - ppc_insn := PPC_MULLW; - elsif std_match(f_in.insn, "011111---------------0111011100-") then - report "PPC_nand"; - ppc_insn := PPC_NAND; - elsif std_match(f_in.insn, "011111---------------0001101000-") then - report "PPC_neg"; - ppc_insn := PPC_NEG; - elsif std_match(f_in.insn, "011111---------------0001111100-") then - report "PPC_nor"; - ppc_insn := PPC_NOR; - elsif std_match(f_in.insn, "011111---------------0110111100-") then - report "PPC_or"; - ppc_insn := PPC_OR; - elsif std_match(f_in.insn, "011111---------------0110011100-") then - report "PPC_orc"; - ppc_insn := PPC_ORC; - -- Has to be before ori - elsif std_match(f_in.insn, "01100000000000000000000000000000") then - report "PPC_nop"; - ppc_insn := PPC_NOP; - elsif std_match(f_in.insn, "011000--------------------------") then - report "PPC_ori"; - ppc_insn := PPC_ORI; - elsif std_match(f_in.insn, "011001--------------------------") then - report "PPC_oris"; - ppc_insn := PPC_ORIS; - elsif std_match(f_in.insn, "011111---------------0001111010-") then - report "PPC_popcntb"; - ppc_insn := PPC_POPCNTB; - elsif std_match(f_in.insn, "011111---------------0111111010-") then - report "PPC_popcntd"; - ppc_insn := PPC_POPCNTD; - elsif std_match(f_in.insn, "011111---------------0101111010-") then - report "PPC_popcntw"; - ppc_insn := PPC_POPCNTW; - elsif std_match(f_in.insn, "011111---------------0010111010-") then - report "PPC_prtyd"; - ppc_insn := PPC_PRTYD; - elsif std_match(f_in.insn, "011111---------------0010011010-") then - report "PPC_prtyw"; - ppc_insn := PPC_PRTYW; - elsif std_match(f_in.insn, "011110---------------------1000-") then - report "PPC_rldcl"; - ppc_insn := PPC_RLDCL; - elsif std_match(f_in.insn, "011110---------------------1001-") then - report "PPC_rldcr"; - ppc_insn := PPC_RLDCR; - elsif std_match(f_in.insn, "011110---------------------010--") then - report "PPC_rldic"; - ppc_insn := PPC_RLDIC; - elsif std_match(f_in.insn, "011110---------------------000--") then - report "PPC_rldicl"; - ppc_insn := PPC_RLDICL; - elsif std_match(f_in.insn, "011110---------------------001--") then - report "PPC_rldicr"; - ppc_insn := PPC_RLDICR; - elsif std_match(f_in.insn, "011110---------------------011--") then - report "PPC_rldimi"; - ppc_insn := PPC_RLDIMI; - elsif std_match(f_in.insn, "010100--------------------------") then - report "PPC_rlwimi"; - ppc_insn := PPC_RLWIMI; - elsif std_match(f_in.insn, "010101--------------------------") then - report "PPC_rlwinm"; - ppc_insn := PPC_RLWINM; - elsif std_match(f_in.insn, "010111--------------------------") then - report "PPC_rlwnm"; - ppc_insn := PPC_RLWNM; - elsif std_match(f_in.insn, "011111---------------0010000000-") then - report "PPC_setb"; - ppc_insn := PPC_SETB; - elsif std_match(f_in.insn, "011111---------------0000011011-") then - report "PPC_sld"; - ppc_insn := PPC_SLD; - elsif std_match(f_in.insn, "011111---------------0000011000-") then - report "PPC_slw"; - ppc_insn := PPC_SLW; - elsif std_match(f_in.insn, "011111---------------1100011010-") then - report "PPC_srad"; - ppc_insn := PPC_SRAD; - elsif std_match(f_in.insn, "011111---------------110011101--") then - report "PPC_sradi"; - ppc_insn := PPC_SRADI; - elsif std_match(f_in.insn, "011111---------------1100011000-") then - report "PPC_sraw"; - ppc_insn := PPC_SRAW; - elsif std_match(f_in.insn, "011111---------------1100111000-") then - report "PPC_srawi"; - ppc_insn := PPC_SRAWI; - elsif std_match(f_in.insn, "011111---------------1000011011-") then - report "PPC_srd"; - ppc_insn := PPC_SRD; - elsif std_match(f_in.insn, "011111---------------1000011000-") then - report "PPC_srw"; - ppc_insn := PPC_SRW; - elsif std_match(f_in.insn, "100110--------------------------") then - report "PPC_stb"; - ppc_insn := PPC_STB; - elsif std_match(f_in.insn, "011111---------------1010110110-") then - report "PPC_stbcx"; - ppc_insn := PPC_STBCX; - elsif std_match(f_in.insn, "100111--------------------------") then - report "PPC_stbu"; - ppc_insn := PPC_STBU; - elsif std_match(f_in.insn, "011111---------------0011110111-") then - report "PPC_stbux"; - ppc_insn := PPC_STBUX; - elsif std_match(f_in.insn, "011111---------------0011010111-") then - report "PPC_stbx"; - ppc_insn := PPC_STBX; - elsif std_match(f_in.insn, "111110------------------------00") then - report "PPC_std"; - ppc_insn := PPC_STD; - elsif std_match(f_in.insn, "011111---------------1010010100-") then - report "PPC_stdbrx"; - ppc_insn := PPC_STDBRX; - elsif std_match(f_in.insn, "011111---------------0011010110-") then - report "PPC_stdcx"; - ppc_insn := PPC_STDCX; - elsif std_match(f_in.insn, "111110------------------------01") then - report "PPC_stdu"; - ppc_insn := PPC_STDU; - elsif std_match(f_in.insn, "011111---------------0010110101-") then - report "PPC_stdux"; - ppc_insn := PPC_STDUX; - elsif std_match(f_in.insn, "011111---------------0010010101-") then - report "PPC_stdx"; - ppc_insn := PPC_STDX; - elsif std_match(f_in.insn, "101100--------------------------") then - report "PPC_sth"; - ppc_insn := PPC_STH; - elsif std_match(f_in.insn, "011111---------------1110010110-") then - report "PPC_sthbrx"; - ppc_insn := PPC_STHBRX; - elsif std_match(f_in.insn, "011111---------------1011010110-") then - report "PPC_sthcx"; - ppc_insn := PPC_STHCX; - elsif std_match(f_in.insn, "101101--------------------------") then - report "PPC_sthu"; - ppc_insn := PPC_STHU; - elsif std_match(f_in.insn, "011111---------------0110110111-") then - report "PPC_sthux"; - ppc_insn := PPC_STHUX; - elsif std_match(f_in.insn, "011111---------------0110010111-") then - report "PPC_sthx"; - ppc_insn := PPC_STHX; - elsif std_match(f_in.insn, "100100--------------------------") then - report "PPC_stw"; - ppc_insn := PPC_STW; - elsif std_match(f_in.insn, "011111---------------1010010110-") then - report "PPC_stwbrx"; - ppc_insn := PPC_STWBRX; - elsif std_match(f_in.insn, "011111---------------0010010110-") then - report "PPC_stwcx"; - ppc_insn := PPC_STWCX; - elsif std_match(f_in.insn, "100101--------------------------") then - report "PPC_stwu"; - ppc_insn := PPC_STWU; - elsif std_match(f_in.insn, "011111---------------0010110111-") then - report "PPC_stwux"; - ppc_insn := PPC_STWUX; - elsif std_match(f_in.insn, "011111---------------0010010111-") then - report "PPC_stwx"; - ppc_insn := PPC_STWX; - elsif std_match(f_in.insn, "011111---------------0000101000-") then - report "PPC_subf"; - ppc_insn := PPC_SUBF; - elsif std_match(f_in.insn, "011111---------------0000001000-") then - report "PPC_subfc"; - ppc_insn := PPC_SUBFC; - elsif std_match(f_in.insn, "011111---------------0010001000-") then - report "PPC_subfe"; - ppc_insn := PPC_SUBFE; - elsif std_match(f_in.insn, "001000--------------------------") then - report "PPC_subfic"; - ppc_insn := PPC_SUBFIC; - elsif std_match(f_in.insn, "011111---------------0011101000-") then - report "PPC_subfme"; - ppc_insn := PPC_SUBFME; - elsif std_match(f_in.insn, "011111---------------0011001000-") then - report "PPC_subfze"; - ppc_insn := PPC_SUBFZE; - elsif std_match(f_in.insn, "011111---------------1001010110-") then - report "PPC_sync"; - ppc_insn := PPC_SYNC; - elsif std_match(f_in.insn, "011111---------------0001000100-") then - report "PPC_td"; - ppc_insn := PPC_TD; - elsif std_match(f_in.insn, "000010--------------------------") then - report "PPC_tdi"; - ppc_insn := PPC_TDI; - elsif std_match(f_in.insn, "011111---------------0000000100-") then - report "PPC_tw"; - ppc_insn := PPC_TW; - elsif std_match(f_in.insn, "000011--------------------------") then - report "PPC_twi"; - ppc_insn := PPC_TWI; - elsif std_match(f_in.insn, "011111---------------0100111100-") then - report "PPC_xor"; - ppc_insn := PPC_XOR; - elsif std_match(f_in.insn, "011010--------------------------") then - report "PPC_xori"; - ppc_insn := PPC_XORI; - elsif std_match(f_in.insn, "011011--------------------------") then - report "PPC_xoris"; - ppc_insn := PPC_XORIS; - elsif std_match(f_in.insn, "000001---------------0000000011-") then - report "PPC_SIM_CONFIG"; - ppc_insn := PPC_SIM_CONFIG; - else - report "PPC_illegal"; - ppc_insn := PPC_ILLEGAL; - end if; + majorop := unsigned(f_in.insn(31 downto 26)); + if majorop = "011111" then + -- major opcode 31, lots of things + v.decode := decode_op_31_array(to_integer(unsigned(f_in.insn(10 downto 1)))); + + elsif majorop = "010011" then + 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 + v.decode := decode_op_30_array(to_integer(unsigned(f_in.insn(4 downto 1)))); + + elsif majorop = "111010" then + v.decode := decode_op_58_array(to_integer(unsigned(f_in.insn(1 downto 0)))); + + elsif majorop = "111110" then + v.decode := decode_op_62_array(to_integer(unsigned(f_in.insn(1 downto 0)))); + + elsif std_match(f_in.insn, "01100000000000000000000000000000") then + report "PPC_nop"; + v.decode := nop_instr; + elsif std_match(f_in.insn, "000001---------------0000000011-") then + report "PPC_SIM_CONFIG"; + v.decode := sim_cfg_instr; + elsif std_match(f_in.insn, "000000---------------0100000000-") then + report "PPC_attn"; + v.decode := attn_instr; - v.decode := decode_rom_array(ppc_insn); + else + v.decode := major_decode_rom_array(to_integer(majorop)); end if; if flush_in = '1' then diff --git a/decode2.vhdl b/decode2.vhdl index 2ace765..c0afcc2 100644 --- a/decode2.vhdl +++ b/decode2.vhdl @@ -62,16 +62,11 @@ architecture behaviour of decode2 is function decode_input_reg_a (t : input_reg_a_t; insn_in : std_ulogic_vector(31 downto 0); reg_data : std_ulogic_vector(63 downto 0)) return decode_input_reg_t is begin - case t is - when RA => + if t = RA or (t = RA_OR_ZERO and insn_ra(insn_in) /= "00000") then return ('1', insn_ra(insn_in), reg_data); - when RA_OR_ZERO => - return ('1', insn_ra(insn_in), ra_or_zero(reg_data, insn_ra(insn_in))); - when RS => - return ('1', insn_rs(insn_in), reg_data); - when NONE => + else return ('0', (others => '0'), (others => '0')); - end case; + end if; end; function decode_input_reg_b (t : input_reg_b_t; insn_in : std_ulogic_vector(31 downto 0); @@ -80,8 +75,6 @@ architecture behaviour of decode2 is case t is when RB => return ('1', insn_rb(insn_in), reg_data); - when RS => - return ('1', insn_rs(insn_in), reg_data); when CONST_UI => return ('0', (others => '0'), std_ulogic_vector(resize(unsigned(insn_ui(insn_in)), 64))); when CONST_SI => @@ -96,6 +89,12 @@ architecture behaviour of decode2 is return ('0', (others => '0'), std_ulogic_vector(resize(signed(insn_bd(insn_in)) & "00", 64))); when CONST_DS => return ('0', (others => '0'), std_ulogic_vector(resize(signed(insn_ds(insn_in)) & "00", 64))); + when CONST_M1 => + return ('0', (others => '0'), x"FFFFFFFFFFFFFFFF"); + when CONST_SH => + return ('0', (others => '0'), x"00000000000000" & "00" & insn_in(1) & insn_in(15 downto 11)); + when CONST_SH32 => + return ('0', (others => '0'), x"00000000000000" & "000" & insn_in(15 downto 11)); when NONE => return ('0', (others => '0'), (others => '0')); end case; @@ -124,58 +123,6 @@ architecture behaviour of decode2 is end case; end; - function decode_const_a (t : constant_a_t; insn_in : std_ulogic_vector(31 downto 0)) return std_ulogic_vector is - begin - case t is - when SH => - return "00" & insn_sh(insn_in); - when SH32 => - return "000" & insn_sh32(insn_in); - when FXM => - return insn_fxm(insn_in); - when BO => - return "000" & insn_bo(insn_in); - when BF => - return "00000" & insn_bf(insn_in); - when TOO => - return "000" & insn_to(insn_in); - when BC => - return "000" & insn_bc(insn_in); - when NONE => - return "00000000"; - end case; - end; - - function decode_const_b (t : constant_b_t; insn_in : std_ulogic_vector(31 downto 0)) return std_ulogic_vector is - begin - case t is - when MB => - return insn_mb(insn_in); - when ME => - return insn_me(insn_in); - when MB32 => - return "0" & insn_mb32(insn_in); - when BI => - return "0" & insn_bi(insn_in); - when L => - return "00000" & insn_l(insn_in); - when NONE => - return "000000"; - end case; - end; - - function decode_const_c (t : constant_c_t; insn_in : std_ulogic_vector(31 downto 0)) return std_ulogic_vector is - begin - case t is - when ME32 => - return insn_me32(insn_in); - when BH => - return "000" & insn_bh(insn_in); - when NONE => - return "00000"; - end case; - end; - function decode_rc (t : rc_t; insn_in : std_ulogic_vector(31 downto 0)) return std_ulogic is begin case t is @@ -202,17 +149,9 @@ begin end if; end process; - r_out.read1_reg <= insn_ra(d_in.insn) when (d_in.decode.input_reg_a = RA) else - insn_ra(d_in.insn) when d_in.decode.input_reg_a = RA_OR_ZERO else - insn_rs(d_in.insn) when d_in.decode.input_reg_a = RS else - (others => '0'); - - r_out.read2_reg <= insn_rb(d_in.insn) when d_in.decode.input_reg_b = RB else - insn_rs(d_in.insn) when d_in.decode.input_reg_b = RS else - (others => '0'); - - r_out.read3_reg <= insn_rs(d_in.insn) when d_in.decode.input_reg_c = RS else - (others => '0'); + r_out.read1_reg <= insn_ra(d_in.insn); + r_out.read2_reg <= insn_rb(d_in.insn); + r_out.read3_reg <= insn_rs(d_in.insn); c_out.read <= d_in.decode.input_cr; @@ -257,17 +196,19 @@ begin v.e.read_data1 := decoded_reg_a.data; v.e.read_reg2 := decoded_reg_b.reg; v.e.read_data2 := decoded_reg_b.data; + v.e.read_data3 := decoded_reg_c.data; v.e.write_reg := decode_output_reg(d_in.decode.output_reg_a, d_in.insn); v.e.rc := decode_rc(d_in.decode.rc, d_in.insn); v.e.cr := c_in.read_cr_data; + v.e.invert_a := d_in.decode.invert_a; v.e.input_carry := d_in.decode.input_carry; v.e.output_carry := d_in.decode.output_carry; + v.e.is_32bit := d_in.decode.is_32bit; + v.e.is_signed := d_in.decode.is_signed; if d_in.decode.lr = '1' then v.e.lr := insn_lk(d_in.insn); end if; - v.e.const1 := decode_const_a(d_in.decode.const_a, d_in.insn); - v.e.const2 := decode_const_b(d_in.decode.const_b, d_in.insn); - v.e.const3 := decode_const_c(d_in.decode.const_c, d_in.insn); + v.e.insn := d_in.insn; -- multiply unit v.m.insn_type := d_in.decode.insn_type; @@ -276,8 +217,8 @@ begin v.m.write_reg := decode_output_reg(d_in.decode.output_reg_a, d_in.insn); v.m.rc := decode_rc(d_in.decode.rc, d_in.insn); - if d_in.decode.mul_32bit = '1' then - if d_in.decode.mul_signed = '1' then + if d_in.decode.is_32bit = '1' then + if d_in.decode.is_signed = '1' then v.m.data1 := (others => mul_a(31)); v.m.data1(31 downto 0) := mul_a(31 downto 0); v.m.data2 := (others => mul_b(31)); @@ -287,7 +228,7 @@ begin v.m.data2 := '0' & x"00000000" & mul_b(31 downto 0); end if; else - if d_in.decode.mul_signed = '1' then + if d_in.decode.is_signed = '1' then v.m.data1 := mul_a(63) & mul_a; v.m.data2 := mul_b(63) & mul_b; else diff --git a/decode_types.vhdl b/decode_types.vhdl index 64e6dfa..54b17e7 100644 --- a/decode_types.vhdl +++ b/decode_types.vhdl @@ -2,71 +2,30 @@ library ieee; use ieee.std_logic_1164.all; package decode_types is - type ppc_insn_t is (PPC_ILLEGAL, PPC_ADD, PPC_ADDC, PPC_ADDE, - PPC_ADDEX, PPC_ADDI, PPC_ADDIC, PPC_ADDIC_RC, PPC_ADDIS, - PPC_ADDME, PPC_ADDPCIS, PPC_ADDZE, PPC_AND, PPC_ANDC, - PPC_ANDI_RC, PPC_ANDIS_RC, PPC_ATTN, PPC_B, PPC_BA, PPC_BC, - PPC_BCA, PPC_BCCTR, PPC_BCLA, PPC_BCLR, PPC_BCTAR, PPC_BPERM, - PPC_CMP, PPC_CMPB, PPC_CMPEQB, PPC_CMPI, PPC_CMPL, PPC_CMPLI, - PPC_CMPRB, PPC_CNTLZD, PPC_CNTLZW, PPC_CNTTZD, PPC_CNTTZW, - PPC_CRAND, PPC_CRANDC, PPC_CREQV, PPC_CRNAND, PPC_CRNOR, - PPC_CROR, PPC_CRORC, PPC_CRXOR, PPC_DARN, PPC_DCBF, PPC_DCBST, - PPC_DCBT, PPC_DCBTST, PPC_DCBZ, PPC_DIV, - PPC_EQV, PPC_EXTSB, PPC_EXTSH, PPC_EXTSW, - PPC_EXTSWSLI, PPC_ICBI, PPC_ICBT, PPC_ISEL, PPC_ISYNC, - PPC_LBARX, PPC_LBZ, PPC_LBZU, PPC_LBZUX, PPC_LBZX, PPC_LD, - PPC_LDARX, PPC_LDBRX, PPC_LDU, PPC_LDUX, PPC_LDX, PPC_LHA, - PPC_LHARX, PPC_LHAU, PPC_LHAUX, PPC_LHAX, PPC_LHBRX, PPC_LHZ, - PPC_LHZU, PPC_LHZUX, PPC_LHZX, PPC_LWA, PPC_LWARX, PPC_LWAUX, - PPC_LWAX, PPC_LWBRX, PPC_LWZ, PPC_LWZU, PPC_LWZUX, PPC_LWZX, - PPC_MADDHD, PPC_MADDHDU, PPC_MADDLD, PPC_MCRF, PPC_MCRXR, - PPC_MCRXRX, PPC_MFCR, PPC_MFOCRF, PPC_MFSPR, PPC_MFTB, - PPC_MOD, PPC_MTCRF, - PPC_MFCTR, PPC_MTCTR, PPC_MFLR, PPC_MTLR, PPC_MTOCRF, - PPC_MTSPR, PPC_MULHD, PPC_MULHDU, PPC_MULHW, PPC_MULHWU, - PPC_MULLD, PPC_MULLI, PPC_MULLW, PPC_NAND, PPC_NEG, PPC_NOR, PPC_NOP, - PPC_OR, PPC_ORC, PPC_ORI, PPC_ORIS, PPC_POPCNTB, PPC_POPCNTD, - PPC_POPCNTW, PPC_PRTYD, PPC_PRTYW, PPC_RLDCL, PPC_RLDCR, - PPC_RLDIC, PPC_RLDICL, PPC_RLDICR, PPC_RLDIMI, PPC_RLWIMI, - PPC_RLWINM, PPC_RLWNM, PPC_SETB, PPC_SLD, PPC_SLW, PPC_SRAD, - PPC_SRADI, PPC_SRAW, PPC_SRAWI, PPC_SRD, PPC_SRW, PPC_STB, - PPC_STBCX, PPC_STBU, PPC_STBUX, PPC_STBX, PPC_STD, PPC_STDBRX, - PPC_STDCX, PPC_STDU, PPC_STDUX, PPC_STDX, PPC_STH, PPC_STHBRX, - PPC_STHCX, PPC_STHU, PPC_STHUX, PPC_STHX, PPC_STW, PPC_STWBRX, - PPC_STWCX, PPC_STWU, PPC_STWUX, PPC_STWX, PPC_SUBF, PPC_SUBFC, - PPC_SUBFE, PPC_SUBFIC, PPC_SUBFME, PPC_SUBFZE, PPC_SYNC, PPC_TD, - PPC_TDI, PPC_TW, PPC_TWI, PPC_XOR, PPC_XORI, PPC_XORIS, - 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_BA, OP_BC, - OP_BCA, OP_BCCTR, OP_BCLA, OP_BCLR, OP_BCTAR, OP_BPERM, OP_CMP, - OP_CMPB, OP_CMPEQB, OP_CMPL, OP_CMPRB, + type insn_type_t is (OP_ILLEGAL, OP_NOP, OP_ADD, + 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, OP_DCBZ, OP_DIV, OP_EQV, OP_EXTSB, OP_EXTSH, OP_EXTSW, OP_EXTSWSLI, OP_ICBI, OP_ICBT, OP_ISEL, OP_ISYNC, OP_LOAD, OP_STORE, OP_MADDHD, OP_MADDHDU, OP_MADDLD, OP_MCRF, - OP_MCRXR, OP_MCRXRX, OP_MFCR, OP_MFOCRF, OP_MFCTR, OP_MFLR, - OP_MFTB, OP_MFSPR, OP_MOD, - OP_MTCRF, OP_MTOCRF, OP_MTCTR, OP_MTLR, OP_MTSPR, OP_MUL_L64, + OP_MCRXR, OP_MCRXRX, OP_MFCR, OP_MFSPR, OP_MOD, + OP_MTCRF, OP_MTSPR, OP_MUL_L64, OP_MUL_H64, OP_MUL_H32, OP_NAND, OP_NEG, OP_NOR, OP_OR, OP_ORC, OP_POPCNTB, OP_POPCNTD, OP_POPCNTW, OP_PRTYD, - OP_PRTYW, OP_RLDCL, OP_RLDCR, OP_RLDIC, OP_RLDICL, OP_RLDICR, - OP_RLDIMI, OP_RLWIMI, OP_RLWINM, OP_RLWNM, OP_SETB, OP_SLD, - OP_SLW, OP_SRAD, OP_SRADI, OP_SRAW, OP_SRAWI, OP_SRD, OP_SRW, - OP_SUBF, OP_SUBFE, OP_SUBFME, OP_SYNC, OP_TD, OP_TDI, OP_TW, + OP_PRTYW, OP_RLC, OP_RLCL, OP_RLCR, OP_SETB, + OP_SHL, OP_SHR, + OP_SYNC, OP_TD, OP_TDI, OP_TW, OP_TWI, OP_XOR, OP_SIM_CONFIG); - type input_reg_a_t is (NONE, RA, RA_OR_ZERO, RS); - type input_reg_b_t is (NONE, RB, RS, CONST_UI, CONST_SI, CONST_SI_HI, CONST_UI_HI, CONST_LI, CONST_BD, CONST_DS); + type input_reg_a_t is (NONE, RA, RA_OR_ZERO); + type input_reg_b_t is (NONE, RB, CONST_UI, CONST_SI, CONST_SI_HI, CONST_UI_HI, CONST_LI, CONST_BD, CONST_DS, CONST_M1, CONST_SH, CONST_SH32); type input_reg_c_t is (NONE, RS); type output_reg_a_t is (NONE, RT, RA); - type constant_a_t is (NONE, SH, SH32, FXM, BO, BF, TOO, BC); - type constant_b_t is (NONE, MB, ME, MB32, BI, L); - type constant_c_t is (NONE, ME32, BH); type rc_t is (NONE, ONE, RC); + type carry_in_t is (ZERO, CA, ONE); constant SH_OFFSET : integer := 0; constant MB_OFFSET : integer := 1; @@ -97,14 +56,11 @@ package decode_types is input_reg_c : input_reg_c_t; output_reg_a : output_reg_a_t; - const_a : constant_a_t; - const_b : constant_b_t; - const_c : constant_c_t; - input_cr : std_ulogic; output_cr : std_ulogic; - input_carry : std_ulogic; + invert_a : std_ulogic; + input_carry : carry_in_t; output_carry : std_ulogic; -- load/store signals @@ -114,9 +70,9 @@ package decode_types is update : std_ulogic; reserve : std_ulogic; - -- multiplier signals - mul_32bit : std_ulogic; - mul_signed : std_ulogic; + -- multiplier and ALU signals + is_32bit : std_ulogic; + is_signed : std_ulogic; rc : rc_t; lr : std_ulogic; @@ -126,12 +82,11 @@ package decode_types is constant decode_rom_init : decode_rom_t := (unit => NONE, insn_type => OP_ILLEGAL, input_reg_a => NONE, input_reg_b => NONE, input_reg_c => NONE, - output_reg_a => NONE, const_a => NONE, const_b => NONE, - const_c => NONE, input_cr => '0', output_cr => '0', - input_carry => '0', output_carry => '0', + output_reg_a => NONE, input_cr => '0', output_cr => '0', + invert_a => '0', input_carry => ZERO, output_carry => '0', length => NONE, byte_reverse => '0', sign_extend => '0', - update => '0', reserve => '0', mul_32bit => '0', - mul_signed => '0', rc => NONE, lr => '0', sgl_pipe => '0'); + update => '0', reserve => '0', is_32bit => '0', + is_signed => '0', rc => NONE, lr => '0', sgl_pipe => '0'); end decode_types; diff --git a/execute1.vhdl b/execute1.vhdl index cec431f..9f54bad 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -7,6 +7,7 @@ use work.decode_types.all; use work.common.all; use work.helpers.all; use work.crhelpers.all; +use work.insn_helpers.all; use work.ppc_fx_insns.all; entity execute1 is @@ -40,7 +41,39 @@ architecture behaviour of execute1 is signal ctrl: ctrl_t := (carry => '0', others => (others => '0')); signal ctrl_tmp: ctrl_t := (carry => '0', others => (others => '0')); + + signal right_shift, rot_clear_left, rot_clear_right: std_ulogic; + signal rotator_result: std_ulogic_vector(63 downto 0); + signal rotator_carry: std_ulogic; + + function decode_input_carry (carry_sel : carry_in_t; ca_in : std_ulogic) return std_ulogic is + begin + case carry_sel is + when ZERO => + return '0'; + when CA => + return ca_in; + when ONE => + return '1'; + end case; + end; begin + + rotator_0: entity work.rotator + port map ( + rs => e_in.read_data3, + ra => e_in.read_data1, + shift => e_in.read_data2(6 downto 0), + insn => e_in.insn, + is_32bit => e_in.is_32bit, + right_shift => right_shift, + arith => e_in.is_signed, + clear_left => rot_clear_left, + clear_right => rot_clear_right, + result => rotator_result, + carry_out => rotator_carry + ); + execute1_0: process(clk) begin if rising_edge(clk) then @@ -51,11 +84,19 @@ begin execute1_1: process(all) variable v : reg_type; + variable a_inv : std_ulogic_vector(63 downto 0); variable result : std_ulogic_vector(63 downto 0); + variable newcrf : std_ulogic_vector(3 downto 0); variable result_with_carry : std_ulogic_vector(64 downto 0); variable result_en : integer; variable crnum : integer; + variable scrnum : integer; variable lo, hi : integer; + variable sh, mb, me : std_ulogic_vector(5 downto 0); + variable sh32, mb32, me32 : std_ulogic_vector(4 downto 0); + variable bo, bi : std_ulogic_vector(4 downto 0); + variable bf, bfa : std_ulogic_vector(2 downto 0); + variable l : std_ulogic; begin result := (others => '0'); result_with_carry := (others => '0'); @@ -72,6 +113,11 @@ begin terminate_out <= '0'; f_out <= Execute1ToFetch1TypeInit; + -- rotator control signals + right_shift <= '1' when e_in.insn_type = OP_SHR else '0'; + rot_clear_left <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCL else '0'; + rot_clear_right <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCR else '0'; + if e_in.valid = '1' then v.e.valid := '1'; @@ -85,232 +131,218 @@ begin when OP_NOP => -- Do nothing when OP_ADD => - result := ppc_add(e_in.read_data1, e_in.read_data2); - result_en := 1; - when OP_ADDE => - result_with_carry := ppc_adde(e_in.read_data1, e_in.read_data2, ctrl.carry and e_in.input_carry); + if e_in.invert_a = '0' then + a_inv := e_in.read_data1; + else + a_inv := not e_in.read_data1; + end if; + result_with_carry := ppc_adde(a_inv, e_in.read_data2, decode_input_carry(e_in.input_carry, ctrl.carry)); result := result_with_carry(63 downto 0); - ctrl_tmp.carry <= result_with_carry(64) and e_in.output_carry; + if e_in.output_carry then + ctrl_tmp.carry <= result_with_carry(64); + end if; result_en := 1; when OP_AND => - result := ppc_and(e_in.read_data1, e_in.read_data2); + result := ppc_and(e_in.read_data3, e_in.read_data2); result_en := 1; when OP_ANDC => - result := ppc_andc(e_in.read_data1, e_in.read_data2); + result := ppc_andc(e_in.read_data3, e_in.read_data2); result_en := 1; when OP_B => f_out.redirect <= '1'; - f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2)); + if (insn_aa(e_in.insn)) then + f_out.redirect_nia <= std_ulogic_vector(signed(e_in.read_data2)); + else + f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2)); + end if; when OP_BC => - if e_in.const1(4-2) = '0' then + bo := insn_bo(e_in.insn); + bi := insn_bi(e_in.insn); + if bo(4-2) = '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 + if ppc_bc_taken(bo, bi, e_in.cr, ctrl.ctr) = 1 then f_out.redirect <= '1'; - f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2)); + if (insn_aa(e_in.insn)) then + f_out.redirect_nia <= std_ulogic_vector(signed(e_in.read_data2)); + else + 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 + bo := insn_bo(e_in.insn); + bi := insn_bi(e_in.insn); + if bo(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 + if ppc_bc_taken(bo, bi, e_in.cr, ctrl.ctr) = 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); + result := ppc_cmpb(e_in.read_data3, e_in.read_data2); result_en := 1; when OP_CMP => + bf := insn_bf(e_in.insn); + l := insn_l(e_in.insn); v.e.write_cr_enable := '1'; - crnum := to_integer(unsigned(e_in.const1(2 downto 0))); + crnum := to_integer(unsigned(bf)); v.e.write_cr_mask := num_to_fxm(crnum); for i in 0 to 7 loop lo := i*4; hi := lo + 3; - v.e.write_cr_data(hi downto lo) := ppc_cmp(e_in.const2(0), e_in.read_data1, e_in.read_data2); + v.e.write_cr_data(hi downto lo) := ppc_cmp(l, e_in.read_data1, e_in.read_data2); end loop; when OP_CMPL => + bf := insn_bf(e_in.insn); + l := insn_l(e_in.insn); v.e.write_cr_enable := '1'; - crnum := to_integer(unsigned(e_in.const1(2 downto 0))); + crnum := to_integer(unsigned(bf)); v.e.write_cr_mask := num_to_fxm(crnum); for i in 0 to 7 loop lo := i*4; hi := lo + 3; - v.e.write_cr_data(hi downto lo) := ppc_cmpl(e_in.const2(0), e_in.read_data1, e_in.read_data2); + v.e.write_cr_data(hi downto lo) := ppc_cmpl(l, e_in.read_data1, e_in.read_data2); end loop; when OP_CNTLZW => - result := ppc_cntlzw(e_in.read_data1); + result := ppc_cntlzw(e_in.read_data3); result_en := 1; when OP_CNTTZW => - result := ppc_cnttzw(e_in.read_data1); + result := ppc_cnttzw(e_in.read_data3); result_en := 1; when OP_CNTLZD => - result := ppc_cntlzd(e_in.read_data1); + result := ppc_cntlzd(e_in.read_data3); result_en := 1; when OP_CNTTZD => - result := ppc_cnttzd(e_in.read_data1); + result := ppc_cnttzd(e_in.read_data3); result_en := 1; when OP_EXTSB => - result := ppc_extsb(e_in.read_data1); + result := ppc_extsb(e_in.read_data3); result_en := 1; when OP_EXTSH => - result := ppc_extsh(e_in.read_data1); + result := ppc_extsh(e_in.read_data3); result_en := 1; when OP_EXTSW => - result := ppc_extsw(e_in.read_data1); + result := ppc_extsw(e_in.read_data3); result_en := 1; when OP_EQV => - result := ppc_eqv(e_in.read_data1, e_in.read_data2); + result := ppc_eqv(e_in.read_data3, e_in.read_data2); result_en := 1; when OP_ISEL => - crnum := to_integer(unsigned(e_in.const1)); + crnum := to_integer(unsigned(insn_bc(e_in.insn))); if e_in.cr(31-crnum) = '1' then result := e_in.read_data1; else result := e_in.read_data2; end if; result_en := 1; - when OP_MFCTR => - result := ctrl.ctr; - result_en := 1; - when OP_MFLR => - result := ctrl.lr; - result_en := 1; - when OP_MFTB => - result := ctrl.tb; - result_en := 1; - when OP_MTCTR => - ctrl_tmp.ctr <= e_in.read_data1; - when OP_MTLR => - ctrl_tmp.lr <= e_in.read_data1; - when OP_MFCR => - result := x"00000000" & e_in.cr; - result_en := 1; - when OP_MFOCRF => - crnum := fxm_to_num(e_in.const1(7 downto 0)); - result := (others => '0'); + when OP_MCRF => + bf := insn_bf(e_in.insn); + bfa := insn_bfa(e_in.insn); + v.e.write_cr_enable := '1'; + crnum := to_integer(unsigned(bf)); + scrnum := to_integer(unsigned(bfa)); + v.e.write_cr_mask := num_to_fxm(crnum); + for i in 0 to 7 loop + lo := (7-i)*4; + hi := lo + 3; + if i = scrnum then + newcrf := e_in.cr(hi downto lo); + end if; + end loop; for i in 0 to 7 loop - lo := (7-i)*4; + lo := i*4; hi := lo + 3; - if crnum = i then - result(hi downto lo) := e_in.cr(hi downto lo); - end if; + v.e.write_cr_data(hi downto lo) := newcrf; end loop; + when OP_MFSPR => + if std_match(e_in.insn(20 downto 11), "0100100000") then + result := ctrl.ctr; + result_en := 1; + elsif std_match(e_in.insn(20 downto 11), "0100000000") then + result := ctrl.lr; + result_en := 1; + elsif std_match(e_in.insn(20 downto 11), "0110001000") then + result := ctrl.tb; + result_en := 1; + end if; + when OP_MFCR => + if e_in.insn(20) = '0' then + -- mfcr + result := x"00000000" & e_in.cr; + else + -- mfocrf + crnum := fxm_to_num(insn_fxm(e_in.insn)); + result := (others => '0'); + for i in 0 to 7 loop + lo := (7-i)*4; + hi := lo + 3; + if crnum = i then + result(hi downto lo) := e_in.cr(hi downto lo); + end if; + end loop; + end if; result_en := 1; when OP_MTCRF => v.e.write_cr_enable := '1'; - v.e.write_cr_mask := e_in.const1(7 downto 0); - v.e.write_cr_data := e_in.read_data1(31 downto 0); - when OP_MTOCRF => - v.e.write_cr_enable := '1'; - -- We require one hot priority encoding here - crnum := fxm_to_num(e_in.const1(7 downto 0)); - v.e.write_cr_mask := num_to_fxm(crnum); - v.e.write_cr_data := e_in.read_data1(31 downto 0); + if e_in.insn(20) = '0' then + -- mtcrf + v.e.write_cr_mask := insn_fxm(e_in.insn); + else + -- mtocrf: We require one hot priority encoding here + crnum := fxm_to_num(insn_fxm(e_in.insn)); + v.e.write_cr_mask := num_to_fxm(crnum); + end if; + v.e.write_cr_data := e_in.read_data3(31 downto 0); + when OP_MTSPR => + if std_match(e_in.insn(20 downto 11), "0100100000") then + ctrl_tmp.ctr <= e_in.read_data3; + elsif std_match(e_in.insn(20 downto 11), "0100000000") then + ctrl_tmp.lr <= e_in.read_data3; + end if; when OP_NAND => - result := ppc_nand(e_in.read_data1, e_in.read_data2); + result := ppc_nand(e_in.read_data3, e_in.read_data2); result_en := 1; when OP_NEG => result := ppc_neg(e_in.read_data1); result_en := 1; when OP_NOR => - result := ppc_nor(e_in.read_data1, e_in.read_data2); + result := ppc_nor(e_in.read_data3, e_in.read_data2); result_en := 1; when OP_OR => - result := ppc_or(e_in.read_data1, e_in.read_data2); + result := ppc_or(e_in.read_data3, e_in.read_data2); result_en := 1; when OP_ORC => - result := ppc_orc(e_in.read_data1, e_in.read_data2); + result := ppc_orc(e_in.read_data3, e_in.read_data2); result_en := 1; when OP_POPCNTB => - result := ppc_popcntb(e_in.read_data1); + result := ppc_popcntb(e_in.read_data3); result_en := 1; when OP_POPCNTW => - result := ppc_popcntw(e_in.read_data1); + result := ppc_popcntw(e_in.read_data3); result_en := 1; when OP_POPCNTD => - result := ppc_popcntd(e_in.read_data1); + result := ppc_popcntd(e_in.read_data3); result_en := 1; when OP_PRTYD => - result := ppc_prtyd(e_in.read_data1); + result := ppc_prtyd(e_in.read_data3); result_en := 1; when OP_PRTYW => - result := ppc_prtyw(e_in.read_data1); + result := ppc_prtyw(e_in.read_data3); result_en := 1; - when OP_RLDCL => - result := ppc_rldcl(e_in.read_data1, e_in.read_data2, e_in.const2(5 downto 0)); - result_en := 1; - when OP_RLDCR => - result := ppc_rldcr(e_in.read_data1, e_in.read_data2, e_in.const2(5 downto 0)); - result_en := 1; - when OP_RLDICL => - result := ppc_rldicl(e_in.read_data1, e_in.const1(5 downto 0), e_in.const2(5 downto 0)); - result_en := 1; - when OP_RLDICR => - result := ppc_rldicr(e_in.read_data1, e_in.const1(5 downto 0), e_in.const2(5 downto 0)); - result_en := 1; - when OP_RLWNM => - result := ppc_rlwnm(e_in.read_data1, e_in.read_data2, e_in.const2(4 downto 0), e_in.const3(4 downto 0)); - result_en := 1; - when OP_RLWINM => - result := ppc_rlwinm(e_in.read_data1, e_in.const1(4 downto 0), e_in.const2(4 downto 0), e_in.const3(4 downto 0)); - result_en := 1; - when OP_RLDIC => - result := ppc_rldic(e_in.read_data1, e_in.const1(5 downto 0), e_in.const2(5 downto 0)); - result_en := 1; - when OP_RLDIMI => - result := ppc_rldimi(e_in.read_data1, e_in.read_data2, e_in.const1(5 downto 0), e_in.const2(5 downto 0)); - result_en := 1; - when OP_RLWIMI => - result := ppc_rlwimi(e_in.read_data1, e_in.read_data2, e_in.const1(4 downto 0), e_in.const2(4 downto 0), e_in.const3(4 downto 0)); - result_en := 1; - when OP_SLD => - result := ppc_sld(e_in.read_data1, e_in.read_data2); - result_en := 1; - when OP_SLW => - result := ppc_slw(e_in.read_data1, e_in.read_data2); - result_en := 1; - when OP_SRAW => - result_with_carry := ppc_sraw(e_in.read_data1, e_in.read_data2); - result := result_with_carry(63 downto 0); - ctrl_tmp.carry <= result_with_carry(64); - result_en := 1; - when OP_SRAWI => - result_with_carry := ppc_srawi(e_in.read_data1, e_in.const1(5 downto 0)); - result := result_with_carry(63 downto 0); - ctrl_tmp.carry <= result_with_carry(64); - result_en := 1; - when OP_SRAD => - result_with_carry := ppc_srad(e_in.read_data1, e_in.read_data2); - result := result_with_carry(63 downto 0); - ctrl_tmp.carry <= result_with_carry(64); - result_en := 1; - when OP_SRADI => - result_with_carry := ppc_sradi(e_in.read_data1, e_in.const1(5 downto 0)); - result := result_with_carry(63 downto 0); - ctrl_tmp.carry <= result_with_carry(64); - result_en := 1; - when OP_SRD => - result := ppc_srd(e_in.read_data1, e_in.read_data2); - result_en := 1; - when OP_SRW => - result := ppc_srw(e_in.read_data1, e_in.read_data2); - result_en := 1; - when OP_SUBF => - result := ppc_subf(e_in.read_data1, e_in.read_data2); - result_en := 1; - when OP_SUBFE => - result_with_carry := ppc_subfe(e_in.read_data1, e_in.read_data2, ctrl.carry or not(e_in.input_carry)); - result := result_with_carry(63 downto 0); - ctrl_tmp.carry <= result_with_carry(64) and e_in.output_carry; + when OP_RLC | OP_RLCL | OP_RLCR | OP_SHL | OP_SHR => + result := rotator_result; + if e_in.output_carry = '1' then + ctrl_tmp.carry <= rotator_carry; + end if; result_en := 1; when OP_XOR => - result := ppc_xor(e_in.read_data1, e_in.read_data2); + result := ppc_xor(e_in.read_data3, e_in.read_data2); result_en := 1; when OP_SIM_CONFIG => diff --git a/insn_helpers.vhdl b/insn_helpers.vhdl index e91e9e6..d3ddcca 100644 --- a/insn_helpers.vhdl +++ b/insn_helpers.vhdl @@ -14,9 +14,11 @@ package insn_helpers is function insn_me32 (insn_in : std_ulogic_vector) return std_ulogic_vector; function insn_li (insn_in : std_ulogic_vector) return std_ulogic_vector; function insn_lk (insn_in : std_ulogic_vector) return std_ulogic; + function insn_aa (insn_in : std_ulogic_vector) return std_ulogic; function insn_rc (insn_in : std_ulogic_vector) return std_ulogic; function insn_bd (insn_in : std_ulogic_vector) return std_ulogic_vector; function insn_bf (insn_in : std_ulogic_vector) return std_ulogic_vector; + function insn_bfa (insn_in : std_ulogic_vector) return std_ulogic_vector; function insn_fxm (insn_in : std_ulogic_vector) return std_ulogic_vector; function insn_bo (insn_in : std_ulogic_vector) return std_ulogic_vector; function insn_bi (insn_in : std_ulogic_vector) return std_ulogic_vector; @@ -91,6 +93,11 @@ package body insn_helpers is return insn_in(0); end; + function insn_aa (insn_in : std_ulogic_vector) return std_ulogic is + begin + return insn_in(1); + end; + function insn_rc (insn_in : std_ulogic_vector) return std_ulogic is begin return insn_in(0); @@ -106,6 +113,11 @@ package body insn_helpers is return insn_in(25 downto 23); end; + function insn_bfa (insn_in : std_ulogic_vector) return std_ulogic_vector is + begin + return insn_in(20 downto 18); + end; + function insn_fxm (insn_in : std_ulogic_vector) return std_ulogic_vector is begin return insn_in(19 downto 12); diff --git a/microwatt.core b/microwatt.core index 94ff0c1..6143f50 100644 --- a/microwatt.core +++ b/microwatt.core @@ -24,6 +24,7 @@ filesets: - loadstore2.vhdl - multiply.vhdl - divider.vhdl + - rotator.vhdl - writeback.vhdl - insn_helpers.vhdl - core.vhdl diff --git a/ppc_fx_insns.vhdl b/ppc_fx_insns.vhdl index ea42b6d..407881f 100644 --- a/ppc_fx_insns.vhdl +++ b/ppc_fx_insns.vhdl @@ -89,7 +89,6 @@ package ppc_fx_insns is function ppc_divd (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector; function ppc_divwu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector; - function ppc_b (nia: std_ulogic_vector(63 downto 0); bd: std_ulogic_vector(23 downto 0)) return std_ulogic_vector; function ppc_bc_taken(bo, bi: std_ulogic_vector(4 downto 0); cr: std_ulogic_vector(31 downto 0); ctr: std_ulogic_vector(63 downto 0)) return integer; function ppc_bcctr_taken(bo, bi: std_ulogic_vector(4 downto 0); cr: std_ulogic_vector(31 downto 0)) return integer; end package ppc_fx_insns; @@ -779,11 +778,6 @@ package body ppc_fx_insns is return std_ulogic_vector(resize(tmp, ra'length)); end; - function ppc_b (nia: std_ulogic_vector(63 downto 0); bd: std_ulogic_vector(23 downto 0)) return std_ulogic_vector is - begin - return std_ulogic_vector(signed(nia) + signed(bd & "00")); - end; - function ppc_bc_taken(bo, bi: std_ulogic_vector(4 downto 0); cr: std_ulogic_vector(31 downto 0); ctr: std_ulogic_vector(63 downto 0)) return integer is variable crfield: integer; variable crbit_match: std_ulogic; diff --git a/rotator.vhdl b/rotator.vhdl new file mode 100644 index 0000000..d8a8ee9 --- /dev/null +++ b/rotator.vhdl @@ -0,0 +1,183 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.common.all; + +entity rotator is + port (rs: in std_ulogic_vector(63 downto 0); + ra: in std_ulogic_vector(63 downto 0); + shift: in std_ulogic_vector(6 downto 0); + insn: in std_ulogic_vector(31 downto 0); + is_32bit: in std_ulogic; + right_shift: in std_ulogic; + arith: in std_ulogic; + clear_left: in std_ulogic; + clear_right: in std_ulogic; + result: out std_ulogic_vector(63 downto 0); + carry_out: out std_ulogic + ); +end entity rotator; + +architecture behaviour of rotator is + signal repl32: std_ulogic_vector(63 downto 0); + signal rot_count: std_ulogic_vector(5 downto 0); + signal rot1, rot2, rot: std_ulogic_vector(63 downto 0); + signal sh, mb, me: std_ulogic_vector(6 downto 0); + signal mr, ml: std_ulogic_vector(63 downto 0); + signal output_mode: std_ulogic_vector(1 downto 0); + + -- note BE bit numbering + function right_mask(mask_begin: std_ulogic_vector(6 downto 0)) return std_ulogic_vector is + variable ret: std_ulogic_vector(63 downto 0); + begin + ret := (others => '0'); + for i in 0 to 63 loop + if i >= to_integer(unsigned(mask_begin)) then + ret(63 - i) := '1'; + end if; + end loop; + return ret; + end; + + function left_mask(mask_end: std_ulogic_vector(6 downto 0)) return std_ulogic_vector is + variable ret: std_ulogic_vector(63 downto 0); + begin + ret := (others => '0'); + if mask_end(6) = '0' then + for i in 0 to 63 loop + if i <= to_integer(unsigned(mask_end)) then + ret(63 - i) := '1'; + end if; + end loop; + end if; + return ret; + end; + +begin + rotator_0: process(all) + begin + -- First replicate bottom 32 bits to both halves if 32-bit + if is_32bit = '1' then + repl32 <= rs(31 downto 0) & rs(31 downto 0); + else + repl32 <= rs; + end if; + + -- Negate shift count for right shifts + if right_shift = '1' then + rot_count <= std_ulogic_vector(- signed(shift(5 downto 0))); + else + rot_count <= shift(5 downto 0); + end if; + + -- Rotator works in 3 stages using 2 bits of the rotate count each + -- time. This gives 4:1 multiplexors which is ideal for the 6-input + -- LUTs in the Xilinx Artix 7. + -- We look at the low bits of the rotate count first because they will + -- have less delay through the negation above. + -- First rotate by 0, 1, 2, or 3 + case rot_count(1 downto 0) is + when "00" => + rot1 <= repl32; + when "01" => + rot1 <= repl32(62 downto 0) & repl32(63); + when "10" => + rot1 <= repl32(61 downto 0) & repl32(63 downto 62); + when others => + rot1 <= repl32(60 downto 0) & repl32(63 downto 61); + end case; + -- Next rotate by 0, 4, 8 or 12 + case rot_count(3 downto 2) is + when "00" => + rot2 <= rot1; + when "01" => + rot2 <= rot1(59 downto 0) & rot1(63 downto 60); + when "10" => + rot2 <= rot1(55 downto 0) & rot1(63 downto 56); + when others => + rot2 <= rot1(51 downto 0) & rot1(63 downto 52); + end case; + -- Lastly rotate by 0, 16, 32 or 48 + case rot_count(5 downto 4) is + when "00" => + rot <= rot2; + when "01" => + rot <= rot2(47 downto 0) & rot2(63 downto 48); + when "10" => + rot <= rot2(31 downto 0) & rot2(63 downto 32); + when others => + rot <= rot2(15 downto 0) & rot2(63 downto 16); + end case; + + -- Trim shift count to 6 bits for 32-bit shifts + sh <= (shift(6) and not is_32bit) & shift(5 downto 0); + + -- Work out mask begin/end indexes (caution, big-endian bit numbering) + if clear_left = '1' then + if is_32bit = '1' then + mb <= "01" & insn(10 downto 6); + else + mb <= "0" & insn(5) & insn(10 downto 6); + end if; + elsif right_shift = '1' then + -- this is basically mb <= sh + (is_32bit? 32: 0); + if is_32bit = '1' then + mb <= sh(5) & not sh(5) & sh(4 downto 0); + else + mb <= sh; + end if; + else + mb <= ('0' & is_32bit & "00000"); + end if; + if clear_right = '1' and is_32bit = '1' then + me <= "01" & insn(5 downto 1); + elsif clear_right = '1' and clear_left = '0' then + me <= "0" & insn(5) & insn(10 downto 6); + else + -- effectively, 63 - sh + me <= sh(6) & not sh(5 downto 0); + end if; + + -- Calculate left and right masks + mr <= right_mask(mb); + ml <= left_mask(me); + + -- Work out output mode + -- 00 for sl[wd] + -- 0w for rlw*, rldic, rldicr, rldimi, where w = 1 iff mb > me + -- 10 for rldicl, sr[wd] + -- 1z for sra[wd][i], z = 1 if rs is negative + if (clear_left = '1' and clear_right = '0') or right_shift = '1' then + output_mode(1) <= '1'; + output_mode(0) <= arith and repl32(63); + else + output_mode(1) <= '0'; + if clear_right = '1' and unsigned(mb(5 downto 0)) > unsigned(me(5 downto 0)) then + output_mode(0) <= '1'; + else + output_mode(0) <= '0'; + end if; + end if; + + -- Generate output from rotated input and masks + case output_mode is + when "00" => + result <= (rot and (mr and ml)) or (ra and not (mr and ml)); + when "01" => + result <= (rot and (mr or ml)) or (ra and not (mr or ml)); + when "10" => + result <= rot and mr; + when others => + result <= rot or not mr; + end case; + + -- Generate carry output for arithmetic shift right of negative value + if output_mode = "11" then + carry_out <= or (rs and not ml); + else + carry_out <= '0'; + end if; + end process; +end behaviour; diff --git a/rotator_tb.vhdl b/rotator_tb.vhdl new file mode 100644 index 0000000..3cb46b0 --- /dev/null +++ b/rotator_tb.vhdl @@ -0,0 +1,269 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.common.all; +use work.glibc_random.all; +use work.ppc_fx_insns.all; +use work.insn_helpers.all; + +entity rotator_tb is +end rotator_tb; + +architecture behave of rotator_tb is + constant clk_period: time := 10 ns; + signal ra, rs: std_ulogic_vector(63 downto 0); + signal shift: std_ulogic_vector(6 downto 0) := (others => '0'); + signal insn: std_ulogic_vector(31 downto 0) := (others => '0'); + signal is_32bit, right_shift, arith, clear_left, clear_right: std_ulogic := '0'; + signal result: std_ulogic_vector(63 downto 0); + signal carry_out: std_ulogic; + +begin + rotator_0: entity work.rotator + port map ( + rs => rs, + ra => ra, + shift => shift, + insn => insn, + is_32bit => is_32bit, + right_shift => right_shift, + arith => arith, + clear_left => clear_left, + clear_right => clear_right, + result => result, + carry_out => carry_out + ); + + stim_process: process + variable behave_ra: std_ulogic_vector(63 downto 0); + variable behave_ca_ra: std_ulogic_vector(64 downto 0); + begin + -- rlwinm, rlwnm + report "test rlw[i]nm"; + ra <= (others => '0'); + is_32bit <= '1'; + right_shift <= '0'; + arith <= '0'; + clear_left <= '1'; + clear_right <= '1'; + rlwnm_loop : for i in 0 to 1000 loop + rs <= pseudorand(64); + shift <= pseudorand(7); + insn <= x"00000" & '0' & pseudorand(10) & '0'; + wait for clk_period; + behave_ra := ppc_rlwinm(rs, shift(4 downto 0), insn_mb32(insn), insn_me32(insn)); + assert behave_ra = result + report "bad rlwnm expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; + + -- rlwimi + report "test rlwimi"; + is_32bit <= '1'; + right_shift <= '0'; + arith <= '0'; + clear_left <= '1'; + clear_right <= '1'; + rlwimi_loop : for i in 0 to 1000 loop + rs <= pseudorand(64); + ra <= pseudorand(64); + shift <= "00" & pseudorand(5); + insn <= x"00000" & '0' & pseudorand(10) & '0'; + wait for clk_period; + behave_ra := ppc_rlwimi(ra, rs, shift(4 downto 0), insn_mb32(insn), insn_me32(insn)); + assert behave_ra = result + report "bad rlwimi expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; + + -- rldicl, rldcl + report "test rld[i]cl"; + ra <= (others => '0'); + is_32bit <= '0'; + right_shift <= '0'; + arith <= '0'; + clear_left <= '1'; + clear_right <= '0'; + rldicl_loop : for i in 0 to 1000 loop + rs <= pseudorand(64); + shift <= pseudorand(7); + insn <= x"00000" & '0' & pseudorand(10) & '0'; + wait for clk_period; + behave_ra := ppc_rldicl(rs, shift(5 downto 0), insn_mb(insn)); + assert behave_ra = result + report "bad rldicl expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; + + -- rldicr, rldcr + report "test rld[i]cr"; + ra <= (others => '0'); + is_32bit <= '0'; + right_shift <= '0'; + arith <= '0'; + clear_left <= '0'; + clear_right <= '1'; + rldicr_loop : for i in 0 to 1000 loop + rs <= pseudorand(64); + shift <= pseudorand(7); + insn <= x"00000" & '0' & pseudorand(10) & '0'; + wait for clk_period; + behave_ra := ppc_rldicr(rs, shift(5 downto 0), insn_me(insn)); + --report "rs = " & to_hstring(rs); + --report "ra = " & to_hstring(ra); + --report "shift = " & to_hstring(shift); + --report "insn me = " & to_hstring(insn_me(insn)); + --report "result = " & to_hstring(result); + assert behave_ra = result + report "bad rldicr expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; + + -- rldic + report "test rldic"; + ra <= (others => '0'); + is_32bit <= '0'; + right_shift <= '0'; + arith <= '0'; + clear_left <= '1'; + clear_right <= '1'; + rldic_loop : for i in 0 to 1000 loop + rs <= pseudorand(64); + shift <= '0' & pseudorand(6); + insn <= x"00000" & '0' & pseudorand(10) & '0'; + wait for clk_period; + behave_ra := ppc_rldic(rs, shift(5 downto 0), insn_mb(insn)); + assert behave_ra = result + report "bad rldic expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; + + -- rldimi + report "test rldimi"; + is_32bit <= '0'; + right_shift <= '0'; + arith <= '0'; + clear_left <= '1'; + clear_right <= '1'; + rldimi_loop : for i in 0 to 1000 loop + rs <= pseudorand(64); + ra <= pseudorand(64); + shift <= '0' & pseudorand(6); + insn <= x"00000" & '0' & pseudorand(10) & '0'; + wait for clk_period; + behave_ra := ppc_rldimi(ra, rs, shift(5 downto 0), insn_mb(insn)); + assert behave_ra = result + report "bad rldimi expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; + + -- slw + report "test slw"; + ra <= (others => '0'); + is_32bit <= '1'; + right_shift <= '0'; + arith <= '0'; + clear_left <= '0'; + clear_right <= '0'; + slw_loop : for i in 0 to 1000 loop + rs <= pseudorand(64); + shift <= pseudorand(7); + wait for clk_period; + behave_ra := ppc_slw(rs, std_ulogic_vector(resize(unsigned(shift), 64))); + assert behave_ra = result + report "bad slw expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; + + -- sld + report "test sld"; + ra <= (others => '0'); + is_32bit <= '0'; + right_shift <= '0'; + arith <= '0'; + clear_left <= '0'; + clear_right <= '0'; + sld_loop : for i in 0 to 1000 loop + rs <= pseudorand(64); + shift <= pseudorand(7); + wait for clk_period; + behave_ra := ppc_sld(rs, std_ulogic_vector(resize(unsigned(shift), 64))); + assert behave_ra = result + report "bad sld expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; + + -- srw + report "test srw"; + ra <= (others => '0'); + is_32bit <= '1'; + right_shift <= '1'; + arith <= '0'; + clear_left <= '0'; + clear_right <= '0'; + srw_loop : for i in 0 to 1000 loop + rs <= pseudorand(64); + shift <= pseudorand(7); + wait for clk_period; + behave_ra := ppc_srw(rs, std_ulogic_vector(resize(unsigned(shift), 64))); + assert behave_ra = result + report "bad srw expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; + + -- srd + report "test srd"; + ra <= (others => '0'); + is_32bit <= '0'; + right_shift <= '1'; + arith <= '0'; + clear_left <= '0'; + clear_right <= '0'; + srd_loop : for i in 0 to 1000 loop + rs <= pseudorand(64); + shift <= pseudorand(7); + wait for clk_period; + behave_ra := ppc_srd(rs, std_ulogic_vector(resize(unsigned(shift), 64))); + assert behave_ra = result + report "bad srd expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; + + -- sraw[i] + report "test sraw[i]"; + ra <= (others => '0'); + is_32bit <= '1'; + right_shift <= '1'; + arith <= '1'; + clear_left <= '0'; + clear_right <= '0'; + sraw_loop : for i in 0 to 1000 loop + rs <= pseudorand(64); + shift <= '0' & pseudorand(6); + wait for clk_period; + behave_ca_ra := ppc_sraw(rs, std_ulogic_vector(resize(unsigned(shift), 64))); + --report "rs = " & to_hstring(rs); + --report "ra = " & to_hstring(ra); + --report "shift = " & to_hstring(shift); + --report "result = " & to_hstring(carry_out & result); + assert behave_ca_ra(63 downto 0) = result and behave_ca_ra(64) = carry_out + report "bad sraw expected " & to_hstring(behave_ca_ra) & " got " & to_hstring(carry_out & result); + end loop; + + -- srad[i] + report "test srad[i]"; + ra <= (others => '0'); + is_32bit <= '0'; + right_shift <= '1'; + arith <= '1'; + clear_left <= '0'; + clear_right <= '0'; + srad_loop : for i in 0 to 1000 loop + rs <= pseudorand(64); + shift <= pseudorand(7); + wait for clk_period; + behave_ca_ra := ppc_srad(rs, std_ulogic_vector(resize(unsigned(shift), 64))); + --report "rs = " & to_hstring(rs); + --report "ra = " & to_hstring(ra); + --report "shift = " & to_hstring(shift); + --report "result = " & to_hstring(carry_out & result); + assert behave_ca_ra(63 downto 0) = result and behave_ca_ra(64) = carry_out + report "bad srad expected " & to_hstring(behave_ca_ra) & " got " & to_hstring(carry_out & result); + end loop; + + assert false report "end of test" severity failure; + wait; + end process; +end behave;