1
0
mirror of https://github.com/antonblanchard/microwatt.git synced 2026-01-11 23:43:15 +00:00
Paul Mackerras ca872faede core: Consolidate several OP_* values into a single OP_COMPUTE
This replaces OP_ADDG6S, OP_BCD, OP_BREV, OP_CMPB, OP_CMPEQB,
OP_CMPRB, OP_CROP, OP_EXTS, OP_EXTSWSLI, OP_ISEL, OP_LOGIC, OP_MFCR,
OP_PRTY, OP_RLC, OP_RLCL, OP_RLCR, OP_SETB, OP_SHL, OP_SHR,
and OP_XOR with a single OP_COMPUTE.  The replaced operations are all
ones which just compute a result value (for GPR or CR) in execute1,
don't have any other side effects, and aren't used in decode2 to
determine other signals.  The operation to be performed is
sufficiently defined by the result and subresult fields in the decode
table.  With the elimination of OP_SPARE, this reduces the number of
insn_type_t values to 44.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2025-08-09 12:13:41 +10:00

176 lines
6.6 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.decode_types.all;
use work.ppc_fx_insns.all;
entity logical is
port (
rs : in std_ulogic_vector(63 downto 0);
rb : in std_ulogic_vector(63 downto 0);
op : in subresult_sel_t;
invert_in : in std_ulogic;
invert_out : in std_ulogic;
is_signed : in std_ulogic;
result : out std_ulogic_vector(63 downto 0);
datalen : in std_logic_vector(3 downto 0)
);
end entity logical;
architecture behaviour of logical is
signal par0, par1 : std_ulogic;
signal parity : std_ulogic_vector(63 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, rs_adj : std_ulogic_vector(63 downto 0);
variable tmp : std_ulogic_vector(63 downto 0);
variable negative : std_ulogic;
variable j : integer;
begin
-- parity calculations
par0 <= rs(0) xor rs(8) xor rs(16) xor rs(24);
par1 <= rs(32) xor rs(40) xor rs(48) xor rs(56);
parity <= (others => '0');
if datalen(3) = '1' then
parity(0) <= par0 xor par1;
else
parity(0) <= par0;
parity(32) <= par1;
end if;
rb_adj := rb;
if invert_in = '1' then
rb_adj := not rb;
end if;
case op is
when "000" => -- and, or, etc.
-- for now, abuse the 'is_signed' field to indicate inversion of RS
rs_adj := rs;
if is_signed = '1' then
rs_adj := not rs;
end if;
tmp := rs_adj and rb_adj;
if invert_out = '1' then
tmp := not tmp;
end if;
when "001" => -- xor, eqv
tmp := rs xor rb;
if invert_out = '1' then
tmp := not tmp;
end if;
when "010" => -- brev
if datalen(3) = '1' then
tmp := rs( 7 downto 0) & rs(15 downto 8) & rs(23 downto 16) & rs(31 downto 24) &
rs(39 downto 32) & rs(47 downto 40) & rs(55 downto 48) & rs(63 downto 56);
elsif datalen(2) = '1' then
tmp := rs(39 downto 32) & rs(47 downto 40) & rs(55 downto 48) & rs(63 downto 56) &
rs( 7 downto 0) & rs(15 downto 8) & rs(23 downto 16) & rs(31 downto 24);
else
tmp := rs(55 downto 48) & rs(63 downto 56) & rs(39 downto 32) & rs(47 downto 40) &
rs(23 downto 16) & rs(31 downto 24) & rs( 7 downto 0) & rs(15 downto 8);
end if;
when "011" => -- prty*
tmp := parity;
when "100" => -- cmpb
tmp := ppc_cmpb(rs, rb);
when "101" => -- 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));
when "110" => -- 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));
when "111" => -- exts*
-- note datalen is a 1-hot encoding
negative := (datalen(0) and rs(7)) or
(datalen(1) and rs(15)) or
(datalen(2) and rs(31));
tmp := (others => negative);
if datalen(2) = '1' then
tmp(31 downto 16) := rs(31 downto 16);
end if;
if datalen(2) = '1' or datalen(1) = '1' then
tmp(15 downto 8) := rs(15 downto 8);
end if;
tmp(7 downto 0) := rs(7 downto 0);
when others =>
tmp := (others => '0');
end case;
result <= tmp;
end process;
end behaviour;