Don't allow IRQs when pipeline is reloading
Former-commit-id: a51d3671dfabab422f2ad880b3cbe1bac65d442b
This commit is contained in:
parent
b288625b9a
commit
b9d0857acc
|
@ -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),
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Reference in a new issue