Move LR, CTR and TAR out of the register file
authorPaul Mackerras <paulus@ozlabs.org>
Tue, 12 Jul 2022 01:20:17 +0000 (11:20 +1000)
committerPaul Mackerras <paulus@ozlabs.org>
Fri, 22 Jul 2022 12:20:35 +0000 (22:20 +1000)
By putting CTR on the odd side and LR and TAR on the even side, we can
read and write CTR for bdnz-style instructions in parallel with
reading LR or TAR for indirect branches and writing LR for branches
with LK=1.  Thus we don't need to double up any of these instructions,
giving a simplification in decode2.

We now have logic for printing LR and CTR at the end of a simulation
in execute1, in addition to the similar logic in register_file and
cr_file.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
common.vhdl
core.vhdl
decode1.vhdl
decode2.vhdl
execute1.vhdl
register_file.vhdl

index 74341d18d5dacdf5e3a3d59f5a643d1a44bab9e0..7df451b202917d74cd62b6af0d9034ec5cadb7c9 100644 (file)
@@ -132,12 +132,15 @@ package common is
     constant RAMSPR_SPRG0  : ramspr_index := 2;
     constant RAMSPR_SPRG2  : ramspr_index := 3;
     constant RAMSPR_HSPRG0 : ramspr_index := 4;
+    constant RAMSPR_LR     : ramspr_index := 5;         -- must equal RAMSPR_CTR
+    constant RAMSPR_TAR    : ramspr_index := 6;
     -- Odd half:
     constant RAMSPR_SRR1   : ramspr_index := 0;
     constant RAMSPR_HSRR1  : ramspr_index := 1;
     constant RAMSPR_SPRG1  : ramspr_index := 2;
     constant RAMSPR_SPRG3  : ramspr_index := 3;
     constant RAMSPR_HSPRG1 : ramspr_index := 4;
+    constant RAMSPR_CTR    : ramspr_index := 5;         -- must equal RAMSPR_LR
 
     type ram_spr_info is record
         index : ramspr_index;
@@ -322,7 +325,6 @@ package common is
        rc: std_ulogic;
        oe: std_ulogic;
        invert_a: std_ulogic;
-        addm1 : std_ulogic;
        invert_out: std_ulogic;
        input_carry: carry_in_t;
        output_carry: std_ulogic;
@@ -350,11 +352,12 @@ package common is
         ramspr_wraddr      : ramspr_index;
         ramspr_write_even  : std_ulogic;
         ramspr_write_odd   : std_ulogic;
+        dec_ctr : std_ulogic;
     end record;
     constant Decode2ToExecute1Init : Decode2ToExecute1Type :=
        (valid => '0', unit => NONE, fac => NONE, insn_type => OP_ILLEGAL, instr_tag => instr_tag_init,
          write_reg_enable => '0',
-         lr => '0', br_abs => '0', rc => '0', oe => '0', invert_a => '0', addm1 => '0',
+         lr => '0', br_abs => '0', rc => '0', oe => '0', invert_a => '0',
         invert_out => '0', input_carry => ZERO, output_carry => '0', input_cr => '0',
          output_cr => '0', output_xer => '0',
         is_32bit => '0', is_signed => '0', xerc => xerc_init, reserve => '0', br_pred => '0',
@@ -366,6 +369,7 @@ package common is
          spr_is_ram => '0',
          ramspr_even_rdaddr => 0, ramspr_odd_rdaddr => 0, ramspr_rd_odd => '0',
          ramspr_wraddr => 0, ramspr_write_even => '0', ramspr_write_odd => '0',
+         dec_ctr => '0',
          others => (others => '0'));
 
     type MultiplyInputType is record
@@ -780,25 +784,8 @@ package body common is
        return to_integer(unsigned(insn(15 downto 11) & insn(20 downto 16)));
     end;
     function fast_spr_num(spr: spr_num_t) return gspr_index_t is
-       variable n : integer range 0 to 31;
-       -- tmp variable introduced as workaround for VCS compilation
-       -- simulation was failing with subtype constraint mismatch error
-       -- see GitHub PR #173
-       variable tmp : std_ulogic_vector(4 downto 0);
     begin
