mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-11 23:43:15 +00:00
core: Implement the maddhd, maddhdu and maddld instructions
These instructions use major opcode 4 and have a third GPR input operand, so we need a decode table for major opcode 4 and some plumbing to get the RC register operand read. The multiply-add instructions use the same insn_type_t values as the regular multiply instructions, and we distinguish in execute1 by looking at the major opcode. This turns out to be convenient because we don't have to add any cases in the code that handles the output of the multiplier, and it frees up some insn_type_t values. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
parent
8edfbf638b
commit
290b05f97d
30
decode1.vhdl
30
decode1.vhdl
@ -34,6 +34,8 @@ architecture behaviour of decode1 is
|
||||
subtype major_opcode_t is unsigned(5 downto 0);
|
||||
type major_rom_array_t is array(0 to 63) of decode_rom_t;
|
||||
type minor_valid_array_t is array(0 to 1023) of std_ulogic;
|
||||
type 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;
|
||||
@ -85,6 +87,24 @@ architecture behaviour of decode1 is
|
||||
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
|
||||
@ -390,6 +410,7 @@ begin
|
||||
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);
|
||||
@ -418,6 +439,15 @@ begin
|
||||
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))));
|
||||
|
||||
@ -135,6 +135,8 @@ architecture behaviour of decode2 is
|
||||
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;
|
||||
@ -282,7 +284,8 @@ begin
|
||||
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;
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ package decode_types is
|
||||
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,
|
||||
@ -23,7 +23,7 @@ package decode_types is
|
||||
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);
|
||||
|
||||
@ -309,6 +309,7 @@ begin
|
||||
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');
|
||||
@ -408,8 +409,20 @@ begin
|
||||
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
|
||||
|
||||
@ -6,6 +6,7 @@ package insn_helpers is
|
||||
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;
|
||||
@ -59,6 +60,11 @@ package body insn_helpers is
|
||||
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);
|
||||
|
||||
@ -90,11 +90,11 @@ const char *ops[64] =
|
||||
"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] =
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user