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 minor_valid_array_2t is array(0 to 2047) of std_ulogic;
+ type op_4_subop_array_t is array(0 to 63) of decode_rom_t;
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;
others => illegal_inst
);
+ -- indexed by bits 5..0 and 10..6 of instruction word
+ constant decode_op_4_valid : minor_valid_array_2t := (
+ 2#11000000000# to 2#11000011111# => '1', -- maddhd
+ 2#11000100000# to 2#11000111111# => '1', -- maddhdu
+ 2#11001100000# to 2#11001111111# => '1', -- maddld
+ others => '0'
+ );
+
+ -- indexed by bits 5..0 of instruction word
+ constant decode_op_4_array : op_4_subop_array_t := (
+ -- unit internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl
+ -- op in out A out in out len ext pipe
+ 2#110000# => (ALU, OP_MUL_H64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0'), -- maddhd
+ 2#110001# => (ALU, OP_MUL_H64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- maddhdu
+ 2#110011# => (ALU, OP_MUL_L64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0'), -- maddld
+ others => decode_rom_init
+ );
+
-- indexed by bits 10..1 of instruction word
constant decode_op_19_valid : minor_valid_array_t := (
-- addpcis, 5 upper bits are part of constant
variable v : Decode1ToDecode2Type;
variable f : Decode1ToFetch1Type;
variable majorop : major_opcode_t;
+ variable minor4op : std_ulogic_vector(10 downto 0);
variable op_19_bits: std_ulogic_vector(2 downto 0);
variable sprn : spr_num_t;
variable br_nia : std_ulogic_vector(61 downto 0);
end if;
v.decode := fetch_fail_inst;
+ elsif majorop = "000100" then
+ -- major opcode 4, mostly VMX/VSX stuff but also some integer ops (madd*)
+ minor4op := f_in.insn(5 downto 0) & f_in.insn(10 downto 6);
+ if decode_op_4_valid(to_integer(unsigned(minor4op))) = '1' then
+ v.decode := decode_op_4_array(to_integer(unsigned(f_in.insn(5 downto 0))));
+ else
+ v.decode := illegal_inst;
+ end if;
+
elsif majorop = "011111" then
-- major opcode 31, lots of things
v.decode := decode_op_31_array(to_integer(unsigned(f_in.insn(10 downto 1))));
case t is
when RS =>
return ('1', gpr_to_gspr(insn_rs(insn_in)), reg_data);
+ when RCR =>
+ return ('1', gpr_to_gspr(insn_rcreg(insn_in)), reg_data);
when NONE =>
return ('0', (others => '0'), (others => '0'));
end case;
else gpr_to_gspr(insn_ra(d_in.insn));
r_out.read2_reg <= d_in.ispr2 when d_in.decode.input_reg_b = SPR
else gpr_to_gspr(insn_rb(d_in.insn));
- r_out.read3_reg <= insn_rs(d_in.insn);
+ r_out.read3_reg <= insn_rcreg(d_in.insn) when d_in.decode.input_reg_c = RCR
+ else insn_rs(d_in.insn);
c_out.read <= d_in.decode.input_cr;
OP_DARN, OP_DCBF, OP_DCBST, OP_DCBT, OP_DCBTST,
OP_DCBZ, OP_DIV, OP_DIVE, OP_EXTS,
OP_EXTSWSLI, OP_ICBI, OP_ICBT, OP_ISEL, OP_ISYNC,
- OP_LOAD, OP_STORE, OP_MADDHD, OP_MADDHDU, OP_MADDLD,
+ OP_LOAD, OP_STORE,
OP_MCRXRX, OP_MFCR, OP_MFMSR, OP_MFSPR, OP_MOD,
OP_MTCRF, OP_MTMSRD, OP_MTSPR, OP_MUL_L64,
OP_MUL_H64, OP_MUL_H32, OP_OR,
type input_reg_a_t is (NONE, RA, RA_OR_ZERO, SPR, CIA);
type input_reg_b_t is (NONE, RB, CONST_UI, CONST_SI, CONST_SI_HI, CONST_UI_HI, CONST_LI, CONST_BD,
CONST_DXHI4, CONST_DS, CONST_M1, CONST_SH, CONST_SH32, SPR);
- type input_reg_c_t is (NONE, RS);
+ type input_reg_c_t is (NONE, RS, RCR);
type output_reg_a_t is (NONE, RT, RA, SPR);
type rc_t is (NONE, ONE, RC);
type carry_in_t is (ZERO, CA, ONE);
variable taken_branch : std_ulogic;
variable abs_branch : std_ulogic;
variable spr_val : std_ulogic_vector(63 downto 0);
+ variable addend : std_ulogic_vector(127 downto 0);
begin
result := (others => '0');
result_with_carry := (others => '0');
x_to_divider.is_modulus <= '1';
end if;
+ addend := (others => '0');
+ if e_in.insn(26) = '0' then
+ -- integer multiply-add, major op 4 (if it is a multiply)
+ addend(63 downto 0) := c_in;
+ if e_in.is_signed = '1' then
+ addend(127 downto 64) := (others => c_in(63));
+ end if;
+ end if;
+ if (sign1 xor sign2) = '1' then
+ addend := not addend;
+ end if;
+
x_to_multiply.not_result <= sign1 xor sign2;
- x_to_multiply.addend <= (others => sign1 xor sign2);
+ x_to_multiply.addend <= addend;
x_to_divider.neg_result <= sign1 xor (sign2 and not x_to_divider.is_modulus);
if e_in.is_32bit = '0' then
-- 64-bit forms
function insn_rt (insn_in : std_ulogic_vector) return std_ulogic_vector;
function insn_ra (insn_in : std_ulogic_vector) return std_ulogic_vector;
function insn_rb (insn_in : std_ulogic_vector) return std_ulogic_vector;
+ function insn_rcreg (insn_in : std_ulogic_vector) return std_ulogic_vector;
function insn_si (insn_in : std_ulogic_vector) return std_ulogic_vector;
function insn_ui (insn_in : std_ulogic_vector) return std_ulogic_vector;
function insn_l (insn_in : std_ulogic_vector) return std_ulogic;
return insn_in(15 downto 11);
end;
+ function insn_rcreg (insn_in : std_ulogic_vector) return std_ulogic_vector is
+ begin
+ return insn_in(10 downto 6);
+ end;
+
function insn_si (insn_in : std_ulogic_vector) return std_ulogic_vector is
begin
return insn_in(15 downto 0);
"illegal", "nop ", "add ", "and ", "attn ", "b ", "bc ", "bcreg ",
"bperm ", "cmp ", "cmpb ", "cmpeqb ", "cmprb ", "cntz ", "crop ", "darn ",
"dcbf ", "dcbst ", "dcbt ", "dcbtst ", "dcbz ", "div ", "dive ", "exts ",
- "extswsl", "icbi ", "icbt ", "isel ", "isync ", "ld ", "st ", "maddhd ",
- "maddhdu", "maddld ", "mcrxrx ", "mfcr ", "mfmsr ", "mfspr ", "mod ", "mtcrf ",
- "mtmsr ", "mtspr ", "mull64 ", "mulh64 ", "mulh32 ", "or ", "popcnt ", "prty ",
- "rfid ", "rlc ", "rlcl ", "rlcr ", "sc ", "setb ", "shl ", "shr ",
- "sync ", "tlbie ", "trap ", "xor ", "ffail ", "?61 ", "?62 ", "?63 "
+ "extswsl", "icbi ", "icbt ", "isel ", "isync ", "ld ", "st ", "mcrxrx ",
+ "mfcr ", "mfmsr ", "mfspr ", "mod ", "mtcrf ", "mtmsr ", "mtspr ", "mull64 ",
+ "mulh64 ", "mulh32 ", "or ", "popcnt ", "prty ", "rfid ", "rlc ", "rlcl ",
+ "rlcr ", "sc ", "setb ", "shl ", "shr ", "sync ", "tlbie ", "trap ",
+ "xor ", "ffail ", "?58 ", "?59 ", "?60 ", "?61 ", "?62 ", "?63 "
};
const char *spr_names[13] =