


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;




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);




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, 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;








 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_LOGIC =>




 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 OP_XOR =>




tmp := rs xor rb;




if invert_out = '1' then




tmp := not tmp;




end if;








when OP_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 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 1hot 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;
