1
0
mirror of https://github.com/antonblanchard/microwatt.git synced 2026-01-11 23:43:15 +00:00
antonblanchard.microwatt/ppc_fx_insns.vhdl
Benjamin Herrenschmidt e4f475e17f sprs: Store common SPRs in register file
This stores the most common SPRs in the register file.

This includes CTR and LR and a not yet final list of others.

The register file is set to 64 entries for now. Specific types
are defined that can represent a GPR index (gpr_index_t) or
a GPR/SPR index (gspr_index_t) along with conversion functions
between the two.

On order to deal with some forms of branch updating both LR and
CTR, we introduced a delayed update of LR after a branch link.

Note: We currently stall the pipeline on such a delayed branch,
but we could avoid stalling fetch in that specific case as we
know we have a branch delay. We could also limit that to the
specific case where we need to update both CTR and LR.

This allows us to make bcreg, mtspr and mfspr pipelined. decode1
will automatically force the single issue flag on mfspr/mtspr to
a "slow" SPR.

[paulus@ozlabs.org - fix direction of decode2.stall_in]

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2019-12-07 15:30:40 +11:00

812 lines
29 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.helpers.all;
package ppc_fx_insns is
function ppc_addi (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_addis (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_add (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_subf (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_neg (ra: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_addic (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_adde (ra, rb: std_ulogic_vector(63 downto 0); carry: std_ulogic) return std_ulogic_vector;
function ppc_subfic (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_subfc (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_subfe (ra, rb: std_ulogic_vector(63 downto 0); carry: std_ulogic) return std_ulogic_vector;
function ppc_addze (ra: std_ulogic_vector(63 downto 0); carry: std_ulogic) return std_ulogic_vector;
function ppc_andi (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_andis (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_ori (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_oris (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_xori (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_xoris (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_and (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_xor (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_nand (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_or (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_nor (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_andc (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_eqv (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_orc (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_extsb (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_extsh (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_extsw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_cntlzw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_cnttzw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_cntlzd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_cnttzd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_popcntb (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_popcntw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_popcntd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_prtyd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_prtyw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_rlwinm (rs: std_ulogic_vector(63 downto 0); sh, mb, me: std_ulogic_vector(4 downto 0)) return std_ulogic_vector;
function ppc_rlwnm (rs, rb: std_ulogic_vector(63 downto 0); mb, me: std_ulogic_vector(4 downto 0)) return std_ulogic_vector;
function ppc_rlwimi (ra, rs: std_ulogic_vector(63 downto 0); sh, mb, me: std_ulogic_vector(4 downto 0)) return std_ulogic_vector;
function ppc_rldicl (rs: std_ulogic_vector(63 downto 0); sh, mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
function ppc_rldicr (rs: std_ulogic_vector(63 downto 0); sh, me: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
function ppc_rldic (rs: std_ulogic_vector(63 downto 0); sh, mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
function ppc_rldcl (rs, rb: std_ulogic_vector(63 downto 0); mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
function ppc_rldcr (rs, rb: std_ulogic_vector(63 downto 0); me: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
function ppc_rldimi (ra, rs: std_ulogic_vector(63 downto 0); sh, mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
function ppc_slw (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_srw (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_srawi (rs : std_ulogic_vector(63 downto 0); sh: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
function ppc_sraw (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_sld (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_srd (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_sradi (rs: std_ulogic_vector(63 downto 0); sh: std_ulogic_vector(5 downto 0)) return std_ulogic_vector;
function ppc_srad (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_mulld (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_mulhd (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_mulhdu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_mulli (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
function ppc_mullw (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_mulhw (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_mulhwu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_cmpi (l: std_ulogic; ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0);
so: std_ulogic) return std_ulogic_vector;
function ppc_cmp (l: std_ulogic; ra, rb: std_ulogic_vector(63 downto 0);
so: std_ulogic) return std_ulogic_vector;
function ppc_cmpli (l: std_ulogic; ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0);
so: std_ulogic) return std_ulogic_vector;
function ppc_cmpl (l: std_ulogic; ra, rb: std_ulogic_vector(63 downto 0);
so: std_ulogic) return std_ulogic_vector;
function ppc_cmpb (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_divw (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_divdu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_divd (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_divwu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
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;
end package ppc_fx_insns;
package body ppc_fx_insns is
function ppc_addi (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(signed(ra) + signed(si));
end;
function ppc_addic (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
begin
return std_logic_vector(resize(unsigned(ra), 65) + unsigned(resize(signed(si), 64)));
end;
function ppc_adde (ra, rb: std_ulogic_vector(63 downto 0); carry: std_ulogic) return std_ulogic_vector is
begin
return std_logic_vector(resize(unsigned(ra), 65) + resize(unsigned(rb), 65) + carry);
end;
function ppc_subfic (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
begin
return std_logic_vector(unsigned(resize(signed(si), 64)) + resize(unsigned(not(ra)), 65) + 1);
end;
function ppc_subfc (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_logic_vector(resize(unsigned(rb), 65) + resize(unsigned(not(ra)), 65) + 1);
end;
function ppc_subfe (ra, rb: std_ulogic_vector(63 downto 0); carry: std_ulogic) return std_ulogic_vector is
begin
return std_logic_vector(resize(unsigned(rb), 65) + resize(unsigned(not(ra)), 65) + carry);
end;
function ppc_addze (ra: std_ulogic_vector(63 downto 0); carry: std_ulogic) return std_ulogic_vector is
begin
return std_logic_vector(resize(unsigned(ra), 65) + carry);
end;
function ppc_addis (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(signed(ra) + shift_left(resize(signed(si), 32), 16));
end;
function ppc_add (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(signed(ra) + signed(rb));
end;
function ppc_subf (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(signed(rb) - signed(ra));
end;
function ppc_neg (ra: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(-signed(ra));
end;
function ppc_andi (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
begin
return rs and std_ulogic_vector(resize(unsigned(ui), 64));
end;
function ppc_andis (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
begin
return rs and std_ulogic_vector(shift_left(resize(unsigned(ui), 64), 16));
end;
function ppc_ori (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
begin
return rs or std_ulogic_vector(resize(unsigned(ui), 64));
end;
function ppc_oris (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
begin
return rs or std_ulogic_vector(shift_left(resize(unsigned(ui), 64), 16));
end;
function ppc_xori (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
begin
return rs xor std_ulogic_vector(resize(unsigned(ui), 64));
end;
function ppc_xoris (rs: std_ulogic_vector(63 downto 0); ui: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
begin
return rs xor std_ulogic_vector(shift_left(resize(unsigned(ui), 64), 16));
end;
function ppc_and (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return rs and rb;
end;
function ppc_xor (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return rs xor rb;
end;
function ppc_nand (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return rs nand rb;
end;
function ppc_or (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return rs or rb;
end;
function ppc_nor (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return rs nor rb;
end;
function ppc_andc (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return rs and not(rb);
end;
function ppc_eqv (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return not(rs xor rb);
end;
function ppc_orc (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return rs or not(rb);
end;
function ppc_extsb (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(resize(signed(rs(7 downto 0)), rs'length));
end;
function ppc_extsh (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(resize(signed(rs(15 downto 0)), rs'length));
end;
function ppc_extsw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(resize(signed(rs(31 downto 0)), rs'length));
end;
function ppc_cntlzw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(to_unsigned(fls_32(rs(31 downto 0)), rs'length));
end;
function ppc_cnttzw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(to_unsigned(ffs_32(rs(31 downto 0)), rs'length));
end;
function ppc_cntlzd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(to_unsigned(fls_64(rs), rs'length));
end;
function ppc_cnttzd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(to_unsigned(ffs_64(rs), rs'length));
end;
function ppc_popcntb (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable ret: std_ulogic_vector (rs'range);
variable hi: integer;
variable lo: integer;
begin
ret := (others => '0');
for i in 1 to 8 loop
hi := (8*i)-1;
lo := 8*(i-1);
ret(hi downto lo) := popcnt8(rs(hi downto lo));
end loop;
return ret;
end;
function ppc_popcntw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable ret: std_ulogic_vector (rs'range);
variable hi: integer;
variable lo: integer;
begin
ret := (others => '0');
for i in 1 to 2 loop
hi := (32*i)-1;
lo := 32*(i-1);
ret(hi downto lo) := popcnt32(rs(hi downto lo));
end loop;
return ret;
end;
function ppc_popcntd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return popcnt64(rs);
end;
function ppc_prtyd (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp : std_ulogic;
variable ret : std_ulogic_vector(63 downto 0);
begin
ret := (others => '0');
tmp := '0';
for i in 0 to 7 loop
tmp := tmp xor rs(i*8);
end loop;
ret(0) := tmp;
return ret;
end;
function ppc_prtyw (rs: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp : std_ulogic;
variable ret : std_ulogic_vector(63 downto 0);
begin
ret := (others => '0');
tmp := '0';
for i in 0 to 3 loop
tmp := tmp xor rs(i*8);
end loop;
ret(0) := tmp;
tmp := '0';
for i in 4 to 7 loop
tmp := tmp xor rs(i*8);
end loop;
ret(32) := tmp;
return ret;
end;
function ppc_rlwinm (rs: std_ulogic_vector(63 downto 0); sh, mb, me: std_ulogic_vector(4 downto 0)) return std_ulogic_vector is
variable hi, lo : integer;
variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
begin
hi := 31 - to_integer(unsigned(mb));
lo := 31 - to_integer(unsigned(me));
tmp1 := rs(31 downto 0) & rs(31 downto 0);
tmp1 := std_ulogic_vector(rotate_left(unsigned(tmp1), to_integer(unsigned(sh))));
tmp2 := (others => '0');
if hi < lo then
-- Mask wraps around
for i in 0 to 63 loop
if i <= hi or i >= lo then
tmp2(i) := tmp1(i);
end if;
end loop;
else
for i in 0 to 63 loop
if i >= lo and i <= hi then
tmp2(i) := tmp1(i);
end if;
end loop;
end if;
return tmp2;
end;
function ppc_rlwnm (rs, rb: std_ulogic_vector(63 downto 0); mb, me: std_ulogic_vector(4 downto 0)) return std_ulogic_vector is
variable hi, lo : integer;
variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
variable n : integer;
begin
hi := 31 - to_integer(unsigned(mb));
lo := 31 - to_integer(unsigned(me));
n := to_integer(unsigned(rb(4 downto 0)));
tmp1 := rs(31 downto 0) & rs(31 downto 0);
tmp1 := std_ulogic_vector(rotate_left(unsigned(tmp1), n));
tmp2 := (others => '0');
if hi < lo then
-- Mask wraps around
for i in 0 to 63 loop
if i <= hi or i >= lo then
tmp2(i) := tmp1(i);
end if;
end loop;
else
for i in 0 to 63 loop
if i >= lo and i <= hi then
tmp2(i) := tmp1(i);
end if;
end loop;
end if;
return tmp2;
end;
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
variable hi, lo : integer;
variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
begin
hi := 31 - to_integer(unsigned(mb));
lo := 31 - to_integer(unsigned(me));
tmp1 := rs(31 downto 0) & rs(31 downto 0);
tmp1 := std_ulogic_vector(rotate_left(unsigned(tmp1), to_integer(unsigned(sh))));
tmp2 := ra;
if hi < lo then
-- Mask wraps around
for i in 0 to 63 loop
if i <= hi or i >= lo then
tmp2(i) := tmp1(i);
end if;
end loop;
else
for i in 0 to 63 loop
if i >= lo and i <= hi then
tmp2(i) := tmp1(i);
end if;
end loop;
end if;
return tmp2;
end;
function ppc_rldicl (rs: std_ulogic_vector(63 downto 0); sh, mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
variable hi : integer;
variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
begin
hi := 63-to_integer(unsigned(mb));
tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), to_integer(unsigned(sh))));
tmp2 := (others => '0');
for i in 0 to 63 loop
if i <= hi then
tmp2(i) := tmp1(i);
end if;
end loop;
return tmp2;
end;
function ppc_rldicr (rs: std_ulogic_vector(63 downto 0); sh, me: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
variable lo : integer;
variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
begin
lo := 63-to_integer(unsigned(me));
tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), to_integer(unsigned(sh))));
tmp2 := (others => '0');
for i in 0 to 63 loop
if i >= lo then
tmp2(i) := tmp1(i);
end if;
end loop;
return tmp2;
end;
function ppc_rldic (rs: std_ulogic_vector(63 downto 0); sh, mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
variable hi, lo : integer;
variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
begin
hi := 63-to_integer(unsigned(mb));
lo := to_integer(unsigned(sh));
tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), to_integer(unsigned(sh))));
tmp2 := (others => '0');
if hi < lo then
-- Mask wraps around
for i in 0 to 63 loop
if i <= hi or i >= lo then
tmp2(i) := tmp1(i);
end if;
end loop;
else
for i in 0 to 63 loop
if i >= lo and i <= hi then
tmp2(i) := tmp1(i);
end if;
end loop;
end if;
return tmp2;
end;
function ppc_rldcl (rs, rb: std_ulogic_vector(63 downto 0); mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
variable hi : integer;
variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
begin
hi := 63-to_integer(unsigned(mb));
tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), to_integer(unsigned(rb(5 downto 0)))));
tmp2 := (others => '0');
for i in 0 to 63 loop
if i <= hi then
tmp2(i) := tmp1(i);
end if;
end loop;
return tmp2;
end;
function ppc_rldcr (rs, rb: std_ulogic_vector(63 downto 0); me: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
variable lo : integer;
variable tmp1, tmp2 : std_ulogic_vector(63 downto 0);
begin
lo := 63-to_integer(unsigned(me));
tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), to_integer(unsigned(rb(5 downto 0)))));
tmp2 := (others => '0');
for i in 0 to 63 loop
if i >= lo then
tmp2(i) := tmp1(i);
end if;
end loop;
return tmp2;
end;
function ppc_rldimi (ra, rs: std_ulogic_vector(63 downto 0); sh, mb: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
variable hi, lo : integer;
variable tmp1, tmp2 : std_ulogic_vector(rs'range);
begin
hi := 63-to_integer(unsigned(mb));
lo := to_integer(unsigned(sh));
tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), lo));
tmp2 := ra;
if hi < lo then
-- Mask wraps around
for i in 0 to 63 loop
if i <= hi or i >= lo then
tmp2(i) := tmp1(i);
end if;
end loop;
else
for i in 0 to 63 loop
if i >= lo and i <= hi then
tmp2(i) := tmp1(i);
end if;
end loop;
end if;
return tmp2;
end;
function ppc_slw (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable n : integer;
variable tmp : unsigned(31 downto 0);
begin
n := to_integer(unsigned(rb(5 downto 0)));
tmp := shift_left(unsigned(rs(31 downto 0)), n);
return (63 downto 32 => '0') & std_ulogic_vector(tmp);
end;
function ppc_srw (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable n : integer;
variable tmp : unsigned(31 downto 0);
begin
n := to_integer(unsigned(rb(5 downto 0)));
tmp := shift_right(unsigned(rs(31 downto 0)), n);
return (63 downto 32 => '0') & std_ulogic_vector(tmp);
end;
function ppc_srawi (rs : std_ulogic_vector(63 downto 0); sh: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
variable n : integer;
variable tmp : signed(31 downto 0);
variable mask : std_ulogic_vector(63 downto 0);
variable carry: std_ulogic;
begin
n := to_integer(unsigned(sh));
tmp := shift_right(signed(rs(31 downto 0)), n);
-- what about n = 0?
mask := (others => '0');
for i in 0 to 63 loop
if i < n then
mask(i) := '1';
end if;
end loop;
carry := '0' when (rs and mask) = (63 downto 0 => '0') else rs(31);
return carry & std_ulogic_vector(resize(tmp, rs'length));
end;
function ppc_sraw (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable n : natural;
variable tmp : signed(31 downto 0);
variable mask : std_ulogic_vector(63 downto 0);
variable carry: std_ulogic;
begin
n := to_integer(unsigned(rb(5 downto 0)));
tmp := shift_right(signed(rs(31 downto 0)), n);
-- what about n = 0?
mask := (others => '0');
for i in 0 to 63 loop
if i < n then
mask(i) := '1';
end if;
end loop;
carry := or (rs and mask) and rs(31);
return carry & std_ulogic_vector(resize(tmp, rs'length));
end;
function ppc_sld (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable n : integer;
begin
n := to_integer(unsigned(rb(6 downto 0)));
return std_ulogic_vector(shift_left(unsigned(rs), n));
end;
function ppc_srd (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable n : integer;
begin
n := to_integer(unsigned(rb(6 downto 0)));
return std_ulogic_vector(shift_right(unsigned(rs), n));
end;
function ppc_sradi (rs: std_ulogic_vector(63 downto 0); sh: std_ulogic_vector(5 downto 0)) return std_ulogic_vector is
variable n : integer;
variable carry: std_ulogic;
variable mask : std_ulogic_vector(63 downto 0);
begin
n := to_integer(unsigned(sh));
-- what about n = 0?
mask := (others => '0');
for i in 0 to 63 loop
if i < n then
mask(i) := '1';
end if;
end loop;
carry := '0' when (rs and mask) = (63 downto 0 => '0') else rs(63);
return carry & std_ulogic_vector(shift_right(signed(rs), n));
end;
function ppc_srad (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable n : integer;
variable carry: std_ulogic;
variable mask : std_ulogic_vector(63 downto 0);
begin
n := to_integer(unsigned(rb(6 downto 0)));
-- what about n = 0?
mask := (others => '0');
for i in 0 to 63 loop
if i < n then
mask(i) := '1';
end if;
end loop;
carry := '0' when (rs and mask) = (63 downto 0 => '0') else rs(63);
return carry & std_ulogic_vector(shift_right(signed(rs), n));
end;
-- Not sure how to better communicate the top 64 bits of the result is unused
function ppc_mulld (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp: signed(127 downto 0);
begin
tmp := signed(ra) * signed(rb);
return std_ulogic_vector(tmp(63 downto 0));
end;
-- Not sure how to better communicate the top 64 bits of the result is unused
function ppc_mulhd (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp: signed(127 downto 0);
begin
tmp := signed(ra) * signed(rb);
return std_ulogic_vector(tmp(127 downto 64));
end;
-- Not sure how to better communicate the top 64 bits of the result is unused
function ppc_mulhdu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp: unsigned(127 downto 0);
begin
tmp := unsigned(ra) * unsigned(rb);
return std_ulogic_vector(tmp(127 downto 64));
end;
-- Not sure how to better communicate the top 16 bits of the result is unused
function ppc_mulli (ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector is
variable tmp: signed(79 downto 0);
begin
tmp := signed(ra) * signed(si);
return std_ulogic_vector(tmp(63 downto 0));
end;
function ppc_mullw (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(signed(ra(31 downto 0)) * signed(rb(31 downto 0)));
end;
function ppc_mulhw (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp: signed(63 downto 0);
begin
tmp := signed(ra(31 downto 0)) * signed(rb(31 downto 0));
return std_ulogic_vector(tmp(63 downto 32)) & std_ulogic_vector(tmp(63 downto 32));
end;
function ppc_mulhwu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp: unsigned(63 downto 0);
begin
tmp := unsigned(ra(31 downto 0)) * unsigned(rb(31 downto 0));
return std_ulogic_vector(tmp(63 downto 32)) & std_ulogic_vector(tmp(63 downto 32));
end;
function ppc_cmpi (l: std_ulogic; ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0);
so: std_ulogic) return std_ulogic_vector is
variable tmp: signed(ra'range);
begin
tmp := signed(ra);
if l = '0' then
tmp := resize(signed(ra(31 downto 0)), tmp'length);
end if;
return ppc_signed_compare(tmp, resize(signed(si), tmp'length), so);
end;
function ppc_cmp (l: std_ulogic; ra, rb: std_ulogic_vector(63 downto 0);
so: std_ulogic) return std_ulogic_vector is
variable tmpa, tmpb: signed(ra'range);
begin
tmpa := signed(ra);
tmpb := signed(rb);
if l = '0' then
tmpa := resize(signed(ra(31 downto 0)), ra'length);
tmpb := resize(signed(rb(31 downto 0)), ra'length);
end if;
return ppc_signed_compare(tmpa, tmpb, so);
end;
function ppc_cmpli (l: std_ulogic; ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0);
so: std_ulogic) return std_ulogic_vector is
variable tmp: unsigned(ra'range);
begin
tmp := unsigned(ra);
if l = '0' then
tmp := resize(unsigned(ra(31 downto 0)), tmp'length);
end if;
return ppc_unsigned_compare(tmp, resize(unsigned(si), tmp'length), so);
end;
function ppc_cmpl (l: std_ulogic; ra, rb: std_ulogic_vector(63 downto 0);
so: std_ulogic) return std_ulogic_vector is
variable tmpa, tmpb: unsigned(ra'range);
begin
tmpa := unsigned(ra);
tmpb := unsigned(rb);
if l = '0' then
tmpa := resize(unsigned(ra(31 downto 0)), ra'length);
tmpb := resize(unsigned(rb(31 downto 0)), ra'length);
end if;
return ppc_unsigned_compare(tmpa, tmpb, so);
end;
function ppc_cmpb (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable ret: std_ulogic_vector (rs'range);
variable hi: integer;
variable lo: integer;
begin
for i in 1 to 8 loop
hi := (8*i)-1;
lo := 8*(i-1);
ret(hi downto lo) := cmp_one_byte(rs(hi downto lo), rb(hi downto lo));
end loop;
return ret;
end;
-- Not synthesizable
function ppc_divw (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp: signed(31 downto 0);
begin
tmp := signed(ra(31 downto 0)) / signed(rb(31 downto 0));
return (63 downto 32 => '0') & std_ulogic_vector(tmp);
end;
function ppc_divdu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp: unsigned(63 downto 0) := (others => '0');
begin
if unsigned(rb) /= 0 then
tmp := unsigned(ra) / unsigned(rb);
end if;
return std_ulogic_vector(tmp);
end;
function ppc_divd (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp: signed(63 downto 0) := (others => '0');
begin
if signed(rb) /= 0 then
tmp := signed(ra) / signed(rb);
end if;
return std_ulogic_vector(tmp);
end;
function ppc_divwu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable tmp: unsigned(31 downto 0) := (others => '0');
begin
if unsigned(rb(31 downto 0)) /= 0 then
tmp := unsigned(ra(31 downto 0)) / unsigned(rb(31 downto 0));
end if;
return std_ulogic_vector(resize(tmp, ra'length));
end;
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
variable crfield: integer;
variable crbit_match: std_ulogic;
variable ctr_not_zero: std_ulogic;
variable ctr_ok: std_ulogic;
variable cond_ok: std_ulogic;
variable ret: integer;
begin
crfield := to_integer(unsigned(bi));
-- BE bit numbering
crbit_match := '1' when cr(31-crfield) = bo(4-1) else '0';
-- We check this before it is decremented
ctr_not_zero := '1' when ctr /= x"0000000000000001" else '0';
ctr_ok := bo(4-2) or (ctr_not_zero xor bo(4-3));
cond_ok := bo(4-0) or crbit_match;
if ctr_ok = '1' and cond_ok = '1' then
ret := 1;
else
ret := 0;
end if;
return ret;
end;
end package body ppc_fx_insns;