1
0
mirror of https://github.com/antonblanchard/microwatt.git synced 2026-01-11 23:43:15 +00:00
Paul Mackerras fdb3ef6874 Finish off taking SPRs out of register file
With this, the register file now contains 64 entries, for 32 GPRs and
32 FPRs, rather than the 128 it had previously.  Several things get
simplified - decode1 no longer has to work out the ispr{1,2,o} values,
decode_input_reg_{a,b,c} no longer have the t = SPR case, etc.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2022-07-22 22:20:39 +10:00

178 lines
6.2 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 insn_type_t;
invert_in : in std_ulogic;
invert_out : 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);
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);
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;
-- bit permutation
for i in 0 to 7 loop
j := i * 8;
if rs(j+7 downto j+6) = "00" then
permute(i) <= rb(to_integer(unsigned(not rs(j+5 downto j))));
else
permute(i) <= '0';
end if;
end loop;
rb_adj := rb;
if invert_in = '1' then
rb_adj := not rb;
end if;
case op is
when OP_AND | OP_OR | OP_XOR =>
case op is
when OP_AND =>
tmp := rs and rb_adj;
when OP_OR =>
tmp := rs or rb_adj;
when others =>
tmp := rs xor rb_adj;
end case;
if invert_out = '1' then
tmp := not tmp;
end if;
when OP_PRTY =>
tmp := parity;
when OP_CMPB =>
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 OP_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 =>
-- e.g. OP_MFSPR
tmp := rs;
end case;
result <= tmp;
end process;
end behaviour;