core: Implement the bpermd instruction
[microwatt.git] / logical.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4
5 library work;
6 use work.decode_types.all;
7 use work.ppc_fx_insns.all;
8
9 entity logical is
10 port (
11 rs : in std_ulogic_vector(63 downto 0);
12 rb : in std_ulogic_vector(63 downto 0);
13 op : in insn_type_t;
14 invert_in : in std_ulogic;
15 invert_out : in std_ulogic;
16 result : out std_ulogic_vector(63 downto 0);
17 datalen : in std_logic_vector(3 downto 0)
18 );
19 end entity logical;
20
21 architecture behaviour of logical is
22
23 subtype twobit is unsigned(1 downto 0);
24 type twobit32 is array(0 to 31) of twobit;
25 signal pc2 : twobit32;
26 subtype threebit is unsigned(2 downto 0);
27 type threebit16 is array(0 to 15) of threebit;
28 signal pc4 : threebit16;
29 subtype fourbit is unsigned(3 downto 0);
30 type fourbit8 is array(0 to 7) of fourbit;
31 signal pc8 : fourbit8;
32 subtype sixbit is unsigned(5 downto 0);
33 type sixbit2 is array(0 to 1) of sixbit;
34 signal pc32 : sixbit2;
35 signal par0, par1 : std_ulogic;
36 signal popcnt : std_ulogic_vector(63 downto 0);
37 signal parity : std_ulogic_vector(63 downto 0);
38 signal permute : std_ulogic_vector(7 downto 0);
39
40 begin
41 logical_0: process(all)
42 variable rb_adj, tmp : std_ulogic_vector(63 downto 0);
43 variable negative : std_ulogic;
44 variable j : integer;
45 begin
46 -- population counts
47 for i in 0 to 31 loop
48 pc2(i) <= unsigned("0" & rs(i * 2 downto i * 2)) + unsigned("0" & rs(i * 2 + 1 downto i * 2 + 1));
49 end loop;
50 for i in 0 to 15 loop
51 pc4(i) <= ('0' & pc2(i * 2)) + ('0' & pc2(i * 2 + 1));
52 end loop;
53 for i in 0 to 7 loop
54 pc8(i) <= ('0' & pc4(i * 2)) + ('0' & pc4(i * 2 + 1));
55 end loop;
56 for i in 0 to 1 loop
57 pc32(i) <= ("00" & pc8(i * 4)) + ("00" & pc8(i * 4 + 1)) +
58 ("00" & pc8(i * 4 + 2)) + ("00" & pc8(i * 4 + 3));
59 end loop;
60 popcnt <= (others => '0');
61 if datalen(3 downto 2) = "00" then
62 -- popcntb
63 for i in 0 to 7 loop
64 popcnt(i * 8 + 3 downto i * 8) <= std_ulogic_vector(pc8(i));
65 end loop;
66 elsif datalen(3) = '0' then
67 -- popcntw
68 for i in 0 to 1 loop
69 popcnt(i * 32 + 5 downto i * 32) <= std_ulogic_vector(pc32(i));
70 end loop;
71 else
72 popcnt(6 downto 0) <= std_ulogic_vector(('0' & pc32(0)) + ('0' & pc32(1)));
73 end if;
74
75 -- parity calculations
76 par0 <= rs(0) xor rs(8) xor rs(16) xor rs(24);
77 par1 <= rs(32) xor rs(40) xor rs(48) xor rs(56);
78 parity <= (others => '0');
79 if datalen(3) = '1' then
80 parity(0) <= par0 xor par1;
81 else
82 parity(0) <= par0;
83 parity(32) <= par1;
84 end if;
85
86 -- bit permutation
87 for i in 0 to 7 loop
88 j := i * 8;
89 if rs(j+7 downto j+6) = "00" then
90 permute(i) <= rb(to_integer(unsigned(rs(j+5 downto j))));
91 else
92 permute(i) <= '0';
93 end if;
94 end loop;
95
96 rb_adj := rb;
97 if invert_in = '1' then
98 rb_adj := not rb;
99 end if;
100
101 case op is
102 when OP_AND | OP_OR | OP_XOR =>
103 case op is
104 when OP_AND =>
105 tmp := rs and rb_adj;
106 when OP_OR =>
107 tmp := rs or rb_adj;
108 when others =>
109 tmp := rs xor rb_adj;
110 end case;
111 if invert_out = '1' then
112 tmp := not tmp;
113 end if;
114
115 when OP_POPCNT =>
116 tmp := popcnt;
117 when OP_PRTY =>
118 tmp := parity;
119 when OP_CMPB =>
120 tmp := ppc_cmpb(rs, rb);
121 when OP_BPERM =>
122 tmp := std_ulogic_vector(resize(unsigned(permute), 64));
123 when others =>
124 -- EXTS
125 -- note datalen is a 1-hot encoding
126 negative := (datalen(0) and rs(7)) or
127 (datalen(1) and rs(15)) or
128 (datalen(2) and rs(31));
129 tmp := (others => negative);
130 if datalen(2) = '1' then
131 tmp(31 downto 16) := rs(31 downto 16);
132 end if;
133 if datalen(2) = '1' or datalen(1) = '1' then
134 tmp(15 downto 8) := rs(15 downto 8);
135 end if;
136 tmp(7 downto 0) := rs(7 downto 0);
137 end case;
138
139 result <= tmp;
140
141 end process;
142 end behaviour;