Add Tercel PHY reset synchronization
[microwatt.git] / ppc_fx_insns.vhdl
index 9b23bc14bf68f6b6a0c19531abe95be8a6fa8462..c34a8849db743c09545a4ceb968e45a9cbb6f524 100644 (file)
@@ -77,21 +77,25 @@ package ppc_fx_insns is
        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)) return std_ulogic_vector;
-       function ppc_cmp (l: std_ulogic; ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
-       function ppc_cmpli (l: std_ulogic; ra: std_ulogic_vector(63 downto 0); si: std_ulogic_vector(15 downto 0)) return std_ulogic_vector;
-       function ppc_cmpl (l: std_ulogic; 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_cmpeqb (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
+        function ppc_cmprb (ra, rb: std_ulogic_vector(63 downto 0); l: std_ulogic) 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_b (nia: std_ulogic_vector(63 downto 0); bd: std_ulogic_vector(23 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;
-       function ppc_bcctr_taken(bo, bi: std_ulogic_vector(4 downto 0); cr: std_ulogic_vector(31 downto 0)) return integer;
+       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 std_ulogic;
 end package ppc_fx_insns;
 
 package body ppc_fx_insns is
@@ -339,10 +343,17 @@ package body ppc_fx_insns is
                tmp2 := (others => '0');
                if hi < lo then
                        -- Mask wraps around
-                       tmp2(63 downto lo) := tmp1(63 downto lo);
-                       tmp2(hi downto 0) := tmp1(hi downto 0);
+                       for i in 0 to 63 loop
+                               if i <= hi or i >= lo then
+                                       tmp2(i) := tmp1(i);
+                               end if;
+                       end loop;
                else
-                       tmp2(hi downto lo) := tmp1(hi downto lo);
+                       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;
@@ -360,10 +371,17 @@ package body ppc_fx_insns is
                tmp2 := (others => '0');
                if hi < lo then
                        -- Mask wraps around
-                       tmp2(63 downto lo) := tmp1(63 downto lo);
-                       tmp2(hi downto 0) := tmp1(hi downto 0);
+                       for i in 0 to 63 loop
+                               if i <= hi or i >= lo then
+                                       tmp2(i) := tmp1(i);
+                               end if;
+                       end loop;
                else
-                       tmp2(hi downto lo) := tmp1(hi downto lo);
+                       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;
@@ -379,10 +397,17 @@ package body ppc_fx_insns is
                tmp2 := ra;
                if hi < lo then
                        -- Mask wraps around
-                       tmp2(63 downto lo) := tmp1(63 downto lo);
-                       tmp2(hi downto 0) := tmp1(hi downto 0);
+                       for i in 0 to 63 loop
+                               if i <= hi or i >= lo then
+                                       tmp2(i) := tmp1(i);
+                               end if;
+                       end loop;
                else
-                       tmp2(hi downto lo) := tmp1(hi downto lo);
+                       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;
@@ -394,7 +419,11 @@ package body ppc_fx_insns is
                hi := 63-to_integer(unsigned(mb));
                tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), to_integer(unsigned(sh))));
                tmp2 := (others => '0');
-               tmp2(hi downto 0) := tmp1(hi downto 0);
+               for i in 0 to 63 loop
+                       if i <= hi then
+                               tmp2(i) := tmp1(i);
+                       end if;
+               end loop;
                return tmp2;
        end;
 
@@ -405,7 +434,11 @@ package body ppc_fx_insns is
                lo := 63-to_integer(unsigned(me));
                tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), to_integer(unsigned(sh))));
                tmp2 := (others => '0');
-               tmp2(63 downto lo) := tmp1(63 downto lo);
+               for i in 0 to 63 loop
+                       if i >= lo then
+                               tmp2(i) := tmp1(i);
+                       end if;
+               end loop;
                return tmp2;
        end;
 
@@ -419,10 +452,17 @@ package body ppc_fx_insns is
                tmp2 := (others => '0');
                if hi < lo then
                        -- Mask wraps around
-                       tmp2(63 downto lo) := tmp1(63 downto lo);
-                       tmp2(hi downto 0) := tmp1(hi downto 0);
+                       for i in 0 to 63 loop
+                               if i <= hi or i >= lo then
+                                       tmp2(i) := tmp1(i);
+                               end if;
+                       end loop;
                else
-                       tmp2(hi downto lo) := tmp1(hi downto lo);
+                       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;
@@ -434,7 +474,11 @@ package body ppc_fx_insns is
                hi := 63-to_integer(unsigned(mb));
                tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), to_integer(unsigned(rb(5 downto 0)))));
                tmp2 := (others => '0');
-               tmp2(hi downto 0) := tmp1(hi downto 0);
+               for i in 0 to 63 loop
+                       if i <= hi then
+                               tmp2(i) := tmp1(i);
+                       end if;
+               end loop;
                return tmp2;
        end;
 
@@ -445,7 +489,11 @@ package body ppc_fx_insns is
                lo := 63-to_integer(unsigned(me));
                tmp1 := std_ulogic_vector(rotate_left(unsigned(rs), to_integer(unsigned(rb(5 downto 0)))));
                tmp2 := (others => '0');
