diff --git a/execute1.vhdl b/execute1.vhdl index ffa9048..6c19559 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -399,13 +399,15 @@ begin ctrl_tmp.msr(63 - 48) <= '0'; -- clear EE f_out.redirect <= '1'; f_out.redirect_nia <= ctrl.irq_nia; - v.e.valid := '1'; + v.e.valid := e_in.valid; report "Writing SRR1: " & to_hstring(ctrl.srr1); elsif irq_valid = '1' then -- we need two cycles to write srr0 and 1 -- will need more when we have to write DSISR, DAR and HIER - exception := '1'; + -- Don't deliver the interrupt until we have a valid instruction + -- coming in, so we have a valid NIA to put in SRR0. + exception := e_in.valid; ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#900#, 64)); ctrl_tmp.srr1 <= msr_copy(ctrl.msr); @@ -821,16 +823,12 @@ begin end if; if exception = '1' then - if e_in.valid = '1' then - v.e.exc_write_enable := '1'; - if exception_nextpc = '1' then - v.e.exc_write_data := std_logic_vector(unsigned(e_in.nia) + 4); - end if; - ctrl_tmp.irq_state <= WRITE_SRR1; - stall_out <= '1'; - v.e.valid := '0'; - result_en := '0'; - end if; + v.e.exc_write_enable := '1'; + if exception_nextpc = '1' then + v.e.exc_write_data := next_nia; + end if; + ctrl_tmp.irq_state <= WRITE_SRR1; + v.e.valid := '1'; end if; v.e.write_data := result; diff --git a/writeback.vhdl b/writeback.vhdl index 71870c2..60afebb 100644 --- a/writeback.vhdl +++ b/writeback.vhdl @@ -55,52 +55,54 @@ begin w_out.write_reg <= e_in.exc_write_reg; w_out.write_data <= e_in.exc_write_data; w_out.write_enable <= '1'; - elsif e_in.write_enable = '1' then - w_out.write_reg <= e_in.write_reg; - w_out.write_data <= e_in.write_data; - w_out.write_enable <= '1'; - end if; - - if e_in.write_cr_enable = '1' then - c_out.write_cr_enable <= '1'; - c_out.write_cr_mask <= e_in.write_cr_mask; - c_out.write_cr_data <= e_in.write_cr_data; - end if; - - if e_in.write_xerc_enable = '1' then - c_out.write_xerc_enable <= '1'; - c_out.write_xerc_data <= e_in.xerc; - end if; - - if l_in.write_enable = '1' then - w_out.write_reg <= gpr_to_gspr(l_in.write_reg); - w_out.write_data <= l_in.write_data; - w_out.write_enable <= '1'; - end if; - - if l_in.rc = '1' then - -- st*cx. instructions - scf(3) := '0'; - scf(2) := '0'; - scf(1) := l_in.store_done; - scf(0) := l_in.xerc.so; - c_out.write_cr_enable <= '1'; - c_out.write_cr_mask <= num_to_fxm(0); - c_out.write_cr_data(31 downto 28) <= scf; - end if; - - -- Perform CR0 update for RC forms - -- Note that loads never have a form with an RC bit, therefore this can test e_in.write_data - if e_in.rc = '1' and e_in.write_enable = '1' then - sign := e_in.write_data(63); - zero := not (or e_in.write_data); - c_out.write_cr_enable <= '1'; - c_out.write_cr_mask <= num_to_fxm(0); - cf(3) := sign; - cf(2) := not sign and not zero; - cf(1) := zero; - cf(0) := e_in.xerc.so; - c_out.write_cr_data(31 downto 28) <= cf; + else + if e_in.write_enable = '1' then + w_out.write_reg <= e_in.write_reg; + w_out.write_data <= e_in.write_data; + w_out.write_enable <= '1'; + end if; + + if e_in.write_cr_enable = '1' then + c_out.write_cr_enable <= '1'; + c_out.write_cr_mask <= e_in.write_cr_mask; + c_out.write_cr_data <= e_in.write_cr_data; + end if; + + if e_in.write_xerc_enable = '1' then + c_out.write_xerc_enable <= '1'; + c_out.write_xerc_data <= e_in.xerc; + end if; + + if l_in.write_enable = '1' then + w_out.write_reg <= gpr_to_gspr(l_in.write_reg); + w_out.write_data <= l_in.write_data; + w_out.write_enable <= '1'; + end if; + + if l_in.rc = '1' then + -- st*cx. instructions + scf(3) := '0'; + scf(2) := '0'; + scf(1) := l_in.store_done; + scf(0) := l_in.xerc.so; + c_out.write_cr_enable <= '1'; + c_out.write_cr_mask <= num_to_fxm(0); + c_out.write_cr_data(31 downto 28) <= scf; + end if; + + -- Perform CR0 update for RC forms + -- Note that loads never have a form with an RC bit, therefore this can test e_in.write_data + if e_in.rc = '1' and e_in.write_enable = '1' then + sign := e_in.write_data(63); + zero := not (or e_in.write_data); + c_out.write_cr_enable <= '1'; + c_out.write_cr_mask <= num_to_fxm(0); + cf(3) := sign; + cf(2) := not sign and not zero; + cf(1) := zero; + cf(0) := e_in.xerc.so; + c_out.write_cr_data(31 downto 28) <= cf; + end if; end if; end process; end;