Merge pull request #13 from mikey/dynamic-ranges
[microwatt.git] / ppc_fx_insns.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4
5 library work;
6 use work.helpers.all;
7
8 package ppc_fx_insns is
9 function ppc_addi (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
10 function ppc_addis (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
11 function ppc_add (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
12 function ppc_subf (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
13 function ppc_neg (ra: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
14
15 function ppc_addic (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
16 function ppc_adde (ra, rb: std_ulogic_vector(63 downto 0); carry: std_ulogic) return std_ulogic_vector;
17 function ppc_subfic (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
18 function ppc_subfc (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
19 function ppc_subfe (ra, rb: std_ulogic_vector(63 downto 0); carry: std_ulogic) return std_ulogic_vector;
20 function ppc_addze (ra: std_ulogic_vector(63 downto 0); carry: std_ulogic) return std_ulogic_vector;
21
22 function ppc_andi (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
23 function ppc_andis (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
24 function ppc_ori (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
25 function ppc_oris (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
26 function ppc_xori (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
27 function ppc_xoris (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
28 function ppc_and (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
29 function ppc_xor (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
30 function ppc_nand (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
31 function ppc_or (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
32 function ppc_nor (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
33 function ppc_andc (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
34 function ppc_eqv (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
35 function ppc_orc (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
36
37 function ppc_extsb (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
38 function ppc_extsh (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
39 function ppc_extsw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
40
41 function ppc_cntlzw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
42 function ppc_cnttzw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
43 function ppc_cntlzd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
44 function ppc_cnttzd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
45
46 function ppc_popcntb (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
47 function ppc_popcntw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
48 function ppc_popcntd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
49
50 function ppc_prtyd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
51 function ppc_prtyw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
52
53 function ppc_rlwinm (rs: std_ulogic_vector(63 downto 0); sh, mb, me: std_ulogic_vector(4 downto 0)) return std_ulogic_vector;
54 function ppc_rlwnm (rs, rb: std_ulogic_vector(63 downto 0); mb, me: std_ulogic_vector(4 downto 0)) return std_ulogic_vector;
55 function ppc_rlwimi (ra, rs: std_ulogic_vector(63 downto 0); sh, mb, me: std_ulogic_vector(4 downto 0)) return std_ulogic_vector;
56 function ppc_rldicl (rs: std_ulogic_vector(63 downto 0); sh, mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
57 function ppc_rldicr (rs: std_ulogic_vector(63 downto 0); sh, me: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
58 function ppc_rldic (rs: std_ulogic_vector(63 downto 0); sh, mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
59 function ppc_rldcl (rs, rb: std_ulogic_vector(63 downto 0); mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
60 function ppc_rldcr (rs, rb: std_ulogic_vector(63 downto 0); me: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
61 function ppc_rldimi (ra, rs: std_ulogic_vector(63 downto 0); sh, mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
62
63 function ppc_slw (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
64 function ppc_srw (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
65 function ppc_srawi (rs : std_ulogic_vector(63 downto 0); sh: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
66 function ppc_sraw (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
67 function ppc_sld (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
68 function ppc_srd (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
69 function ppc_sradi (rs: std_ulogic_vector(63 downto 0); sh: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
70 function ppc_srad (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
71
72 function ppc_mulld (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
73 function ppc_mulhd (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
74 function ppc_mulhdu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
75 function ppc_mulli (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
76 function ppc_mullw (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
77 function ppc_mulhw (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
78 function ppc_mulhwu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
79
80 function ppc_cmpi (l: std_ulogic; ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
81 function ppc_cmp (l: std_ulogic; ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
82 function ppc_cmpli (l: std_ulogic; ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
83 function ppc_cmpl (l: std_ulogic; ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
84
85 function ppc_cmpb (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
86
87 function ppc_divw (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
88 function ppc_divdu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
89 function ppc_divd (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
90 function ppc_divwu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
91
92 function ppc_b (nia: std_ulogic_vector(63 downto 0); bd: std_ulogic_vector(23 downto 0)) return std_ulogic_vector;
93 function ppc_bc_taken(bo, bi: std_ulogic_vector(4 downto 0); cr: std_ulogic_vector(31 downto 0); ctr: std_ulogic_vector(63 downto 0)) return integer;
94 function ppc_bcctr_taken(bo, bi: std_ulogic_vector(4 downto 0); cr: std_ulogic_vector(31 downto 0)) return integer;
95 end package ppc_fx_insns;
96
97 package body ppc_fx_insns is
98 function ppc_addi (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
99 begin
100 return std_ulogic_vector(signed(ra) + signed(si));
101 end;
102
103 function ppc_addic (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
104 begin
105 return std_logic_vector(resize(unsigned(ra), 65) + unsigned(resize(signed(si), 64)));
106 end;
107
108 function ppc_adde (ra, rb: std_ulogic_vector(63 downto 0); carry: std_ulogic) return std_ulogic_vector is
109 begin
110 return std_logic_vector(resize(unsigned(ra), 65) + resize(unsigned(rb), 65) + carry);
111 end;
112
113 function ppc_subfic (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
114 begin
115 return std_logic_vector(unsigned(resize(signed(si), 64)) + resize(unsigned(not(ra)), 65) + 1);
116 end;
117
118 function ppc_subfc (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
119 begin
120 return std_logic_vector(resize(unsigned(rb), 65) + resize(unsigned(not(ra)), 65) + 1);
121 end;
122
123 function ppc_subfe (ra, rb: std_ulogic_vector(63 downto 0); carry: std_ulogic) return std_ulogic_vector is
124 begin
125 return std_logic_vector(resize(unsigned(rb), 65) + resize(unsigned(not(ra)), 65) + carry);
126 end;
127
128 function ppc_addze (ra: std_ulogic_vector(63 downto 0); carry: std_ulogic) return std_ulogic_vector is
129 begin
130 return std_logic_vector(resize(unsigned(ra), 65) + carry);
131 end;
132
133 function ppc_addis (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
134 begin
135 return std_ulogic_vector(signed(ra) + shift_left(resize(signed(si), 32), 16));
136 end;
137
138 function ppc_add (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
139 begin
140 return std_ulogic_vector(signed(ra) + signed(rb));
141 end;
142
143 function ppc_subf (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
144 begin
145 return std_ulogic_vector(signed(rb) - signed(ra));
146 end;
147
148 function ppc_neg (ra: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
149 begin
150 return std_ulogic_vector(-signed(ra));
151 end;
152
153 function ppc_andi (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
154 begin
155 return rs and std_ulogic_vector(resize(unsigned(ui), 64));
156 end;
157
158 function ppc_andis (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
159 begin
160 return rs and std_ulogic_vector(shift_left(resize(unsigned(ui), 64), 16));
161 end;
162
163 function ppc_ori (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
164 begin
165 return rs or std_ulogic_vector(resize(unsigned(ui), 64));
166 end;
167
168 function ppc_oris (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
169 begin
170 return rs or std_ulogic_vector(shift_left(resize(unsigned(ui), 64), 16));
171 end;
172
173 function ppc_xori (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
174 begin
175 return rs xor std_ulogic_vector(resize(unsigned(ui), 64));
176 end;
177
178 function ppc_xoris (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
179 begin
180 return rs xor std_ulogic_vector(shift_left(resize(unsigned(ui), 64), 16));
181 end;
182
183 function ppc_and (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
184 begin
185 return rs and rb;
186 end;
187
188 function ppc_xor (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
189 begin
190 return rs xor rb;
191 end;
192
193 function ppc_nand (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
194 begin
195 return rs nand rb;
196 end;
197
198 function ppc_or (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
199 begin
200 return rs or rb;
201 end;
202
203 function ppc_nor (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
204 begin
205 return rs nor rb;
206 end;
207
208 function ppc_andc (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
209 begin
210 return rs and not(rb);
211 end;
212
213 function ppc_eqv (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
214 begin
215 return not(rs xor rb);
216 end;
217
218 function ppc_orc (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
219 begin
220 return rs or not(rb);
221 end;
222
223 function ppc_extsb (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
224 begin
225 return std_ulogic_vector(resize(signed(rs(7 downto 0)), rs'length));
226 end;
227
228 function ppc_extsh (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
229 begin
230 return std_ulogic_vector(resize(signed(rs(15 downto 0)), rs'length));
231 end;
232
233 function ppc_extsw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
234 begin
235 return std_ulogic_vector(resize(signed(rs(31 downto 0)), rs'length));
236 end;
237
238 function ppc_cntlzw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
239 begin
240 return std_ulogic_vector(to_unsigned(fls_32(rs(31 downto 0)), rs'length));
241 end;
242
243 function ppc_cnttzw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
244 begin
245 return std_ulogic_vector(to_unsigned(ffs_32(rs(31 downto 0)), rs'length));
246 end;
247
248 function ppc_cntlzd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
249 begin
250 return std_ulogic_vector(to_unsigned(fls_64(rs), rs'length));
251 end;
252
253 function ppc_cnttzd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
254 begin
255 return std_ulogic_vector(to_unsigned(ffs_64(rs), rs'length));
256 end;
257
258 function ppc_popcntb (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
259 variable ret: std_ulogic_vector (rs'range);
260 variable hi: integer;
261 variable lo: integer;
262 begin
263 ret := (others => '0');
264
265 for i in 1 to 8 loop
266 hi := (8*i)-1;
267 lo := 8*(i-1);
268 ret(hi downto lo) := popcnt8(rs(hi downto lo));
269 end loop;
270
271 return ret;
272 end;
273
274 function ppc_popcntw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
275 variable ret: std_ulogic_vector (rs'range);
276 variable hi: integer;
277 variable lo: integer;
278 begin
279 ret := (others => '0');
280
281 for i in 1 to 2 loop
282 hi := (32*i)-1;
283 lo := 32*(i-1);
284 ret(hi downto lo) := popcnt32(rs(hi downto lo));
285 end loop;
286
287 return ret;
288 end;
289
290 function ppc_popcntd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
291 begin
292 return popcnt64(rs);
293 end;
294
295 function ppc_prtyd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
296 variable tmp : std_ulogic;
297 variable ret : std_ulogic_vector(63 downto 0);
298 begin
299 ret := (others => '0');
300
301 tmp := '0';
302 for i in 0 to 7 loop
303 tmp := tmp xor rs(i*8);
304 end loop;
305
306 ret(0) := tmp;
307 return ret;
308 end;
309
310 function ppc_prtyw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
311 variable tmp : std_ulogic;
312 variable ret : std_ulogic_vector(63 downto 0);
313 begin
314 ret := (others => '0');
315
316 tmp := '0';
317 for i in 0 to 3 loop
318 tmp := tmp xor rs(i*8);
319 end loop;
320 ret(0) := tmp;
321
322 tmp := '0';
323 for i in 4 to 7 loop
324 tmp := tmp xor rs(i*8);
325 end loop;
326 ret(32) := tmp;
327
328 return ret;
329 end;
330
331 function ppc_rlwinm (rs: std_ulogic_vector(63 downto 0); sh, mb, me: std_ulogic_vector(4 downto 0)) return std_ulogic_vector is
332 variable hi, lo : integer;
333 variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
334 begin
335 hi := 31 - to_integer(unsigned(mb));
336 lo := 31 - to_integer(unsigned(me));
337 tmp1 := rs(31 downto 0) & rs(31 downto 0);
338 tmp1 := std_ulogic_vector(rotate_left(unsigned(tmp1), to_integer(unsigned(sh))));
339 tmp2 := (others => '0');
340 if hi < lo then
341 -- Mask wraps around
342 for i in 0 to 63 loop
343 if i <= hi or i >= lo then
344 tmp2(i) := tmp1(i);
345 end if;
346 end loop;
347 else
348 for i in 0 to 63 loop
349 if i >= lo and i <= hi then
350 tmp2(i) := tmp1(i);
351 end if;
352 end loop;
353 end if;
354 return tmp2;
355 end;
356
357 function ppc_rlwnm (rs, rb: std_ulogic_vector(63 downto 0); mb, me: std_ulogic_vector(4 downto 0)) return std_ulogic_vector is
358 variable hi, lo : integer;
359 variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
360 variable n : integer;
361 begin
362 hi := 31 - to_integer(unsigned(mb));
363 lo := 31 - to_integer(unsigned(me));
364 n := to_integer(unsigned(rb(4 downto 0)));
365 tmp1 := rs(31 downto 0) & rs(31 downto 0);
366 tmp1 := std_ulogic_vector(rotate_left(unsigned(tmp1), n));
367 tmp2 := (others => '0');
368 if hi < lo then
369 -- Mask wraps around
370 for i in 0 to 63 loop
371 if i <= hi or i >= lo then
372 tmp2(i) := tmp1(i);
373 end if;
374 end loop;
375 else
376 for i in 0 to 63 loop
377 if i >= lo and i <= hi then
378 tmp2(i) := tmp1(i);
379 end if;
380 end loop;
381 end if;
382 return tmp2;
383 end;
384
385 function ppc_rlwimi (ra, rs: std_ulogic_vector(63 downto 0); sh, mb, me: std_ulogic_vector(4 downto 0)) return std_ulogic_vector is
386 variable hi, lo : integer;
387 variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
388 begin
389 hi := 31 - to_integer(unsigned(mb));
390 lo := 31 - to_integer(unsigned(me));
391 tmp1 := rs(31 downto 0) & rs(31 downto 0);
392 tmp1 := std_ulogic_vector(rotate_left(unsigned(tmp1), to_integer(unsigned(sh))));
393 tmp2 := ra;
394 if hi < lo then
395 -- Mask wraps around
396 for i in 0 to 63 loop
397 if i <= hi or i >= lo then
398 tmp2(i) := tmp1(i);
399 end if;
400 end loop;
401 else
402 for i in 0 to 63 loop
403 if i >= lo and i <= hi then
404 tmp2(i) := tmp1(i);
405 end if;
406 end loop;
407 end if;
408 return tmp2;
409 end;
410
411 function ppc_rldicl (rs: std_ulogic_vector(63 downto 0); sh, mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
412 variable hi : integer;
413 variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
414 begin
415 hi := 63-to_integer(unsigned(mb));
416 tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), to_integer(unsigned(sh))));
417 tmp2 := (others => '0');
418 for i in 0 to 63 loop
419 if i <= hi then
420 tmp2(i) := tmp1(i);
421 end if;
422 end loop;
423 return tmp2;
424 end;
425
426 function ppc_rldicr (rs: std_ulogic_vector(63 downto 0); sh, me: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
427 variable lo : integer;
428 variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
429 begin
430 lo := 63-to_integer(unsigned(me));
431 tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), to_integer(unsigned(sh))));
432 tmp2 := (others => '0');
433 for i in 0 to 63 loop
434 if i >= lo then
435 tmp2(i) := tmp1(i);
436 end if;
437 end loop;
438 return tmp2;
439 end;
440
441 function ppc_rldic (rs: std_ulogic_vector(63 downto 0); sh, mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
442 variable hi, lo : integer;
443 variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
444 begin
445 hi := 63-to_integer(unsigned(mb));
446 lo := to_integer(unsigned(sh));
447 tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), to_integer(unsigned(sh))));
448 tmp2 := (others => '0');
449 if hi < lo then
450 -- Mask wraps around
451 for i in 0 to 63 loop
452 if i <= hi or i >= lo then
453 tmp2(i) := tmp1(i);
454 end if;
455 end loop;
456 else
457 for i in 0 to 63 loop
458 if i >= lo and i <= hi then
459 tmp2(i) := tmp1(i);
460 end if;
461 end loop;
462 end if;
463 return tmp2;
464 end;
465
466 function ppc_rldcl (rs, rb: std_ulogic_vector(63 downto 0); mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
467 variable hi : integer;
468 variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
469 begin
470 hi := 63-to_integer(unsigned(mb));
471 tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), to_integer(unsigned(rb(5 downto 0)))));
472 tmp2 := (others => '0');
473 for i in 0 to 63 loop
474 if i <= hi then
475 tmp2(i) := tmp1(i);
476 end if;
477 end loop;
478 return tmp2;
479 end;
480
481 function ppc_rldcr (rs, rb: std_ulogic_vector(63 downto 0); me: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
482 variable lo : integer;
483 variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
484 begin
485 lo := 63-to_integer(unsigned(me));
486 tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), to_integer(unsigned(rb(5 downto 0)))));
487 tmp2 := (others => '0');
488 for i in 0 to 63 loop
489 if i >= lo then
490 tmp2(i) := tmp1(i);
491 end if;
492 end loop;
493 return tmp2;
494 end;
495
496 function ppc_rldimi (ra, rs: std_ulogic_vector(63 downto 0); sh, mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
497 variable hi, lo : integer;
498 variable tmp1, tmp2 : std_ulogic_vector(rs'range);
499 begin
500 hi := 63-to_integer(unsigned(mb));
501 lo := to_integer(unsigned(sh));
502 tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), lo));
503 tmp2 := ra;
504 if hi < lo then
505 -- Mask wraps around
506 for i in 0 to 63 loop
507 if i <= hi or i >= lo then
508 tmp2(i) := tmp1(i);
509 end if;
510 end loop;
511 else
512 for i in 0 to 63 loop
513 if i >= lo and i <= hi then
514 tmp2(i) := tmp1(i);
515 end if;
516 end loop;
517 end if;
518 return tmp2;
519 end;
520
521 function ppc_slw (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
522 variable n : integer;
523 variable tmp : unsigned(31 downto 0);
524 begin
525 n := to_integer(unsigned(rb(5 downto 0)));
526 tmp := shift_left(unsigned(rs(31 downto 0)), n);
527
528 return (63 downto 32 => '0') & std_ulogic_vector(tmp);
529 end;
530
531 function ppc_srw (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
532 variable n : integer;
533 variable tmp : unsigned(31 downto 0);
534 begin
535 n := to_integer(unsigned(rb(5 downto 0)));
536 tmp := shift_right(unsigned(rs(31 downto 0)), n);
537
538 return (63 downto 32 => '0') & std_ulogic_vector(tmp);
539 end;
540
541 function ppc_srawi (rs : std_ulogic_vector(63 downto 0); sh: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
542 variable n : integer;
543 variable tmp : signed(31 downto 0);
544 variable mask : std_ulogic_vector(63 downto 0);
545 variable carry: std_ulogic;
546 begin
547 n := to_integer(unsigned(sh));
548 tmp := shift_right(signed(rs(31 downto 0)), n);
549 -- what about n = 0?
550 mask := (others => '0');
551 for i in 0 to 63 loop
552 if i < n then
553 mask(i) := '1';
554 end if;
555 end loop;
556 carry := '0' when (rs and mask) = (63 downto 0 => '0') else rs(31);
557
558 return carry & std_ulogic_vector(resize(tmp, rs'length));
559 end;
560
561 function ppc_sraw (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
562 variable n : natural;
563 variable tmp : signed(31 downto 0);
564 variable mask : std_ulogic_vector(63 downto 0);
565 variable carry: std_ulogic;
566 begin
567 n := to_integer(unsigned(rb(5 downto 0)));
568 tmp := shift_right(signed(rs(31 downto 0)), n);
569 -- what about n = 0?
570 mask := (others => '0');
571 for i in 0 to 63 loop
572 if i < n then
573 mask(i) := '1';
574 end if;
575 end loop;
576 carry := or (rs and mask) and rs(31);
577 return carry & std_ulogic_vector(resize(tmp, rs'length));
578 end;
579
580 function ppc_sld (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
581 variable n : integer;
582 begin
583 n := to_integer(unsigned(rb(6 downto 0)));
584 return std_ulogic_vector(shift_left(unsigned(rs), n));
585 end;
586
587 function ppc_srd (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
588 variable n : integer;
589 begin
590 n := to_integer(unsigned(rb(6 downto 0)));
591 return std_ulogic_vector(shift_right(unsigned(rs), n));
592 end;
593
594 function ppc_sradi (rs: std_ulogic_vector(63 downto 0); sh: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
595 variable n : integer;
596 variable carry: std_ulogic;
597 variable mask : std_ulogic_vector(63 downto 0);
598 begin
599 n := to_integer(unsigned(sh));
600 -- what about n = 0?
601 mask := (others => '0');
602 for i in 0 to 63 loop
603 if i < n then
604 mask(i) := '1';
605 end if;
606 end loop;
607 carry := '0' when (rs and mask) = (63 downto 0 => '0') else rs(63);
608
609 return carry & std_ulogic_vector(shift_right(signed(rs), n));
610 end;
611
612 function ppc_srad (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
613 variable n : integer;
614 variable carry: std_ulogic;
615 variable mask : std_ulogic_vector(63 downto 0);
616 begin
617 n := to_integer(unsigned(rb(6 downto 0)));
618 -- what about n = 0?
619 mask := (others => '0');
620 for i in 0 to 63 loop
621 if i < n then
622 mask(i) := '1';
623 end if;
624 end loop;
625 carry := '0' when (rs and mask) = (63 downto 0 => '0') else rs(63);
626
627 return carry & std_ulogic_vector(shift_right(signed(rs), n));
628 end;
629
630 -- Not sure how to better communicate the top 64 bits of the result is unused
631 function ppc_mulld (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
632 variable tmp: signed(127 downto 0);
633 begin
634 tmp := signed(ra) * signed(rb);
635 return std_ulogic_vector(tmp(63 downto 0));
636 end;
637
638 -- Not sure how to better communicate the top 64 bits of the result is unused
639 function ppc_mulhd (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
640 variable tmp: signed(127 downto 0);
641 begin
642 tmp := signed(ra) * signed(rb);
643 return std_ulogic_vector(tmp(127 downto 64));
644 end;
645
646 -- Not sure how to better communicate the top 64 bits of the result is unused
647 function ppc_mulhdu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
648 variable tmp: unsigned(127 downto 0);
649 begin
650 tmp := unsigned(ra) * unsigned(rb);
651 return std_ulogic_vector(tmp(127 downto 64));
652 end;
653
654 -- Not sure how to better communicate the top 16 bits of the result is unused
655 function ppc_mulli (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
656 variable tmp: signed(79 downto 0);
657 begin
658 tmp := signed(ra) * signed(si);
659 return std_ulogic_vector(tmp(63 downto 0));
660 end;
661
662 function ppc_mullw (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
663 begin
664 return std_ulogic_vector(signed(ra(31 downto 0)) * signed(rb(31 downto 0)));
665 end;
666
667 function ppc_mulhw (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
668 variable tmp: signed(63 downto 0);
669 begin
670 tmp := signed(ra(31 downto 0)) * signed(rb(31 downto 0));
671 return std_ulogic_vector(tmp(63 downto 32)) & std_ulogic_vector(tmp(63 downto 32));
672 end;
673
674 function ppc_mulhwu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
675 variable tmp: unsigned(63 downto 0);
676 begin
677 tmp := unsigned(ra(31 downto 0)) * unsigned(rb(31 downto 0));
678 return std_ulogic_vector(tmp(63 downto 32)) & std_ulogic_vector(tmp(63 downto 32));
679 end;
680
681 function ppc_cmpi (l: std_ulogic; ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
682 variable tmp: signed(ra'range);
683 begin
684 tmp := signed(ra);
685 if l = '0' then
686 tmp := resize(signed(ra(31 downto 0)), tmp'length);
687 end if;
688
689 return ppc_signed_compare(tmp, resize(signed(si), tmp'length));
690 end;
691
692 function ppc_cmp (l: std_ulogic; ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
693 variable tmpa, tmpb: signed(ra'range);
694 begin
695 tmpa := signed(ra);
696 tmpb := signed(rb);
697 if l = '0' then
698 tmpa := resize(signed(ra(31 downto 0)), ra'length);
699 tmpb := resize(signed(rb(31 downto 0)), ra'length);
700 end if;
701
702 return ppc_signed_compare(tmpa, tmpb);
703 end;
704
705 function ppc_cmpli (l: std_ulogic; ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
706 variable tmp: unsigned(ra'range);
707 begin
708 tmp := unsigned(ra);
709 if l = '0' then
710 tmp := resize(unsigned(ra(31 downto 0)), tmp'length);
711 end if;
712
713 return ppc_unsigned_compare(tmp, resize(unsigned(si), tmp'length));
714 end;
715
716 function ppc_cmpl (l: std_ulogic; ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
717 variable tmpa, tmpb: unsigned(ra'range);
718 begin
719 tmpa := unsigned(ra);
720 tmpb := unsigned(rb);
721 if l = '0' then
722 tmpa := resize(unsigned(ra(31 downto 0)), ra'length);
723 tmpb := resize(unsigned(rb(31 downto 0)), ra'length);
724 end if;
725
726 return ppc_unsigned_compare(tmpa, tmpb);
727 end;
728
729 function ppc_cmpb (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
730 variable ret: std_ulogic_vector (rs'range);
731 variable hi: integer;
732 variable lo: integer;
733 begin
734 for i in 1 to 8 loop
735 hi := (8*i)-1;
736 lo := 8*(i-1);
737 ret(hi downto lo) := cmp_one_byte(rs(hi downto lo), rb(hi downto lo));
738 end loop;
739
740 return ret;
741 end;
742
743 -- Not synthesizable
744 function ppc_divw (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
745 variable tmp: signed(31 downto 0);
746 begin
747 tmp := signed(ra(31 downto 0)) / signed(rb(31 downto 0));
748
749 return (63 downto 32 => '0') & std_ulogic_vector(tmp);
750 end;
751
752 function ppc_divdu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
753 variable tmp: unsigned(63 downto 0) := (others => '0');
754 begin
755 if unsigned(rb) /= 0 then
756 tmp := unsigned(ra) / unsigned(rb);
757 end if;
758
759 return std_ulogic_vector(tmp);
760 end;
761
762 function ppc_divd (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
763 variable tmp: signed(63 downto 0) := (others => '0');
764 begin
765 if signed(rb) /= 0 then
766 tmp := signed(ra) / signed(rb);
767 end if;
768
769 return std_ulogic_vector(tmp);
770 end;
771
772 function ppc_divwu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
773 variable tmp: unsigned(31 downto 0) := (others => '0');
774 begin
775 if unsigned(rb(31 downto 0)) /= 0 then
776 tmp := unsigned(ra(31 downto 0)) / unsigned(rb(31 downto 0));
777 end if;
778
779 return std_ulogic_vector(resize(tmp, ra'length));
780 end;
781
782 function ppc_b (nia: std_ulogic_vector(63 downto 0); bd: std_ulogic_vector(23 downto 0)) return std_ulogic_vector is
783 begin
784 return std_ulogic_vector(signed(nia) + signed(bd & "00"));
785 end;
786
787 function ppc_bc_taken(bo, bi: std_ulogic_vector(4 downto 0); cr: std_ulogic_vector(31 downto 0); ctr: std_ulogic_vector(63 downto 0)) return integer is
788 variable crfield: integer;
789 variable crbit_match: std_ulogic;
790 variable ctr_not_zero: std_ulogic;
791 variable ctr_ok: std_ulogic;
792 variable cond_ok: std_ulogic;
793 variable ret: integer;
794 begin
795 crfield := to_integer(unsigned(bi));
796 -- BE bit numbering
797 crbit_match := '1' when cr(31-crfield) = bo(4-1) else '0';
798 -- We check this before it is decremented
799 ctr_not_zero := '1' when ctr /= x"0000000000000001" else '0';
800 ctr_ok := bo(4-2) or (ctr_not_zero xor bo(4-3));
801 cond_ok := bo(4-0) or crbit_match;
802 if ctr_ok = '1' and cond_ok = '1' then
803 ret := 1;
804 else
805 ret := 0;
806 end if;
807 return ret;
808 end;
809
810 function ppc_bcctr_taken(bo, bi: std_ulogic_vector(4 downto 0); cr: std_ulogic_vector(31 downto 0)) return integer is
811 variable crfield: integer;
812 variable crbit_match: std_ulogic;
813 variable cond_ok: std_ulogic;
814 variable ret: integer;
815 begin
816 crfield := to_integer(unsigned(bi));
817 -- BE bit numbering
818 crbit_match := '1' when cr(31-crfield) = bo(4-1) else '0';
819 cond_ok := bo(4-0) or crbit_match;
820 if cond_ok = '1' then
821 ret := 1;
822 else
823 ret := 0;
824 end if;
825 return ret;
826 end;
827 end package body ppc_fx_insns;