-               tmp2(63 downto lo) := tmp1(63 downto lo);
+               for i in 0 to 63 loop
+                       if i >= lo then
+                               tmp2(i) := tmp1(i);
+                       end if;
+               end loop;
                return tmp2;
        end;
 
@@ -459,10 +507,17 @@ package body ppc_fx_insns is
                tmp2 := ra;
                if hi < lo then
                        -- Mask wraps around
-                       tmp2(63 downto lo) := tmp1(63 downto lo);
-                       tmp2(hi downto 0) := tmp1(hi downto 0);
+                       for i in 0 to 63 loop
+                               if i <= hi or i >= lo then
+                                       tmp2(i) := tmp1(i);
+                               end if;
+                       end loop;
                else
-                       tmp2(hi downto lo) := tmp1(hi downto lo);
+                       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;
@@ -490,12 +545,19 @@ package body ppc_fx_insns is
        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?
-               carry := or rs(n-1 downto 0) and rs(31);
+               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;
@@ -503,13 +565,19 @@ package body ppc_fx_insns is
        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?
-               carry := or rs(n-1 downto 0) and rs(31);
-
+               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;
 
@@ -530,10 +598,17 @@ package body ppc_fx_insns is
        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?
-               carry := or rs(n-1 downto 0) and rs(63);
+               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;
@@ -541,10 +616,17 @@ package body ppc_fx_insns is
        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?
-               carry := or rs(n-1 downto 0) and rs(63);
+               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;
@@ -600,7 +682,8 @@ package body ppc_fx_insns is
                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)) return std_ulogic_vector is
+       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);
@@ -608,10 +691,11 @@ package body ppc_fx_insns is
                        tmp := resize(signed(ra(31 downto 0)), tmp'length);
                end if;
 
-               return ppc_signed_compare(tmp, resize(signed(si), tmp'length));
+               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)) return std_ulogic_vector is
+       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);
@@ -621,10 +705,11 @@ package body ppc_fx_insns is
                        tmpb := resize(signed(rb(31 downto 0)), ra'length);
                end if;
 
-               return ppc_signed_compare(tmpa, tmpb);
+               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)) return std_ulogic_vector is
+       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);
@@ -632,10 +717,11 @@ package body ppc_fx_insns is
                        tmp := resize(unsigned(ra(31 downto 0)), tmp'length);
                end if;
 
-               return ppc_unsigned_compare(tmp, resize(unsigned(si), tmp'length));
+               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)) return std_ulogic_vector is
+       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);
@@ -645,7 +731,7 @@ package body ppc_fx_insns is
                        tmpb := resize(unsigned(rb(31 downto 0)), ra'length);
                end if;
 
-               return ppc_unsigned_compare(tmpa, tmpb);
+               return ppc_unsigned_compare(tmpa, tmpb, so);
        end;
 
        function ppc_cmpb (rs, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
@@ -662,6 +748,34 @@ package body ppc_fx_insns is
                return ret;
        end;
 
+        function ppc_cmpeqb (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
+            variable match: std_ulogic;
+            variable j: integer;
+        begin
+            match := '0';
+            for i in 0 to 7 loop
+                j := i * 8;
+                if ra(7 downto 0) = rb(j + 7 downto j) then
+                    match := '1';
+                end if;
+            end loop;
+            return '0' & match & "00";
+        end;
+
+        function ppc_cmprb (ra, rb: std_ulogic_vector(63 downto 0); l: std_ulogic) return std_ulogic_vector is
+            variable match: std_ulogic;
+            variable v: unsigned(7 downto 0);
+        begin
+            match := '0';
+            v := unsigned(ra(7 downto 0));
+            if v >= unsigned(rb(7 downto 0)) and v <= unsigned(rb(15 downto 8)) then
+                match := '1';
+            elsif l = '1' and v >= unsigned(rb(23 downto 16)) and v <= unsigned(rb(31 downto 24)) then
+                match := '1';
+            end if;
+            return '0' & match & "00";
+        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);
@@ -701,18 +815,12 @@ package body ppc_fx_insns is
                return std_ulogic_vector(resize(tmp, ra'length));
        end;
 
-       function ppc_b (nia: std_ulogic_vector(63 downto 0); bd: std_ulogic_vector(23 downto 0)) return std_ulogic_vector is
-       begin
-               return std_ulogic_vector(signed(nia) + signed(bd & "00"));
-       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
+       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 std_ulogic 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
@@ -721,29 +829,7 @@ package body ppc_fx_insns is
                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;
+                return ctr_ok and cond_ok;
        end;
 
-       function ppc_bcctr_taken(bo, bi: std_ulogic_vector(4 downto 0); cr: std_ulogic_vector(31 downto 0)) return integer is
-               variable crfield: integer;
-               variable crbit_match: 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';
-               cond_ok := bo(4-0) or crbit_match;
-               if cond_ok = '1' then
-                       ret := 1;
-               else
-                       ret := 0;
-               end if;
-               return ret;
-       end;
 end package body ppc_fx_insns;