-       case spr is
-       when SPR_LR =>
-           n := 0;              -- N.B. decode2 relies on this specific value
-       when SPR_CTR =>
-           n := 1;              -- N.B. decode2 relies on this specific value
-       when SPR_TAR =>
-           n := 13;
-       when others =>
-           n := 0;
-           return "0000000";
-       end case;
-       tmp := std_ulogic_vector(to_unsigned(n, 5));
-       return "01" & tmp;
+        return "0000000";
     end;
 
     function gspr_to_gpr(i: gspr_index_t) return gpr_index_t is
index b2f2704e13ea694d9012a661427af2602f5382e4..82c66b48717b642547fcb345e9e8c93664698e4d 100644 (file)
--- a/core.vhdl
+++ b/core.vhdl
@@ -138,6 +138,7 @@ architecture behave of core is
     signal rst_dbg     : std_ulogic;
     signal alt_reset_d : std_ulogic;
 
+    signal sim_ex_dump: std_ulogic;
     signal sim_cr_dump: std_ulogic;
 
     -- Debug actions
@@ -326,7 +327,7 @@ begin
             dbg_gpr_addr => dbg_gpr_addr,
             dbg_gpr_data => dbg_gpr_data,
            sim_dump => terminate,
-           sim_dump_done => sim_cr_dump,
+           sim_dump_done => sim_ex_dump,
             log_out => log_data(255 downto 184)
            );
 
