


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








subtype twobit is unsigned(1 downto 0);




type twobit32 is array(0 to 31) of twobit;




signal pc2 : twobit32;




subtype threebit is unsigned(2 downto 0);




type threebit16 is array(0 to 15) of threebit;




signal pc4 : threebit16;




subtype fourbit is unsigned(3 downto 0);




type fourbit8 is array(0 to 7) of fourbit;




signal pc8 : fourbit8;




subtype sixbit is unsigned(5 downto 0);




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








begin




logical_0: process(all)




variable rb_adj, tmp : std_ulogic_vector(63 downto 0);




variable negative : std_ulogic;




begin




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




end loop;




for i in 0 to 15 loop




pc4(i) <= ('0' & pc2(i * 2)) + ('0' & pc2(i * 2 + 1));




end loop;




for i in 0 to 7 loop




pc8(i) <= ('0' & pc4(i * 2)) + ('0' & pc4(i * 2 + 1));




end loop;




for i in 0 to 1 loop




pc32(i) <= ("00" & pc8(i * 4)) + ("00" & pc8(i * 4 + 1)) +




("00" & pc8(i * 4 + 2)) + ("00" & pc8(i * 4 + 3));




end loop;




popcnt <= (others => '0');




if datalen(3 downto 2) = "00" then




 popcntb




for i in 0 to 7 loop




popcnt(i * 8 + 3 downto i * 8) <= std_ulogic_vector(pc8(i));




end loop;




elsif datalen(3) = '0' then




 popcntw




for i in 0 to 1 loop




popcnt(i * 32 + 5 downto i * 32) <= std_ulogic_vector(pc32(i));




end loop;




else




popcnt(6 downto 0) <= std_ulogic_vector(('0' & pc32(0)) + ('0' & pc32(1)));




end if;








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




tmp := rs and rb_adj;




when OP_OR =>




tmp := rs or rb_adj;




when OP_XOR =>




tmp := rs xor rb_adj;




when OP_POPCNT =>




tmp := popcnt;




when OP_PRTY =>




tmp := parity;




when OP_CMPB =>




tmp := ppc_cmpb(rs, rb);




when others =>




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




end case;








if invert_out = '1' then




tmp := not tmp;




end if;




result <= tmp;








end process;




end behaviour;
