library work;
use work.decode_types.all;
+use work.ppc_fx_insns.all;
entity logical is
port (
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);
- popcnt : out std_ulogic_vector(63 downto 0);
- parity : out std_ulogic_vector(63 downto 0)
+ datalen : in std_logic_vector(3 downto 0)
);
end entity logical;
type sixbit2 is array(0 to 1) of sixbit;
signal pc32 : sixbit2;
signal par0, par1 : std_ulogic;
+ signal popcnt : std_ulogic_vector(63 downto 0);
+ 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
- rb_adj := rb;
- if invert_in = '1' then
- rb_adj := not rb;
- end if;
-
- 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;
-
- result <= tmp;
- if invert_out = '1' then
- result <= not tmp;
- end if;
-
-- population counts
for i in 0 to 31 loop
pc2(i) <= unsigned("0" & rs(i * 2 downto i * 2)) + unsigned("0" & rs(i * 2 + 1 downto i * 2 + 1));
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(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_POPCNT =>
+ tmp := popcnt;
+ 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_MTSPR
+ tmp := rs;
+ end case;
+
+ result <= tmp;
+
end process;
end behaviour;