Implement CRNOR and friends
authorTom Vijlbrief <tvijlbrief@gmail.com>
Fri, 3 Jan 2020 14:25:00 +0000 (15:25 +0100)
committerTom Vijlbrief <tvijlbrief@gmail.com>
Mon, 6 Jan 2020 10:09:14 +0000 (11:09 +0100)
Signed-off-by: Tom Vijlbrief <tvijlbrief@gmail.com>
decode1.vhdl
execute1.vhdl
insn_helpers.vhdl

index b4e7d260ffe91cb3816fa4c235da95f6bcf20454..51a2643a5cdbb6b035e49c0f88d1f041d778673c 100644 (file)
@@ -84,14 +84,14 @@ architecture behaviour of decode1 is
                 2#1000010000# => '1', -- bcctr
                 2#0000010000# => '1', -- bclr
                 2#1000110000# => '0', -- bctar
-                2#0100000001# => '0', -- crand
-                2#0010000001# => '0', -- crandc
-                2#0100100001# => '0', -- creqv
-                2#0011100001# => '0', -- crnand
-                2#0000100001# => '0', -- crnor
-                2#0111000001# => '0', -- cror
-                2#0011000001# => '0', -- crorc
-                2#0110100001# => '0', -- crxor
+                2#0100000001# => '1', -- crand
+                2#0010000001# => '1', -- crandc
+                2#0100100001# => '1', -- creqv
+                2#0011100001# => '1', -- crnand
+                2#0000100001# => '1', -- crnor
+                2#0111000001# => '1', -- cror
+                2#0110100001# => '1', -- crorc
+                2#0011000001# => '1', -- crxor
                 2#0010010110# => '1', -- isync
                 2#0000000000# => '1', -- mcrf
                 others => '0'
