decode: Index minor op table with insn bits for opcode 30
[microwatt.git] / execute1.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.common.all;
8 use work.helpers.all;
9 use work.crhelpers.all;
10 use work.insn_helpers.all;
11 use work.ppc_fx_insns.all;
12
13 entity execute1 is
14 generic (
15 SIM : boolean := false
16 );
17 port (
18 clk : in std_logic;
19
20 -- asynchronous
21 flush_out : out std_ulogic;
22
23 e_in : in Decode2ToExecute1Type;
24
25 -- asynchronous
26 f_out : out Execute1ToFetch1Type;
27
28 e_out : out Execute1ToExecute2Type;
29
30 terminate_out : out std_ulogic
31 );
32 end entity execute1;
33
34 architecture behaviour of execute1 is
35 type reg_type is record
36 --f : Execute1ToFetch1Type;
37 e : Execute1ToExecute2Type;
38 end record;
39
40 signal r, rin : reg_type;
41
42 signal ctrl: ctrl_t := (carry => '0', others => (others => '0'));
43 signal ctrl_tmp: ctrl_t := (carry => '0', others => (others => '0'));
44 begin
45 execute1_0: process(clk)
46 begin
47 if rising_edge(clk) then
48 r <= rin;
49 ctrl <= ctrl_tmp;
50 end if;
51 end process;
52
53 execute1_1: process(all)
54 variable v : reg_type;
55 variable result : std_ulogic_vector(63 downto 0);
56 variable newcrf : std_ulogic_vector(3 downto 0);
57 variable result_with_carry : std_ulogic_vector(64 downto 0);
58 variable result_en : integer;
59 variable crnum : integer;
60 variable scrnum : integer;
61 variable lo, hi : integer;
62 begin
63 result := (others => '0');
64 result_with_carry := (others => '0');
65 result_en := 0;
66
67 v := r;
68 v.e := Execute1ToExecute2Init;
69 --v.f := Execute1ToFetch1TypeInit;
70
71 ctrl_tmp <= ctrl;
72 -- FIXME: run at 512MHz not core freq
73 ctrl_tmp.tb <= std_ulogic_vector(unsigned(ctrl.tb) + 1);
74
75 terminate_out <= '0';
76 f_out <= Execute1ToFetch1TypeInit;
77
78 if e_in.valid = '1' then
79
80 v.e.valid := '1';
81 v.e.write_reg := e_in.write_reg;
82
83 case_0: case e_in.insn_type is
84
85 when OP_ILLEGAL =>
86 terminate_out <= '1';
87 report "illegal";
88 when OP_NOP =>
89 -- Do nothing
90 when OP_ADD =>
91 result := ppc_add(e_in.read_data1, e_in.read_data2);
92 result_en := 1;
93 when OP_ADDE =>
94 result_with_carry := ppc_adde(e_in.read_data1, e_in.read_data2, ctrl.carry and e_in.input_carry);
95 result := result_with_carry(63 downto 0);
96 ctrl_tmp.carry <= result_with_carry(64) and e_in.output_carry;
97 result_en := 1;
98 when OP_AND =>
99 result := ppc_and(e_in.read_data1, e_in.read_data2);
100 result_en := 1;
101 when OP_ANDC =>
102 result := ppc_andc(e_in.read_data1, e_in.read_data2);
103 result_en := 1;
104 when OP_B =>
105 f_out.redirect <= '1';
106 if (insn_aa(e_in.insn)) then
107 f_out.redirect_nia <= std_ulogic_vector(signed(e_in.read_data2));
108 else
109 f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2));
110 end if;
111 when OP_BC =>
112 if e_in.const1(4-2) = '0' then
113 ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1);
114 end if;
115 if ppc_bc_taken(e_in.const1(4 downto 0), e_in.const2(4 downto 0), e_in.cr, ctrl.ctr) = 1 then
116 f_out.redirect <= '1';
117 if (insn_aa(e_in.insn)) then
118 f_out.redirect_nia <= std_ulogic_vector(signed(e_in.read_data2));
119 else
120 f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2));
121 end if;
122 end if;
123 when OP_BCREG =>
124 -- bits 10 and 6 distinguish between bclr, bcctr and bctar
125 if e_in.const1(4-2) = '0' and e_in.insn(10) = '0' then
126 ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1);
127 end if;
128 if ppc_bc_taken(e_in.const1(4 downto 0), e_in.const2(4 downto 0), e_in.cr, ctrl.ctr) = 1 then
129 f_out.redirect <= '1';
130 if e_in.insn(10) = '0' then
131 f_out.redirect_nia <= ctrl.lr(63 downto 2) & "00";
132 else
133 f_out.redirect_nia <= ctrl.ctr(63 downto 2) & "00";
134 end if;
135 end if;
136 when OP_CMPB =>
137 result := ppc_cmpb(e_in.read_data1, e_in.read_data2);
138 result_en := 1;
139 when OP_CMP =>
140 v.e.write_cr_enable := '1';
141 crnum := to_integer(unsigned(e_in.const1(2 downto 0)));
142 v.e.write_cr_mask := num_to_fxm(crnum);
143 for i in 0 to 7 loop
144 lo := i*4;
145 hi := lo + 3;
146 v.e.write_cr_data(hi downto lo) := ppc_cmp(e_in.const2(0), e_in.read_data1, e_in.read_data2);
147 end loop;
148 when OP_CMPL =>
149 v.e.write_cr_enable := '1';
150 crnum := to_integer(unsigned(e_in.const1(2 downto 0)));
151 v.e.write_cr_mask := num_to_fxm(crnum);
152 for i in 0 to 7 loop
153 lo := i*4;
154 hi := lo + 3;
155 v.e.write_cr_data(hi downto lo) := ppc_cmpl(e_in.const2(0), e_in.read_data1, e_in.read_data2);
156 end loop;
157 when OP_CNTLZW =>
158 result := ppc_cntlzw(e_in.read_data1);
159 result_en := 1;
160 when OP_CNTTZW =>
161 result := ppc_cnttzw(e_in.read_data1);
162 result_en := 1;
163 when OP_CNTLZD =>
164 result := ppc_cntlzd(e_in.read_data1);
165 result_en := 1;
166 when OP_CNTTZD =>
167 result := ppc_cnttzd(e_in.read_data1);
168 result_en := 1;
169 when OP_EXTSB =>
170 result := ppc_extsb(e_in.read_data1);
171 result_en := 1;
172 when OP_EXTSH =>
173 result := ppc_extsh(e_in.read_data1);
174 result_en := 1;
175 when OP_EXTSW =>
176 result := ppc_extsw(e_in.read_data1);
177 result_en := 1;
178 when OP_EQV =>
179 result := ppc_eqv(e_in.read_data1, e_in.read_data2);
180 result_en := 1;
181 when OP_ISEL =>
182 crnum := to_integer(unsigned(e_in.const1));
183 if e_in.cr(31-crnum) = '1' then
184 result := e_in.read_data1;
185 else
186 result := e_in.read_data2;
187 end if;
188 result_en := 1;
189 when OP_MCRF =>
190 v.e.write_cr_enable := '1';
191 crnum := to_integer(unsigned(e_in.const1(2 downto 0)));
192 scrnum := to_integer(unsigned(e_in.const2(2 downto 0)));
193 v.e.write_cr_mask := num_to_fxm(crnum);
194 for i in 0 to 7 loop
195 lo := (7-i)*4;
196 hi := lo + 3;
197 if i = scrnum then
198 newcrf := e_in.cr(hi downto lo);
199 end if;
200 end loop;
201 for i in 0 to 7 loop
202 lo := i*4;
203 hi := lo + 3;
204 v.e.write_cr_data(hi downto lo) := newcrf;
205 end loop;
206 when OP_MFSPR =>
207 if std_match(e_in.insn(20 downto 11), "0100100000") then
208 result := ctrl.ctr;
209 result_en := 1;
210 elsif std_match(e_in.insn(20 downto 11), "0100000000") then
211 result := ctrl.lr;
212 result_en := 1;
213 elsif std_match(e_in.insn(20 downto 11), "0110001000") then
214 result := ctrl.tb;
215 result_en := 1;
216 end if;
217 when OP_MFCR =>
218 result := x"00000000" & e_in.cr;
219 result_en := 1;
220 when OP_MFOCRF =>
221 crnum := fxm_to_num(e_in.const1(7 downto 0));
222 result := (others => '0');
223 for i in 0 to 7 loop
224 lo := (7-i)*4;
225 hi := lo + 3;
226 if crnum = i then
227 result(hi downto lo) := e_in.cr(hi downto lo);
228 end if;
229 end loop;
230 result_en := 1;
231 when OP_MTCRF =>
232 v.e.write_cr_enable := '1';
233 v.e.write_cr_mask := e_in.const1(7 downto 0);
234 v.e.write_cr_data := e_in.read_data1(31 downto 0);
235 when OP_MTOCRF =>
236 v.e.write_cr_enable := '1';
237 -- We require one hot priority encoding here
238 crnum := fxm_to_num(e_in.const1(7 downto 0));
239 v.e.write_cr_mask := num_to_fxm(crnum);
240 v.e.write_cr_data := e_in.read_data1(31 downto 0);
241 when OP_MTSPR =>
242 if std_match(e_in.insn(20 downto 11), "0100100000") then
243 ctrl_tmp.ctr <= e_in.read_data1;
244 elsif std_match(e_in.insn(20 downto 11), "0100000000") then
245 ctrl_tmp.lr <= e_in.read_data1;
246 end if;
247 when OP_NAND =>
248 result := ppc_nand(e_in.read_data1, e_in.read_data2);
249 result_en := 1;
250 when OP_NEG =>
251 result := ppc_neg(e_in.read_data1);
252 result_en := 1;
253 when OP_NOR =>
254 result := ppc_nor(e_in.read_data1, e_in.read_data2);
255 result_en := 1;
256 when OP_OR =>
257 result := ppc_or(e_in.read_data1, e_in.read_data2);
258 result_en := 1;
259 when OP_ORC =>
260 result := ppc_orc(e_in.read_data1, e_in.read_data2);
261 result_en := 1;
262 when OP_POPCNTB =>
263 result := ppc_popcntb(e_in.read_data1);
264 result_en := 1;
265 when OP_POPCNTW =>
266 result := ppc_popcntw(e_in.read_data1);
267 result_en := 1;
268 when OP_POPCNTD =>
269 result := ppc_popcntd(e_in.read_data1);
270 result_en := 1;
271 when OP_PRTYD =>
272 result := ppc_prtyd(e_in.read_data1);
273 result_en := 1;
274 when OP_PRTYW =>
275 result := ppc_prtyw(e_in.read_data1);
276 result_en := 1;
277 when OP_RLDCX =>
278 if e_in.insn(1) = '0' then
279 result := ppc_rldcl(e_in.read_data1, e_in.read_data2, e_in.const2(5 downto 0));
280 else
281 result := ppc_rldcr(e_in.read_data1, e_in.read_data2, e_in.const2(5 downto 0));
282 end if;
283 result_en := 1;
284 when OP_RLDICL =>
285 result := ppc_rldicl(e_in.read_data1, e_in.const1(5 downto 0), e_in.const2(5 downto 0));
286 result_en := 1;
287 when OP_RLDICR =>
288 result := ppc_rldicr(e_in.read_data1, e_in.const1(5 downto 0), e_in.const2(5 downto 0));
289 result_en := 1;
290 when OP_RLWNM =>
291 result := ppc_rlwnm(e_in.read_data1, e_in.read_data2, e_in.const2(4 downto 0), e_in.const3(4 downto 0));
292 result_en := 1;
293 when OP_RLWINM =>
294 result := ppc_rlwinm(e_in.read_data1, e_in.const1(4 downto 0), e_in.const2(4 downto 0), e_in.const3(4 downto 0));
295 result_en := 1;
296 when OP_RLDIC =>
297 result := ppc_rldic(e_in.read_data1, e_in.const1(5 downto 0), e_in.const2(5 downto 0));
298 result_en := 1;
299 when OP_RLDIMI =>
300 result := ppc_rldimi(e_in.read_data1, e_in.read_data2, e_in.const1(5 downto 0), e_in.const2(5 downto 0));
301 result_en := 1;
302 when OP_RLWIMI =>
303 result := ppc_rlwimi(e_in.read_data1, e_in.read_data2, e_in.const1(4 downto 0), e_in.const2(4 downto 0), e_in.const3(4 downto 0));
304 result_en := 1;
305 when OP_SLD =>
306 result := ppc_sld(e_in.read_data1, e_in.read_data2);
307 result_en := 1;
308 when OP_SLW =>
309 result := ppc_slw(e_in.read_data1, e_in.read_data2);
310 result_en := 1;
311 when OP_SRAW =>
312 result_with_carry := ppc_sraw(e_in.read_data1, e_in.read_data2);
313 result := result_with_carry(63 downto 0);
314 ctrl_tmp.carry <= result_with_carry(64);
315 result_en := 1;
316 when OP_SRAWI =>
317 result_with_carry := ppc_srawi(e_in.read_data1, e_in.const1(5 downto 0));
318 result := result_with_carry(63 downto 0);
319 ctrl_tmp.carry <= result_with_carry(64);
320 result_en := 1;
321 when OP_SRAD =>
322 result_with_carry := ppc_srad(e_in.read_data1, e_in.read_data2);
323 result := result_with_carry(63 downto 0);
324 ctrl_tmp.carry <= result_with_carry(64);
325 result_en := 1;
326 when OP_SRADI =>
327 result_with_carry := ppc_sradi(e_in.read_data1, e_in.const1(5 downto 0));
328 result := result_with_carry(63 downto 0);
329 ctrl_tmp.carry <= result_with_carry(64);
330 result_en := 1;
331 when OP_SRD =>
332 result := ppc_srd(e_in.read_data1, e_in.read_data2);
333 result_en := 1;
334 when OP_SRW =>
335 result := ppc_srw(e_in.read_data1, e_in.read_data2);
336 result_en := 1;
337 when OP_SUBF =>
338 result := ppc_subf(e_in.read_data1, e_in.read_data2);
339 result_en := 1;
340 when OP_SUBFE =>
341 result_with_carry := ppc_subfe(e_in.read_data1, e_in.read_data2, ctrl.carry or not(e_in.input_carry));
342 result := result_with_carry(63 downto 0);
343 ctrl_tmp.carry <= result_with_carry(64) and e_in.output_carry;
344 result_en := 1;
345 when OP_XOR =>
346 result := ppc_xor(e_in.read_data1, e_in.read_data2);
347 result_en := 1;
348
349 when OP_SIM_CONFIG =>
350 -- bit 0 was used to select the microwatt console, which
351 -- we no longer support.
352 if SIM = true then
353 result := x"0000000000000000";
354 else
355 result := x"0000000000000000";
356 end if;
357 result_en := 1;
358
359 when OP_TDI =>
360 -- Keep our test cases happy for now, ignore trap instructions
361 report "OP_TDI FIXME";
362
363 when others =>
364 terminate_out <= '1';
365 report "illegal";
366 end case;
367
368 if e_in.lr = '1' then
369 ctrl_tmp.lr <= std_ulogic_vector(unsigned(e_in.nia) + 4);
370 end if;
371
372 if result_en = 1 then
373 v.e.write_data := result;
374 v.e.write_enable := '1';
375 v.e.rc := e_in.rc;
376 end if;
377 end if;
378
379 -- Update registers
380 rin <= v;
381
382 -- update outputs
383 --f_out <= r.f;
384 e_out <= r.e;
385 flush_out <= f_out.redirect;
386 end process;
387 end architecture behaviour;