diff --git a/common.vhdl b/common.vhdl index d376ac3..15c5c2a 100644 --- a/common.vhdl +++ b/common.vhdl @@ -31,6 +31,7 @@ package common is constant SPR_DEC : spr_num_t := 22; constant SPR_SRR0 : spr_num_t := 26; constant SPR_SRR1 : spr_num_t := 27; + constant SPR_CFAR : spr_num_t := 28; constant SPR_HSRR0 : spr_num_t := 314; constant SPR_HSRR1 : spr_num_t := 315; constant SPR_SPRG0 : spr_num_t := 272; @@ -94,6 +95,7 @@ package common is tb: std_ulogic_vector(63 downto 0); dec: std_ulogic_vector(63 downto 0); msr: std_ulogic_vector(63 downto 0); + cfar: std_ulogic_vector(63 downto 0); irq_state : irq_state_t; irq_nia: std_ulogic_vector(63 downto 0); srr1: std_ulogic_vector(63 downto 0); diff --git a/decode1.vhdl b/decode1.vhdl index 2060e64..d215e7e 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -473,8 +473,8 @@ begin end if; else -- Could be OP_RFID - v.ispr1 := fast_spr_num(SPR_SRR0); - v.ispr2 := fast_spr_num(SPR_SRR1); + v.ispr1 := fast_spr_num(SPR_SRR1); + v.ispr2 := fast_spr_num(SPR_SRR0); end if; elsif majorop = "011110" then diff --git a/execute1.vhdl b/execute1.vhdl index c585f78..0da059a 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -652,26 +652,27 @@ begin result_en := '1'; v.e.write_reg := fast_spr_num(SPR_CTR); end if; - if ppc_bc_taken(bo, bi, e_in.cr, a_in) = '1' then - f_out.redirect <= '1'; - f_out.redirect_nia <= b_in(63 downto 2) & "00"; - end if; + is_branch := '1'; + taken_branch := ppc_bc_taken(bo, bi, e_in.cr, a_in); + abs_branch := '1'; when OP_RFID => - f_out.redirect <= '1'; - f_out.virt_mode <= b_in(MSR_IR) or b_in(MSR_PR); - f_out.priv_mode <= not b_in(MSR_PR); - f_out.redirect_nia <= a_in(63 downto 2) & "00"; -- srr0 + f_out.virt_mode <= a_in(MSR_IR) or a_in(MSR_PR); + f_out.priv_mode <= not a_in(MSR_PR); -- Can't use msr_copy here because the partial function MSR -- bits should be left unchanged, not zeroed. - ctrl_tmp.msr(63 downto 31) <= b_in(63 downto 31); - ctrl_tmp.msr(26 downto 22) <= b_in(26 downto 22); - ctrl_tmp.msr(15 downto 0) <= b_in(15 downto 0); - if b_in(MSR_PR) = '1' then + ctrl_tmp.msr(63 downto 31) <= a_in(63 downto 31); + ctrl_tmp.msr(26 downto 22) <= a_in(26 downto 22); + ctrl_tmp.msr(15 downto 0) <= a_in(15 downto 0); + if a_in(MSR_PR) = '1' then ctrl_tmp.msr(MSR_EE) <= '1'; ctrl_tmp.msr(MSR_IR) <= '1'; ctrl_tmp.msr(MSR_DR) <= '1'; end if; + -- mark this as a branch so CFAR gets updated + is_branch := '1'; + taken_branch := '1'; + abs_branch := '1'; when OP_CNTZ => v.e.valid := '0'; @@ -757,6 +758,8 @@ begin spr_val(31 downto 0) := ctrl.tb(63 downto 32); when SPR_DEC => spr_val := ctrl.dec; + when SPR_CFAR => + spr_val := ctrl.cfar; when 724 => -- LOG_ADDR SPR spr_val := log_wr_addr & r.log_addr_spr; when 725 => -- LOG_DATA SPR @@ -879,9 +882,9 @@ begin v.e.rc := e_in.rc and valid_in; -- Mispredicted branches cause a redirect - if is_branch = '1' and taken_branch /= e_in.br_pred then - f_out.redirect <= '1'; + if is_branch = '1' then if taken_branch = '1' then + ctrl_tmp.cfar <= e_in.nia; if abs_branch = '1' then f_out.redirect_nia <= b_in; else @@ -890,6 +893,9 @@ begin else f_out.redirect_nia <= next_nia; end if; + if taken_branch /= e_in.br_pred then + f_out.redirect <= '1'; + end if; end if; -- Update LR on the next cycle after a branch link diff --git a/fetch1.vhdl b/fetch1.vhdl index 0d9c6f7..a56f33d 100644 --- a/fetch1.vhdl +++ b/fetch1.vhdl @@ -83,11 +83,11 @@ begin v.priv_mode := '1'; v_int.stop_state := RUNNING; elsif e_in.redirect = '1' then - v.nia := e_in.redirect_nia; + v.nia := e_in.redirect_nia(63 downto 2) & "00"; v.virt_mode := e_in.virt_mode; v.priv_mode := e_in.priv_mode; elsif d_in.redirect = '1' then - v.nia := d_in.redirect_nia; + v.nia := d_in.redirect_nia(63 downto 2) & "00"; elsif stall_in = '0' then -- For debug stop/step to work properly we need a little bit of