From b9d0857acc4460340f60c50036aa53eddfbd211a Mon Sep 17 00:00:00 2001 From: Michel Heily Date: Sat, 16 Nov 2019 18:01:41 +0200 Subject: [PATCH] Don't allow IRQs when pipeline is reloading Former-commit-id: a51d3671dfabab422f2ad880b3cbe1bac65d442b --- src/core/arm7tdmi/cpu.rs | 21 +++++++++------------ src/core/arm7tdmi/exception.rs | 5 ++++- src/core/gba.rs | 5 ++++- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/core/arm7tdmi/cpu.rs b/src/core/arm7tdmi/cpu.rs index bda63b7..d0c7c4e 100644 --- a/src/core/arm7tdmi/cpu.rs +++ b/src/core/arm7tdmi/cpu.rs @@ -13,7 +13,7 @@ use super::super::sysbus::{ }; #[derive(Debug, PartialEq)] -enum PipelineState { +pub enum PipelineState { Refill1, Refill2, Execute, @@ -42,13 +42,8 @@ pub struct Core { pub(super) bs_carry_out: bool, - pipeline_state: PipelineState, + pub pipeline_state: PipelineState, pipeline: [u32; 2], - - fetched_arm: u32, - decoded_arm: u32, - fetched_thumb: u16, - decoded_thumb: u16, pub last_executed: Option, pub cycles: usize, @@ -311,8 +306,8 @@ impl Core { } } - pub(super) fn did_pipeline_flush(&self) -> bool { - self.pipeline_state == PipelineState::Refill1 + pub fn did_pipeline_flush(&self) -> bool { + self.pipeline_state != PipelineState::Execute } fn step_arm_exec(&mut self, insn: u32, sb: &mut SysBus) -> CpuResult<()> { @@ -355,13 +350,13 @@ impl Core { self.last_executed = None; } PipelineState::Execute => { - let insn = ThumbInstruction::decode(insn, self.pc.wrapping_sub(4))?; + let decoded_thumb = ThumbInstruction::decode(insn, self.pc.wrapping_sub(4))?; self.gpr_previous = self.get_registers(); - self.exec_thumb(sb, insn)?; + self.exec_thumb(sb, decoded_thumb)?; if !self.did_pipeline_flush() { self.pc = pc.wrapping_add(2); } - self.last_executed = Some(DecodedInstruction::Thumb(insn)); + self.last_executed = Some(DecodedInstruction::Thumb(decoded_thumb)); } } Ok(()) @@ -411,6 +406,8 @@ impl Core { self.pipeline[0] = self.pipeline[1]; self.pipeline[1] = fetched_now; + self.trace_opcode(insn.into()); + match self.cpsr.state() { CpuState::ARM => self.step_arm_exec(insn, bus), CpuState::THUMB => self.step_thumb_exec(insn as u16, bus), diff --git a/src/core/arm7tdmi/exception.rs b/src/core/arm7tdmi/exception.rs index 4062ef7..149a2fb 100644 --- a/src/core/arm7tdmi/exception.rs +++ b/src/core/arm7tdmi/exception.rs @@ -1,5 +1,5 @@ use super::super::sysbus::SysBus; -use super::cpu::Core; +use super::cpu::{Core, PipelineState}; use super::REG_LR; use super::{CpuMode, CpuState}; use colored::*; @@ -63,6 +63,9 @@ impl Core { } pub fn irq(&mut self, sb: &mut SysBus) { + if self.pipeline_state != PipelineState::Execute { + panic!("IRQ when pipeline refilling! {:?}", self.pipeline_state); + } if !self.cpsr.irq_disabled() { let lr = self.get_next_pc() + 4; self.exception(sb, Exception::Irq, lr) diff --git a/src/core/gba.rs b/src/core/gba.rs index f742618..cd89c43 100644 --- a/src/core/gba.rs +++ b/src/core/gba.rs @@ -76,7 +76,10 @@ impl GameBoyAdvance { }; let cycles = if !io.dmac.perform_work(&mut self.sysbus, &mut irqs) { - if io.intc.irq_pending() { + if io.intc.irq_pending() + && self.cpu.last_executed.is_some() + && !self.cpu.did_pipeline_flush() + { self.cpu.irq(&mut self.sysbus); io.haltcnt = HaltState::Running; }