execute1: Move CR result to data path process
[microwatt.git] / execute1.vhdl
index cfbb2788128fae4ea7c334a9a0dbcd752338c956..0b9ba0e4058f19ae29092e17d90807bf4553ebcc 100644 (file)
@@ -119,10 +119,11 @@ architecture behaviour of execute1 is
     signal overflow_32 : std_ulogic;
     signal overflow_64 : std_ulogic;
 
-    signal cmprb_result : std_ulogic_vector(3 downto 0);
-    signal cmpeqb_result : std_ulogic_vector(3 downto 0);
     signal trapval : std_ulogic_vector(4 downto 0);
 
+    signal write_cr_mask : std_ulogic_vector(7 downto 0);
+    signal write_cr_data : std_ulogic_vector(31 downto 0);
+
     -- multiply signals
     signal x_to_multiply: MultiplyInputType;
     signal multiply_to_x: MultiplyOutputType;
@@ -169,7 +170,6 @@ architecture behaviour of execute1 is
     begin
        e.xerc.ca32 := carry32;
        e.xerc.ca := carry;
-       e.write_xerc_enable := '1';
     end;
 
     procedure set_ov(e: inout Execute1ToWritebackType;
@@ -181,7 +181,6 @@ architecture behaviour of execute1 is
        if ov = '1' then
            e.xerc.so := '1';
        end if;
-       e.write_xerc_enable := '1';
     end;
 
     function calc_ov(msb_a : std_ulogic; msb_b: std_ulogic;
@@ -360,7 +359,6 @@ begin
        variable darn : std_ulogic_vector(63 downto 0);
        variable setb_result : std_ulogic_vector(63 downto 0);
        variable mfcr_result : std_ulogic_vector(63 downto 0);
-       variable crnum : crnum_t;
        variable lo, hi : integer;
        variable l : std_ulogic;
         variable zerohi, zerolo : std_ulogic;
@@ -368,7 +366,16 @@ begin
         variable a_lt : std_ulogic;
         variable a_lt_lo : std_ulogic;
         variable a_lt_hi : std_ulogic;
-       variable bfa : std_ulogic_vector(2 downto 0);
+       variable newcrf : std_ulogic_vector(3 downto 0);
+       variable bf, bfa : std_ulogic_vector(2 downto 0);
+       variable crnum : crnum_t;
+       variable scrnum : crnum_t;
+        variable cr_operands : std_ulogic_vector(1 downto 0);
+       variable crresult : std_ulogic;
+       variable bt, ba, bb : std_ulogic_vector(4 downto 0);
+        variable btnum : integer range 0 to 3;
+       variable banum, bbnum : integer range 0 to 31;
+        variable j : integer;
     begin
         -- Main adder
         if e_in.invert_a = '0' then
@@ -591,24 +598,77 @@ begin
             end if;
         end if;
 
-        cmprb_result <= ppc_cmprb(a_in, b_in, insn_l(e_in.insn));
-        cmpeqb_result <= ppc_cmpeqb(a_in, b_in);
+        -- CR result mux
+        bf := insn_bf(e_in.insn);
+        crnum := to_integer(unsigned(bf));
+        newcrf := (others => '0');
+        case current.sub_select is
+            when "000" =>
+                -- CMP and CMPL instructions
+                if e_in.is_signed = '1' then
+                    newcrf := trapval(4 downto 2) & xerc_in.so;
+                else
+                    newcrf := trapval(1 downto 0) & trapval(2) & xerc_in.so;
+                end if;
+            when "001" =>
+                newcrf := ppc_cmprb(a_in, b_in, insn_l(e_in.insn));
+            when "010" =>
+                newcrf := ppc_cmpeqb(a_in, b_in);
+            when "011" =>
+                if current.insn(1) = '1' then
+                    -- CR logical instructions
+                    j := (7 - crnum) * 4;
+                    newcrf := cr_in(j + 3 downto j);
+                    bt := insn_bt(e_in.insn);
+                    ba := insn_ba(e_in.insn);
+                    bb := insn_bb(e_in.insn);
+                    btnum := 3 - to_integer(unsigned(bt(1 downto 0)));
+                    banum := 31 - to_integer(unsigned(ba));
+                    bbnum := 31 - to_integer(unsigned(bb));
+                    -- Bits 6-9 of the instruction word give the truth table
+                    -- of the requested logical operation
+                    cr_operands := cr_in(banum) & cr_in(bbnum);
+                    crresult := e_in.insn(6 + to_integer(unsigned(cr_operands)));
+                    for i in 0 to 3 loop
+                        if i = btnum then
+                            newcrf(i) := crresult;
+                        end if;
+                    end loop;
+                else
+                    -- MCRF
+                    bfa := insn_bfa(e_in.insn);
+                    scrnum := to_integer(unsigned(bfa));
+                    j := (7 - scrnum) * 4;
+                    newcrf := cr_in(j + 3 downto j);
+                end if;
+            when "100" =>
+                -- MCRXRX
+                newcrf := xerc_in.ov & xerc_in.ca & xerc_in.ov32 & xerc_in.ca32;
+            when others =>
+        end case;
+        if current.insn_type = OP_MTCRF then
+            if e_in.insn(20) = '0' then
+                -- mtcrf
+                write_cr_mask <= insn_fxm(e_in.insn);
+            else
+                -- mtocrf: We require one hot priority encoding here
+                crnum := fxm_to_num(insn_fxm(e_in.insn));
+                write_cr_mask <= num_to_fxm(crnum);
+            end if;
+            write_cr_data <= c_in(31 downto 0);
+        else
+            write_cr_mask <= num_to_fxm(crnum);
+            write_cr_data <= newcrf & newcrf & newcrf & newcrf &
+                             newcrf & newcrf & newcrf & newcrf;
+        end if;
+
     end process;
 
     execute1_1: process(all)
        variable v : reg_type;
-       variable newcrf : std_ulogic_vector(3 downto 0);
-       variable crnum : crnum_t;
-       variable scrnum : crnum_t;
        variable lo, hi : integer;
        variable sh, mb, me : std_ulogic_vector(5 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 cr_operands : std_ulogic_vector(1 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 overflow : std_ulogic;
         variable lv : Execute1ToLoadstore1Type;
        variable irq_valid : std_ulogic;
@@ -625,7 +685,6 @@ begin
         variable f : Execute1ToFetch1Type;
         variable fv : Execute1ToFPUType;
     begin
-       newcrf := (others => '0');
         is_branch := '0';
         is_direct_branch := '0';
         taken_branch := '0';
@@ -800,27 +859,12 @@ begin
                     else
                         v.e.xerc.ov := carry_64;
                         v.e.xerc.ov32 := carry_32;
-                        v.e.write_xerc_enable := '1';
                     end if;
                 end if;
                 if e_in.oe = '1' then
                     set_ov(v.e, overflow_64, overflow_32);
                 end if;
             when OP_CMP =>
-                -- CMP and CMPL instructions
-                if e_in.is_signed = '1' then
-                    newcrf := trapval(4 downto 2) & xerc_in.so;
-                else
-                    newcrf := trapval(1 downto 0) & trapval(2) & xerc_in.so;
-                end if;
-                bf := insn_bf(e_in.insn);
-                crnum := to_integer(unsigned(bf));
-                v.e.write_cr_mask := num_to_fxm(crnum);
-                for i in 0 to 7 loop
-                    lo := i*4;
-                    hi := lo + 3;
-                    v.e.write_cr_data(hi downto lo) := newcrf;
-                end loop;
             when OP_TRAP =>
                 -- trap instructions (tw, twi, td, tdi)
                 v.vector := 16#700#;
@@ -833,19 +877,7 @@ begin
                 end if;
             when OP_ADDG6S =>
             when OP_CMPRB =>
-                newcrf := cmprb_result;
-                bf := insn_bf(e_in.insn);
-                crnum := to_integer(unsigned(bf));
-                v.e.write_cr_mask := num_to_fxm(crnum);
-                v.e.write_cr_data := newcrf & newcrf & newcrf & newcrf &
-                                     newcrf & newcrf & newcrf & newcrf;
             when OP_CMPEQB =>
-                newcrf := cmpeqb_result;
-                bf := insn_bf(e_in.insn);
-                crnum := to_integer(unsigned(bf));
-                v.e.write_cr_mask := num_to_fxm(crnum);
-                v.e.write_cr_data := newcrf & newcrf & newcrf & newcrf &
-                                     newcrf & newcrf & newcrf & newcrf;
             when OP_AND | OP_OR | OP_XOR | OP_POPCNT | OP_PRTY | OP_CMPB | OP_EXTS |
                     OP_BPERM | OP_BCD =>
 
@@ -911,53 +943,8 @@ begin
                 v.cntz_in_progress := '1';
                 v.busy := '1';
            when OP_ISEL =>
-           when OP_CROP =>
-               cr_op := insn_cr(e_in.insn);
-               if cr_op(0) = '0' then -- MCRF
-                   bf := insn_bf(e_in.insn);
-                   bfa := insn_bfa(e_in.insn);
-                   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 := cr_in(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
-                   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));
-                    -- Bits 5-8 of cr_op give the truth table of the requested
-                    -- logical operation
-                    cr_operands := cr_in(banum) & cr_in(bbnum);
-                    crresult := cr_op(5 + to_integer(unsigned(cr_operands)));
-                   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) := cr_in(i);
-                       end if;
-                   end loop;
-               end if;
+            when OP_CROP =>
             when OP_MCRXRX =>
-                newcrf := xerc_in.ov & xerc_in.ca & xerc_in.ov32 & xerc_in.ca32;
-                bf := insn_bf(e_in.insn);
-                crnum := to_integer(unsigned(bf));
-                v.e.write_cr_mask := num_to_fxm(crnum);
-                v.e.write_cr_data := newcrf & newcrf & newcrf & newcrf &
-                                     newcrf & newcrf & newcrf & newcrf;
             when OP_DARN =>
            when OP_MFMSR =>
            when OP_MFSPR =>
@@ -1007,15 +994,6 @@ begin
 
            when OP_MFCR =>
            when OP_MTCRF =>
-               if e_in.insn(20) = '0' then
-                   -- mtcrf
-                   v.e.write_cr_mask := insn_fxm(e_in.insn);
-               else
-                   -- mtocrf: We require one hot priority encoding here
-                   crnum := fxm_to_num(insn_fxm(e_in.insn));
-                   v.e.write_cr_mask := num_to_fxm(crnum);
-               end if;
-               v.e.write_cr_data := c_in(31 downto 0);
             when OP_MTMSRD =>
                 if e_in.insn(16) = '1' then
                     -- just update EE and RI
@@ -1050,7 +1028,6 @@ begin
                        v.e.xerc.ca := c_in(63-34);
                        v.e.xerc.ov32 := c_in(63-44);
                        v.e.xerc.ca32 := c_in(63-45);
-                       v.e.write_xerc_enable := '1';
                    end if;
                else
                    -- slow spr
@@ -1170,7 +1147,6 @@ begin
                     v.mul_finish := '1';
                     v.busy := '1';
                 else
-                    v.e.write_xerc_enable := current.oe;
                     -- We must test oe because the RC update code in writeback
                     -- will use the xerc value to set CR0:SO so we must not clobber
                     -- xerc if OE wasn't set.
@@ -1190,7 +1166,6 @@ begin
            end if;
         elsif r.mul_finish = '1' then
             hold_wr_data := '1';
-            v.e.write_xerc_enable := current.oe;
             v.e.xerc.ov := multiply_to_x.overflow;
             v.e.xerc.ov32 := multiply_to_x.overflow;
             if multiply_to_x.overflow = '1' then
@@ -1268,8 +1243,11 @@ begin
         end if;
         v.e.write_reg := current.write_reg;
        v.e.write_enable := current.write_reg_enable and v.e.valid and not exception;
-        v.e.write_cr_enable := current.output_cr and v.e.valid and not exception;
         v.e.rc := current.rc and v.e.valid and not exception;
+        v.e.write_cr_data := write_cr_data;
+        v.e.write_cr_mask := write_cr_mask;
+        v.e.write_cr_enable := current.output_cr and v.e.valid and not exception;
+        v.e.write_xerc_enable := current.output_xer and v.e.valid and not exception;
 
         bypass_data.tag.valid <= current.instr_tag.valid and current.write_reg_enable and v.e.valid;
         bypass_data.tag.tag <= current.instr_tag.tag;