@@ -347,6 +348,7 @@ begin
 
     execute1_0: entity work.execute1
         generic map (
+            SIM => SIM,
             EX1_BYPASS => EX1_BYPASS,
             HAS_FPU => HAS_FPU,
             HAS_SHORT_MULT => HAS_SHORT_MULT,
@@ -376,6 +378,8 @@ begin
             dc_events => dcache_events,
             ic_events => icache_events,
             terminate_out => terminate,
+            sim_dump => sim_ex_dump,
+            sim_dump_done => sim_cr_dump,
             log_out => log_data(134 downto 120),
             log_rd_addr => log_rd_addr,
             log_rd_data => log_rd_data,
index fd01d617a7d0b3e4eb67f1721e4a2577dec6d116..b6cea31b9879ccd9722a964374ad7b83271a5d72 100644 (file)
@@ -89,8 +89,8 @@ architecture behaviour of decode1 is
         28 =>       (ALU,  NONE, OP_AND,       NONE,       CONST_UI,    RS,   RA,   '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', ONE,  '0', '0', NONE), -- andi.
         29 =>       (ALU,  NONE, OP_AND,       NONE,       CONST_UI_HI, RS,   RA,   '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', ONE,  '0', '0', NONE), -- andis.
          0 =>       (ALU,  NONE, OP_ATTN,      NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- attn
-        18 =>       (ALU,  NONE, OP_B,         NONE,       CONST_LI,    NONE, SPR,  '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), -- b
-        16 =>       (ALU,  NONE, OP_BC,        SPR,        CONST_BD,    NONE, SPR , '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), -- bc
+        18 =>       (ALU,  NONE, OP_B,         NONE,       CONST_LI,    NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), -- b
+        16 =>       (ALU,  NONE, OP_BC,        NONE,       CONST_BD,    NONE, NONE, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), -- bc
         11 =>       (ALU,  NONE, OP_CMP,       RA,         CONST_SI,    NONE, NONE, '0', '1', '1', '0', ONE,  '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- cmpi
         10 =>       (ALU,  NONE, OP_CMP,       RA,         CONST_UI,    NONE, NONE, '0', '1', '1', '0', ONE,  '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cmpli
         34 =>       (LDST, NONE, OP_LOAD,      RA_OR_ZERO, CONST_SI,    NONE, RT,   '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lbz
@@ -177,7 +177,7 @@ architecture behaviour of decode1 is
         -- addpcis
         2#001#    =>       (ALU, NONE, OP_ADD,       CIA,        CONST_DXHI4, NONE, RT,   '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
         -- bclr, bcctr, bctar
-        2#100#    =>       (ALU, NONE, OP_BCREG,     SPR,        SPR,         NONE, SPR,  '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE),
+        2#100#    =>       (ALU, NONE, OP_BCREG,     NONE,       NONE,        NONE, SPR,  '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE),
         -- isync
         2#111#    =>       (ALU, NONE, OP_ISYNC,     NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
         -- rfid
@@ -530,6 +530,13 @@ architecture behaviour of decode1 is
     begin
         ret := (index => 0, isodd => '0', valid => '1');
         case sprn is
+            when SPR_LR =>
+                ret.index := RAMSPR_LR;
+            when SPR_CTR =>
+                ret.index := RAMSPR_CTR;
+                ret.isodd := '1';
+            when SPR_TAR =>
+                ret.index := RAMSPR_TAR;
             when SPR_SRR0 =>
                 ret.index := RAMSPR_SRR0;
             when SPR_SRR1 =>
@@ -683,13 +690,6 @@ begin
             end if;
 
         when 16 =>
-            -- CTR may be needed as input to bc
-            if f_in.insn(23) = '0' then
-                v.ispr1 := fast_spr_num(SPR_CTR);
-                v.ispro := fast_spr_num(SPR_CTR);
-            elsif f_in.insn(0) = '1' then
-                v.ispro := fast_spr_num(SPR_LR);
-            end if;
             -- Predict backward branches as taken, forward as untaken
             v.br_pred := f_in.insn(15);
             br_offset := resize(signed(f_in.insn(15 downto 2)), 24);
@@ -698,37 +698,12 @@ begin
             -- Unconditional branches are always taken
             v.br_pred := '1';
             br_offset := signed(f_in.insn(25 downto 2));
-            if f_in.insn(0) = '1' then
-                v.ispro := fast_spr_num(SPR_LR);
-            end if;
 
         when 19 =>
             vi.override := not decode_op_19_valid(to_integer(unsigned(f_in.insn(5 downto 1) & f_in.insn(10 downto 6))));
             op_19_bits := f_in.insn(5) & f_in.insn(3) & f_in.insn(2);
             v.decode := decode_op_19_array(to_integer(unsigned(op_19_bits)));
 
-            -- Work out ispr1/ispr2 independent of v.decode since they seem to be critical path
-            if f_in.insn(2) = '0' then
-                -- Could be OP_BCREG: bclr, bcctr, bctar
-                -- Branch uses CTR as condition when BO(2) is 0. This is
-                -- also used to indicate that CTR is modified (they go
-                -- together).
-                -- bcctr doesn't update CTR or use it in the branch condition
-                if f_in.insn(23) = '0' and (f_in.insn(10) = '0' or f_in.insn(6) = '1') then
-                    v.ispr1 := fast_spr_num(SPR_CTR);
-                    v.ispro := fast_spr_num(SPR_CTR);
-                elsif f_in.insn(0) = '1' then
-                    v.ispro := fast_spr_num(SPR_LR);
-                end if;
-                if f_in.insn(10) = '0' then
-                    v.ispr2 := fast_spr_num(SPR_LR);
-                elsif f_in.insn(6) = '0' then
-                    v.ispr2 := fast_spr_num(SPR_CTR);
-                else
-                    v.ispr2 := fast_spr_num(SPR_TAR);
-                end if;
-            end if;
-
         when 24 =>
             -- ori, special-case the standard NOP
             if std_match(f_in.insn, "01100000000000000000000000000000") then
index c76b7f52829b6933a3ff9f910efb1ae473eba293..928ec945343c3c8c03d52eadd23a51d7b15ea2d0 100644 (file)
@@ -406,6 +406,7 @@ begin
         variable length : std_ulogic_vector(3 downto 0);
         variable op : insn_type_t;
         variable valid_in : std_ulogic;
+        variable decctr : std_ulogic;
     begin
         v := dc2;
 
@@ -470,17 +471,45 @@ begin
             end if;
             op := d_in.decode.insn_type;
 
+            -- Does this instruction decrement CTR?
+            -- bc, bclr, bctar with BO(2) = 0 do, but not bcctr.
+            decctr := '0';
+            if d_in.insn(23) = '0' and
+                (op = OP_BC or
+                 (op = OP_BCREG and not (d_in.insn(10) = '1' and d_in.insn(6) = '0'))) then
+                decctr := '1';
+            end if;
+            v.e.dec_ctr := decctr;
+
             v.repeat := d_in.decode.repeat;
             if d_in.decode.repeat /= NONE then
                 v.e.repeat := '1';
-            elsif v.e.lr = '1' and decoded_reg_a.reg_valid = '1' then
-                -- bcl/bclrl/bctarl that needs to write both CTR and LR has to be doubled
-                v.e.repeat := '1';
             end if;
 
             v.e.spr_select := d_in.spr_info;
 
+            if decctr = '1' then
+                -- read and write CTR
+                v.e.ramspr_odd_rdaddr := RAMSPR_CTR;
+                v.e.ramspr_wraddr := RAMSPR_CTR;
+                v.e.ramspr_write_odd := '1';
+            end if;
+            if v.e.lr = '1' then
+                -- write LR
+                v.e.ramspr_wraddr := RAMSPR_LR;
+                v.e.ramspr_write_even := '1';
+            end if;
+
             case op is
+                when OP_BCREG =>
+                    if d_in.insn(10) = '0' then
+                        v.e.ramspr_even_rdaddr := RAMSPR_LR;
+                    elsif d_in.insn(6) = '0' then
+                        v.e.ramspr_odd_rdaddr := RAMSPR_CTR;
+                        v.e.ramspr_rd_odd := '1';
+                    else
+                        v.e.ramspr_even_rdaddr := RAMSPR_TAR;
+                    end if;
                 when OP_MFSPR =>
                     v.e.ramspr_even_rdaddr := d_in.ram_spr.index;
                     v.e.ramspr_odd_rdaddr := d_in.ram_spr.index;
@@ -520,7 +549,6 @@ begin
             v.e.write_reg := decoded_reg_o.reg;
             v.e.write_reg_enable := decoded_reg_o.reg_valid;
             v.e.invert_a := d_in.decode.invert_a;
-            v.e.addm1 := '0';
             v.e.insn_type := op;
             v.e.invert_out := d_in.decode.invert_out;
             v.e.input_carry := d_in.decode.input_carry;
@@ -536,14 +564,6 @@ begin
             v.e.br_pred := d_in.br_pred;
             v.e.result_sel := result_select(op);
             v.e.sub_select := subresult_select(op);
-            if op = OP_BC or op = OP_BCREG then
-                if d_in.insn(23) = '0' and
-                    not (d_in.decode.insn_type = OP_BCREG and d_in.insn(10) = '0') then
-                    -- decrement CTR if BO(2) = 0 and not bcctr
-                    v.e.addm1 := '1';
-                    v.e.result_sel := "000";        -- select adder output
-                end if;
-            end if;
             if op = OP_MFSPR then
                 if is_fast_spr(d_in.ispr1) = '1' then
                     v.e.result_sel := "000";        -- adder_result, effectively a_in
@@ -562,16 +582,9 @@ begin
             -- dc2.busy = 1 and dc2.e.valid = 1, thus this must be a repeated instruction.
             -- Set up for the second iteration (if deferred = 1 this will all be ignored)
             v.e.second := '1';
-            case dc2.repeat is
-                when DUPD =>
-                    -- update-form loads, 2nd instruction writes RA
-                    v.e.write_reg := dc2.e.read_reg1;
-                when NONE =>
-                    -- bcl/bclrl/bctarl that needs to write both CTR and LR
-                    v.e.write_reg(0) := '0';    -- point to LR
-                    v.e.result_sel := "110";    -- select NIA (to go to LR)
-                when others =>
-            end case;
+            -- DUPD is the only possibility here:
+            -- update-form loads, 2nd instruction writes RA
+            v.e.write_reg := dc2.e.read_reg1;
         end if;
 
         -- issue control
index b0b2f98b455bb43e0809a0e65ebf77e193325e7b..5ee830b556ed82d76f89a128b7f617df997bfb06 100644 (file)
@@ -12,6 +12,7 @@ use work.ppc_fx_insns.all;
 
 entity execute1 is
     generic (
+        SIM : boolean := false;
         EX1_BYPASS : boolean := true;
         HAS_FPU : boolean := true;
         HAS_SHORT_MULT : boolean := false;
@@ -54,6 +55,10 @@ entity execute1 is
         dc_events    : in DcacheEventType;
         ic_events    : in IcacheEventType;
 
+        -- debug
+        sim_dump      : in std_ulogic;
+        sim_dump_done : out std_ulogic;
+
         log_out : out std_ulogic_vector(14 downto 0);
         log_rd_addr : out std_ulogic_vector(31 downto 0);
         log_rd_data : in std_ulogic_vector(63 downto 0);
@@ -92,10 +97,12 @@ architecture behaviour of execute1 is
         fp_intr : std_ulogic;
         res2_sel : std_ulogic_vector(1 downto 0);
         bypass_valid : std_ulogic;
+        ramspr_odd_data : std_ulogic_vector(63 downto 0);
     end record;
     constant actions_type_init : actions_type :=
         (e => Execute1ToWritebackInit, se => side_effect_init,
-         new_msr => (others => '0'), res2_sel => "00", others => '0');
+         new_msr => (others => '0'), res2_sel => "00",
+         ramspr_odd_data => 64x"0", others => '0');
 
     type reg_stage1_type is record
        e : Execute1ToWritebackType;
@@ -104,7 +111,6 @@ architecture behaviour of execute1 is
         fp_exception_next : std_ulogic;
         trace_next : std_ulogic;
         prev_op : insn_type_t;
-        br_taken : std_ulogic;
         oe : std_ulogic;
         mul_select : std_ulogic_vector(1 downto 0);
         res2_sel : std_ulogic_vector(1 downto 0);
@@ -122,11 +128,12 @@ architecture behaviour of execute1 is
         xerc : xer_common_t;
         xerc_valid : std_ulogic;
         ramspr_wraddr : ramspr_index;
+        ramspr_odd_data : std_ulogic_vector(63 downto 0);
     end record;
     constant reg_stage1_type_init : reg_stage1_type :=
         (e => Execute1ToWritebackInit, se => side_effect_init,
          busy => '0',
-         fp_exception_next => '0', trace_next => '0', prev_op => OP_ILLEGAL, br_taken => '0',
+         fp_exception_next => '0', trace_next => '0', prev_op => OP_ILLEGAL,
          oe => '0', mul_select => "00", res2_sel => "00",
          spr_select => spr_id_init, pmu_spr_num => 5x"0",
          mul_in_progress => '0', mul_finish => '0', div_in_progress => '0',
@@ -134,7 +141,7 @@ architecture behaviour of execute1 is
          taken_branch_event => '0', br_mispredict => '0',
          msr => 64x"0",
          xerc => xerc_init, xerc_valid => '0',
-         ramspr_wraddr => 0);
+         ramspr_wraddr => 0, ramspr_odd_data => 64x"0");
 
     type reg_stage2_type is record
        e : Execute1ToWritebackType;
@@ -514,7 +521,7 @@ begin
             odd_wr_data := intr_srr1(ctrl.msr, interrupt_in.srr1);
         else
             even_wr_data := ex1.e.write_data;
-            odd_wr_data := ex1.e.write_data;
+            odd_wr_data := ex1.ramspr_odd_data;
         end if;
         ramspr_wr_addr <= wr_addr;
         ramspr_even_wr_data <= even_wr_data;
@@ -531,7 +538,7 @@ begin
             ramspr_even <= even_rd_data;
         end if;
         if ex1.se.ramspr_write_odd = '1' and e_in.ramspr_odd_rdaddr = ex1.ramspr_wraddr then
-            ramspr_odd <= ex1.e.write_data;
+            ramspr_odd <= ex1.ramspr_odd_data;
         else
             ramspr_odd <= odd_rd_data;
         end if;
@@ -600,7 +607,6 @@ begin
     -- Data path for integer instructions (first execute stage)
     execute1_dp: process(all)
        variable a_inv : std_ulogic_vector(63 downto 0);
-       variable b_or_m1 : std_ulogic_vector(63 downto 0);
        variable sum_with_carry : std_ulogic_vector(64 downto 0);
         variable sign1, sign2 : std_ulogic;
         variable abs1, abs2 : signed(63 downto 0);
@@ -635,12 +641,7 @@ begin
         else
             a_inv := not a_in;
         end if;
-        if e_in.addm1 = '0' then
-            b_or_m1 := b_in;
-        else
-            b_or_m1 := (others => '1');
-        end if;
-        sum_with_carry := ppc_adde(a_inv, b_or_m1,
+        sum_with_carry := ppc_adde(a_inv, b_in,
                                    decode_input_carry(e_in.input_carry, xerc_in));
         adder_result <= sum_with_carry(63 downto 0);
         carry_32 <= sum_with_carry(32) xor a_inv(32) xor b_in(32);
@@ -956,6 +957,10 @@ begin
 
         v.se.ramspr_write_even := e_in.ramspr_write_even;
         v.se.ramspr_write_odd := e_in.ramspr_write_odd;
+        v.ramspr_odd_data := c_in;
+        if e_in.dec_ctr = '1' then
+            v.ramspr_odd_data := std_ulogic_vector(unsigned(ramspr_odd) - 1);
+        end if;
 
         -- Note the difference between v.exception and v.trap:
         -- v.exception signals a condition that prevents execution of the
@@ -1059,61 +1064,42 @@ begin
                 end if;
                 v.se.write_cfar := '1';
             when OP_BC =>
-                -- read_data1 is CTR
-                -- If this instruction updates both CTR and LR, then it is
-                -- doubled; the first instruction decrements CTR and determines
-                -- whether the branch is taken, and the second does the
-                -- redirect and the LR update.
+                -- If CTR is being decremented, it is in ramspr_odd.
                bo := insn_bo(e_in.insn);
                bi := insn_bi(e_in.insn);
-                if e_in.second = '0' then
-                    v.take_branch := ppc_bc_taken(bo, bi, cr_in, a_in);
-                else
-                    v.take_branch := ex1.br_taken;
-                end if;
+                v.take_branch := ppc_bc_taken(bo, bi, cr_in, ramspr_odd);
                 if v.take_branch = '1' then
                     v.e.br_offset := b_in;
                     v.e.abs_br := insn_aa(e_in.insn);
                 end if;
-                if e_in.repeat = '0' or e_in.second = '1' then
-                    -- Mispredicted branches cause a redirect
-                    if v.take_branch /= e_in.br_pred then
-                        v.e.redirect := '1';
-                    end if;
-                    v.direct_branch := '1';
-                    v.e.br_last := '1';
-                    v.e.br_taken := v.take_branch;
-                    if ex1.msr(MSR_BE) = '1' then
-                        v.do_trace := '1';
-                    end if;
-                    v.se.write_cfar := v.take_branch;
+                -- Mispredicted branches cause a redirect
+                if v.take_branch /= e_in.br_pred then
+                    v.e.redirect := '1';
+                end if;
+                v.direct_branch := '1';
+                v.e.br_last := '1';
+                v.e.br_taken := v.take_branch;
+                if ex1.msr(MSR_BE) = '1' then
+                    v.do_trace := '1';
                 end if;
+                v.se.write_cfar := v.take_branch;
             when OP_BCREG =>
-                -- read_data1 is CTR, read_data2 is target register (CTR, LR or TAR)
-                -- If this instruction updates both CTR and LR, then it is
-                -- doubled; the first instruction decrements CTR and determines
-                -- whether the branch is taken, and the second does the
-                -- redirect and the LR update.
+                -- If CTR is being decremented, it is in ramspr_odd.
+                -- The target address is in ramspr_result (LR, CTR or TAR).
                bo := insn_bo(e_in.insn);
                bi := insn_bi(e_in.insn);
-                if e_in.second = '0' then
-                    v.take_branch := ppc_bc_taken(bo, bi, cr_in, a_in);
-                else
-                    v.take_branch := ex1.br_taken;
-                end if;
+                v.take_branch := ppc_bc_taken(bo, bi, cr_in, ramspr_odd);
                 if v.take_branch = '1' then
-                    v.e.br_offset := b_in;
+                    v.e.br_offset := ramspr_result;
                     v.e.abs_br := '1';
                 end if;
-                if e_in.repeat = '0' or e_in.second = '1' then
-                    -- Indirect branches are never predicted taken
-                    v.e.redirect := v.take_branch;
-                    v.e.br_taken := v.take_branch;
-                    if ex1.msr(MSR_BE) = '1' then
-                        v.do_trace := '1';
-                    end if;
-                    v.se.write_cfar := v.take_branch;
+                -- Indirect branches are never predicted taken
+                v.e.redirect := v.take_branch;
+                v.e.br_taken := v.take_branch;
+                if ex1.msr(MSR_BE) = '1' then
+                    v.do_trace := '1';
                 end if;
+                v.se.write_cfar := v.take_branch;
 
            when OP_RFID =>
                 srr1 := ramspr_odd;
@@ -1130,7 +1116,7 @@ begin
                     v.new_msr(MSR_DR) := '1';
                 end if;
                 v.se.write_msr := '1';
-                v.e.br_offset := ramspr_even;
+                v.e.br_offset := ramspr_result;
                 v.e.abs_br := '1';
                 v.e.redirect := '1';
                 v.se.write_cfar := '1';
@@ -1343,6 +1329,7 @@ begin
             v.mul_select := e_in.sub_select(1 downto 0);
             v.se := side_effect_init;
             v.ramspr_wraddr := e_in.ramspr_wraddr;
+            v.ramspr_odd_data := actions.ramspr_odd_data;
         end if;
 
         lv := Execute1ToLoadstore1Init;
@@ -1430,7 +1417,6 @@ begin
             v.e.valid := actions.complete;
             bypass_valid := actions.bypass_valid;
             v.taken_branch_event := actions.take_branch;
-            v.br_taken := actions.take_branch;
             v.trace_next := actions.do_trace;
             v.fp_exception_next := actions.fp_intr;
             v.res2_sel := actions.res2_sel;
@@ -1759,6 +1745,25 @@ begin
         exception_log <= v.e.interrupt;
     end process;
 
+    sim_dump_test: if SIM generate
+        dump_exregs: process(all)
+            variable xer : std_ulogic_vector(63 downto 0);
+        begin
+            if sim_dump = '1' then
+                report "LR " & to_hstring(even_sprs(RAMSPR_LR));
+                report "CTR " & to_hstring(odd_sprs(RAMSPR_CTR));
+                sim_dump_done <= '1';
+            else
+                sim_dump_done <= '0';
+            end if;
+        end process;
+    end generate;
+
+    -- Keep GHDL synthesis happy
+    sim_dump_test_synth: if not SIM generate
+        sim_dump_done <= '0';
+    end generate;
+
     e1_log: if LOG_LENGTH > 0 generate
         signal log_data : std_ulogic_vector(14 downto 0);
     begin
index 0235dfcd2f817fe5abab77bd5a599b519845555f..ed856cb2f3b9366fa662cd730e3341d877dc5b6a 100644 (file)
@@ -130,9 +130,6 @@ begin
                 loop_0: for i in 0 to 31 loop
                     report "GPR" & integer'image(i) & " " & to_hstring(registers(i));
                 end loop loop_0;
-
-                report "LR " & to_hstring(registers(to_integer(unsigned(fast_spr_num(SPR_LR)))));
-                report "CTR " & to_hstring(registers(to_integer(unsigned(fast_spr_num(SPR_CTR)))));
                 sim_dump_done <= '1';
             else
                 sim_dump_done <= '0';