@@ -101,7 +101,7 @@ architecture behaviour of decode1 is
        constant decode_op_19_array : op_19_subop_array_t := (
                --                 unit     internal      in1         in2          in3   out   CR   CR   inv  inv  cry   cry  ldst  BR   sgn  upd  rsrv 32b  sgn  rc    lk   sgl
                --                               op                                            in   out   A   out  in    out  len        ext                                 pipe
-                -- mcrf; cr logical ops not implemented yet
+                -- mcrf; and cr logical ops
                2#000#    =>       (ALU,    OP_MCRF,      NONE,       NONE,        NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'),
                -- addpcis not implemented yet
                2#001#    =>       (ALU,    OP_ILLEGAL,   NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC,   '0', '1'),
index 9b14088dabee3ceaede87092a6bdfad263cfa559..421bccb7c901306179a3cfb320b8543b723f9526 100644 (file)
@@ -152,6 +152,10 @@ begin
        variable sh32, mb32, me32 : std_ulogic_vector(4 downto 0);
        variable bo, bi : std_ulogic_vector(4 downto 0);
        variable bf, bfa : std_ulogic_vector(2 downto 0);
+       variable cr_op : std_ulogic_vector(9 downto 0);
+       variable bt, ba, bb : std_ulogic_vector(4 downto 0);
+       variable btnum, banum, bbnum : integer range 0 to 31;
+       variable crresult : std_ulogic;
        variable l : std_ulogic;
        variable next_nia : std_ulogic_vector(63 downto 0);
         variable carry_32, carry_64 : std_ulogic;
@@ -335,24 +339,64 @@ begin
                end if;
                result_en := '1';
            when OP_MCRF =>
-               bf := insn_bf(e_in.insn);
-               bfa := insn_bfa(e_in.insn);
-               v.e.write_cr_enable := '1';
-               crnum := to_integer(unsigned(bf));
-               scrnum := to_integer(unsigned(bfa));
-               v.e.write_cr_mask := num_to_fxm(crnum);
-               for i in 0 to 7 loop
-                   lo := (7-i)*4;
-                   hi := lo + 3;
-                   if i = scrnum then
-                       newcrf := e_in.cr(hi downto lo);
-                   end if;
-               end loop;
-               for i in 0 to 7 loop
-                   lo := i*4;
-                   hi := lo + 3;
-                   v.e.write_cr_data(hi downto lo) := newcrf;
-               end loop;
+               cr_op := insn_cr(e_in.insn);
+               report "CR OP " & to_hstring(cr_op);
+               if cr_op(0) = '0' then -- MCRF
+                   bf := insn_bf(e_in.insn);
+                   bfa := insn_bfa(e_in.insn);
+                   v.e.write_cr_enable := '1';
+                   crnum := to_integer(unsigned(bf));
+                   scrnum := to_integer(unsigned(bfa));
+                   v.e.write_cr_mask := num_to_fxm(crnum);
+                   for i in 0 to 7 loop
+                       lo := (7-i)*4;
+                       hi := lo + 3;
+                       if i = scrnum then
+                           newcrf := e_in.cr(hi downto lo);
+                       end if;
+                   end loop;
+                   for i in 0 to 7 loop
+                       lo := i*4;
+                       hi := lo + 3;
+                       v.e.write_cr_data(hi downto lo) := newcrf;
+                   end loop;
+               else
+                   v.e.write_cr_enable := '1';
+                   bt := insn_bt(e_in.insn);
+                   ba := insn_ba(e_in.insn);
+                   bb := insn_bb(e_in.insn);
+                   btnum := 31 - to_integer(unsigned(bt));
+                   banum := 31 - to_integer(unsigned(ba));
+                   bbnum := 31 - to_integer(unsigned(bb));
+                   case cr_op(8 downto 5) is
+                   when "1001" => -- CREQV
+                       crresult := not(e_in.cr(banum) xor e_in.cr(bbnum));
+                   when "0111" => -- CRNAND
+                       crresult := not(e_in.cr(banum) and e_in.cr(bbnum));
+                   when "0100" => -- CRANDC
+                       crresult := (e_in.cr(banum) and not e_in.cr(bbnum));
+                   when "1000" => -- CRAND
+                       crresult := (e_in.cr(banum) and e_in.cr(bbnum));
+                   when "0001" => -- CRNOR
+                       crresult := not(e_in.cr(banum) or e_in.cr(bbnum));
+                   when "1101" => -- CRORC
+                       crresult := (e_in.cr(banum) or not e_in.cr(bbnum));
+                   when "0110" => -- CRXOR
+                       crresult := (e_in.cr(banum) xor e_in.cr(bbnum));
+                   when "1110" => -- CROR
+                       crresult := (e_in.cr(banum) or e_in.cr(bbnum));
+                   when others =>
+                       report "BAD CR?";
+                   end case;
+                   v.e.write_cr_mask := num_to_fxm((31-btnum) / 4);
+                   for i in 0 to 31 loop
+                       if i = btnum then
+                           v.e.write_cr_data(i) := crresult;
+                       else
+                           v.e.write_cr_data(i) := e_in.cr(i);
+                       end if;
+                   end loop;
+               end if;
            when OP_MFSPR =>
                if is_fast_spr(e_in.read_reg1) then
                    result := e_in.read_data1;
index f58dacdccec7f0ee531994c5edbf2c7f208c9bba..88120445484eec7c63b590f53d247df32c84e42b 100644 (file)
@@ -20,6 +20,10 @@ package insn_helpers is
     function insn_bd (insn_in : std_ulogic_vector) return std_ulogic_vector;
     function insn_bf (insn_in : std_ulogic_vector) return std_ulogic_vector;
     function insn_bfa (insn_in : std_ulogic_vector) return std_ulogic_vector;
+    function insn_cr (insn_in : std_ulogic_vector) return std_ulogic_vector;
+    function insn_bt (insn_in : std_ulogic_vector) return std_ulogic_vector;
+    function insn_ba (insn_in : std_ulogic_vector) return std_ulogic_vector;
+    function insn_bb (insn_in : std_ulogic_vector) return std_ulogic_vector;
     function insn_fxm (insn_in : std_ulogic_vector) return std_ulogic_vector;
     function insn_bo (insn_in : std_ulogic_vector) return std_ulogic_vector;
     function insn_bi (insn_in : std_ulogic_vector) return std_ulogic_vector;
@@ -124,6 +128,26 @@ package body insn_helpers is
         return insn_in(20 downto 18);
     end;
 
+    function insn_cr (insn_in : std_ulogic_vector) return std_ulogic_vector is
+    begin
+        return insn_in(10 downto 1);
+    end;
+    
+    function insn_bb (insn_in : std_ulogic_vector) return std_ulogic_vector is
+    begin
+        return insn_in(15 downto 11);
+    end;
+
+    function insn_ba (insn_in : std_ulogic_vector) return std_ulogic_vector is
+    begin
+        return insn_in(20 downto 16);
+    end;
+
+    function insn_bt (insn_in : std_ulogic_vector) return std_ulogic_vector is
+    begin
+        return insn_in(25 downto 21);
+    end;
+
     function insn_fxm (insn_in : std_ulogic_vector) return std_ulogic_vector is
     begin
         return insn_in(19 downto 12);