mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-03-06 11:03:25 +00:00
core: Implement BCD Assist instructions addg6s, cdtbcd, cbcdtod
To avoid adding too much logic, this moves the adder used by OP_ADD out of the case statement in execute1.vhdl so that the result can be used by OP_ADDG6S as well. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
@@ -173,6 +173,7 @@ architecture behaviour of decode1 is
|
||||
2#0010001010# => (ALU, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- adde
|
||||
2#1010001010# => (ALU, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- addeo
|
||||
2#0010101010# => (ALU, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', OV, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- addex
|
||||
2#0001001010# => (ALU, OP_ADDG6S, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- addg6s
|
||||
2#0011101010# => (ALU, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- addme
|
||||
2#1011101010# => (ALU, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- addmeo
|
||||
2#0011001010# => (ALU, OP_ADD, RA, NONE, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- addze
|
||||
@@ -180,6 +181,8 @@ architecture behaviour of decode1 is
|
||||
2#0000011100# => (ALU, OP_AND, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- and
|
||||
2#0000111100# => (ALU, OP_AND, NONE, RB, RS, RA, '0', '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- andc
|
||||
2#0011111100# => (ALU, OP_BPERM, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- bperm
|
||||
2#0100111010# => (ALU, OP_BCD, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- cbcdtd
|
||||
2#0100011010# => (ALU, OP_BCD, NONE, NONE, RS, RA, '0', '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- cdtbcd
|
||||
2#0000000000# => (ALU, OP_CMP, RA, RB, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0'), -- cmp
|
||||
2#0111111100# => (ALU, OP_CMPB, NONE, RB, RS, RA, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- cmpb
|
||||
2#0011100000# => (ALU, OP_CMPEQB, RA, RB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- cmpeqb
|
||||
|
||||
@@ -18,6 +18,7 @@ package decode_types is
|
||||
OP_SHL, OP_SHR,
|
||||
OP_SYNC, OP_TLBIE, OP_TRAP,
|
||||
OP_XOR,
|
||||
OP_BCD, OP_ADDG6S,
|
||||
OP_FETCH_FAILED
|
||||
);
|
||||
type input_reg_a_t is (NONE, RA, RA_OR_ZERO, SPR, CIA);
|
||||
|
||||
@@ -295,7 +295,7 @@ begin
|
||||
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 sum_with_carry : std_ulogic_vector(64 downto 0);
|
||||
variable result_en : std_ulogic;
|
||||
variable crnum : crnum_t;
|
||||
variable crbit : integer range 0 to 31;
|
||||
@@ -332,7 +332,7 @@ begin
|
||||
variable addend : std_ulogic_vector(127 downto 0);
|
||||
begin
|
||||
result := (others => '0');
|
||||
result_with_carry := (others => '0');
|
||||
sum_with_carry := (others => '0');
|
||||
result_en := '0';
|
||||
newcrf := (others => '0');
|
||||
is_branch := '0';
|
||||
@@ -395,6 +395,15 @@ begin
|
||||
v.cntz_in_progress := '0';
|
||||
v.mul_finish := '0';
|
||||
|
||||
-- Main adder
|
||||
if e_in.invert_a = '0' then
|
||||
a_inv := a_in;
|
||||
else
|
||||
a_inv := not a_in;
|
||||
end if;
|
||||
sum_with_carry := ppc_adde(a_inv, b_in,
|
||||
decode_input_carry(e_in.input_carry, v.e.xerc));
|
||||
|
||||
-- signals to multiply and divide units
|
||||
sign1 := '0';
|
||||
sign2 := '0';
|
||||
@@ -584,16 +593,9 @@ begin
|
||||
when OP_NOP =>
|
||||
-- Do nothing
|
||||
when OP_ADD | OP_CMP | OP_TRAP =>
|
||||
if e_in.invert_a = '0' then
|
||||
a_inv := a_in;
|
||||
else
|
||||
a_inv := not a_in;
|
||||
end if;
|
||||
result_with_carry := ppc_adde(a_inv, b_in,
|
||||
decode_input_carry(e_in.input_carry, v.e.xerc));
|
||||
result := result_with_carry(63 downto 0);
|
||||
result := sum_with_carry(63 downto 0);
|
||||
carry_32 := result(32) xor a_inv(32) xor b_in(32);
|
||||
carry_64 := result_with_carry(64);
|
||||
carry_64 := sum_with_carry(64);
|
||||
if e_in.insn_type = OP_ADD then
|
||||
if e_in.output_carry = '1' then
|
||||
if e_in.input_carry /= OV then
|
||||
@@ -606,8 +608,8 @@ begin
|
||||
end if;
|
||||
if e_in.oe = '1' then
|
||||
set_ov(v.e,
|
||||
calc_ov(a_inv(63), b_in(63), carry_64, result_with_carry(63)),
|
||||
calc_ov(a_inv(31), b_in(31), carry_32, result_with_carry(31)));
|
||||
calc_ov(a_inv(63), b_in(63), carry_64, sum_with_carry(63)),
|
||||
calc_ov(a_inv(31), b_in(31), carry_32, sum_with_carry(31)));
|
||||
end if;
|
||||
result_en := '1';
|
||||
else
|
||||
@@ -672,6 +674,19 @@ begin
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
when OP_ADDG6S =>
|
||||
result := (others => '0');
|
||||
for i in 0 to 14 loop
|
||||
lo := i * 4;
|
||||
hi := (i + 1) * 4;
|
||||
if (a_in(hi) xor b_in(hi) xor sum_with_carry(hi)) = '0' then
|
||||
result(lo + 3 downto lo) := "0110";
|
||||
end if;
|
||||
end loop;
|
||||
if sum_with_carry(64) = '0' then
|
||||
result(63 downto 60) := "0110";
|
||||
end if;
|
||||
result_en := '1';
|
||||
when OP_CMPRB =>
|
||||
newcrf := ppc_cmprb(a_in, b_in, insn_l(e_in.insn));
|
||||
bf := insn_bf(e_in.insn);
|
||||
@@ -688,7 +703,8 @@ begin
|
||||
v.e.write_cr_mask := num_to_fxm(crnum);
|
||||
v.e.write_cr_data := newcrf & newcrf & newcrf & newcrf &
|
||||
newcrf & newcrf & newcrf & newcrf;
|
||||
when OP_AND | OP_OR | OP_XOR | OP_POPCNT | OP_PRTY | OP_CMPB | OP_EXTS | OP_BPERM =>
|
||||
when OP_AND | OP_OR | OP_XOR | OP_POPCNT | OP_PRTY | OP_CMPB | OP_EXTS |
|
||||
OP_BPERM | OP_BCD =>
|
||||
result := logical_result;
|
||||
result_en := '1';
|
||||
when OP_B =>
|
||||
|
||||
77
logical.vhdl
77
logical.vhdl
@@ -37,6 +37,72 @@ architecture behaviour of logical is
|
||||
signal parity : std_ulogic_vector(63 downto 0);
|
||||
signal permute : std_ulogic_vector(7 downto 0);
|
||||
|
||||
function bcd_to_dpd(bcd: std_ulogic_vector(11 downto 0)) return std_ulogic_vector is
|
||||
variable dpd: std_ulogic_vector(9 downto 0);
|
||||
variable a, b, c, d, e, f, g, h, i, j, k, m: std_ulogic;
|
||||
begin
|
||||
-- The following equations are copied from PowerISA v3.0B Book 1 appendix B
|
||||
a := bcd(11);
|
||||
b := bcd(10);
|
||||
c := bcd(9);
|
||||
d := bcd(8);
|
||||
e := bcd(7);
|
||||
f := bcd(6);
|
||||
g := bcd(5);
|
||||
h := bcd(4);
|
||||
i := bcd(3);
|
||||
j := bcd(2);
|
||||
k := bcd(1);
|
||||
m := bcd(0);
|
||||
dpd(9) := (f and a and i and not e) or (j and a and not i) or (b and not a);
|
||||
dpd(8) := (g and a and i and not e) or (k and a and not i) or (c and not a);
|
||||
dpd(7) := d;
|
||||
dpd(6) := (j and not a and e and not i) or (f and not i and not e) or
|
||||
(f and not a and not e) or (e and i);
|
||||
dpd(5) := (k and not a and e and not i) or (g and not i and not e) or
|
||||
(g and not a and not e) or (a and i);
|
||||
dpd(4) := h;
|
||||
dpd(3) := a or e or i;
|
||||
dpd(2) := (not e and j and not i) or (e and i) or a;
|
||||
dpd(1) := (not a and k and not i) or (a and i) or e;
|
||||
dpd(0) := m;
|
||||
return dpd;
|
||||
end;
|
||||
|
||||
function dpd_to_bcd(dpd: std_ulogic_vector(9 downto 0)) return std_ulogic_vector is
|
||||
variable bcd: std_ulogic_vector(11 downto 0);
|
||||
variable p, q, r, s, t, u, v, w, x, y: std_ulogic;
|
||||
begin
|
||||
-- The following equations are copied from PowerISA v3.0B Book 1 appendix B
|
||||
p := dpd(9);
|
||||
q := dpd(8);
|
||||
r := dpd(7);
|
||||
s := dpd(6);
|
||||
t := dpd(5);
|
||||
u := dpd(4);
|
||||
v := dpd(3);
|
||||
w := dpd(2);
|
||||
x := dpd(1);
|
||||
y := dpd(0);
|
||||
bcd(11) := (not s and v and w) or (t and v and w and s) or (v and w and not x);
|
||||
bcd(10) := (p and s and x and not t) or (p and not w) or (p and not v);
|
||||
bcd(9) := (q and s and x and not t) or (q and not w) or (q and not v);
|
||||
bcd(8) := r;
|
||||
bcd(7) := (v and not w and x) or (s and v and w and x) or (not t and v and w and x);
|
||||
bcd(6) := (p and t and v and w and x and not s) or (s and not x and v) or
|
||||
(s and not v);
|
||||
bcd(5) := (q and t and w and v and x and not s) or (t and not x and v) or
|
||||
(t and not v);
|
||||
bcd(4) := u;
|
||||
bcd(3) := (t and v and w and x) or (s and v and w and x) or (v and not w and not x);
|
||||
bcd(2) := (p and not s and not t and w and v) or (s and v and not w and x) or
|
||||
(p and w and not x and v) or (w and not v);
|
||||
bcd(1) := (q and not s and not t and v and w) or (t and v and not w and x) or
|
||||
(q and v and w and not x) or (x and not v);
|
||||
bcd(0) := y;
|
||||
return bcd;
|
||||
end;
|
||||
|
||||
begin
|
||||
logical_0: process(all)
|
||||
variable rb_adj, tmp : std_ulogic_vector(63 downto 0);
|
||||
@@ -120,6 +186,17 @@ begin
|
||||
tmp := ppc_cmpb(rs, rb);
|
||||
when OP_BPERM =>
|
||||
tmp := std_ulogic_vector(resize(unsigned(permute), 64));
|
||||
when OP_BCD =>
|
||||
-- invert_in is abused to indicate direction of conversion
|
||||
if invert_in = '0' then
|
||||
-- cbcdtd
|
||||
tmp := x"000" & bcd_to_dpd(rs(55 downto 44)) & bcd_to_dpd(rs(43 downto 32)) &
|
||||
x"000" & bcd_to_dpd(rs(23 downto 12)) & bcd_to_dpd(rs(11 downto 0));
|
||||
else
|
||||
-- cdtbcd
|
||||
tmp := x"00" & dpd_to_bcd(rs(51 downto 42)) & dpd_to_bcd(rs(41 downto 32)) &
|
||||
x"00" & dpd_to_bcd(rs(19 downto 10)) & dpd_to_bcd(rs(9 downto 0));
|
||||
end if;
|
||||
when others =>
|
||||
-- EXTS
|
||||
-- note datalen is a 1-hot encoding
|
||||
|
||||
@@ -94,7 +94,7 @@ const char *ops[64] =
|
||||
"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 "
|
||||
"xor ", "bcd ", "addg6s ", "ffail ", "?60 ", "?61 ", "?62 ", "?63 "
|
||||
};
|
||||
|
||||
const char *spr_names[13] =
|
||||
|
||||
Reference in New Issue
Block a user