Don't allow IRQs when pipeline is reloading

Former-commit-id: a51d3671dfabab422f2ad880b3cbe1bac65d442b
This commit is contained in:
Michel Heily 2019-11-16 18:01:41 +02:00
parent b288625b9a
commit b9d0857acc
3 changed files with 17 additions and 14 deletions

View file

@ -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<DecodedInstruction>,
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),

View file

@ -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)

View file

@ -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;
}