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)]
|
#[derive(Debug, PartialEq)]
|
||||||
enum PipelineState {
|
pub enum PipelineState {
|
||||||
Refill1,
|
Refill1,
|
||||||
Refill2,
|
Refill2,
|
||||||
Execute,
|
Execute,
|
||||||
|
@ -42,13 +42,8 @@ pub struct Core {
|
||||||
|
|
||||||
pub(super) bs_carry_out: bool,
|
pub(super) bs_carry_out: bool,
|
||||||
|
|
||||||
pipeline_state: PipelineState,
|
pub pipeline_state: PipelineState,
|
||||||
pipeline: [u32; 2],
|
pipeline: [u32; 2],
|
||||||
|
|
||||||
fetched_arm: u32,
|
|
||||||
decoded_arm: u32,
|
|
||||||
fetched_thumb: u16,
|
|
||||||
decoded_thumb: u16,
|
|
||||||
pub last_executed: Option<DecodedInstruction>,
|
pub last_executed: Option<DecodedInstruction>,
|
||||||
|
|
||||||
pub cycles: usize,
|
pub cycles: usize,
|
||||||
|
@ -311,8 +306,8 @@ impl Core {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn did_pipeline_flush(&self) -> bool {
|
pub fn did_pipeline_flush(&self) -> bool {
|
||||||
self.pipeline_state == PipelineState::Refill1
|
self.pipeline_state != PipelineState::Execute
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step_arm_exec(&mut self, insn: u32, sb: &mut SysBus) -> CpuResult<()> {
|
fn step_arm_exec(&mut self, insn: u32, sb: &mut SysBus) -> CpuResult<()> {
|
||||||
|
@ -355,13 +350,13 @@ impl Core {
|
||||||
self.last_executed = None;
|
self.last_executed = None;
|
||||||
}
|
}
|
||||||
PipelineState::Execute => {
|
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.gpr_previous = self.get_registers();
|
||||||
self.exec_thumb(sb, insn)?;
|
self.exec_thumb(sb, decoded_thumb)?;
|
||||||
if !self.did_pipeline_flush() {
|
if !self.did_pipeline_flush() {
|
||||||
self.pc = pc.wrapping_add(2);
|
self.pc = pc.wrapping_add(2);
|
||||||
}
|
}
|
||||||
self.last_executed = Some(DecodedInstruction::Thumb(insn));
|
self.last_executed = Some(DecodedInstruction::Thumb(decoded_thumb));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -411,6 +406,8 @@ impl Core {
|
||||||
self.pipeline[0] = self.pipeline[1];
|
self.pipeline[0] = self.pipeline[1];
|
||||||
self.pipeline[1] = fetched_now;
|
self.pipeline[1] = fetched_now;
|
||||||
|
|
||||||
|
self.trace_opcode(insn.into());
|
||||||
|
|
||||||
match self.cpsr.state() {
|
match self.cpsr.state() {
|
||||||
CpuState::ARM => self.step_arm_exec(insn, bus),
|
CpuState::ARM => self.step_arm_exec(insn, bus),
|
||||||
CpuState::THUMB => self.step_thumb_exec(insn as u16, bus),
|
CpuState::THUMB => self.step_thumb_exec(insn as u16, bus),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use super::super::sysbus::SysBus;
|
use super::super::sysbus::SysBus;
|
||||||
use super::cpu::Core;
|
use super::cpu::{Core, PipelineState};
|
||||||
use super::REG_LR;
|
use super::REG_LR;
|
||||||
use super::{CpuMode, CpuState};
|
use super::{CpuMode, CpuState};
|
||||||
use colored::*;
|
use colored::*;
|
||||||
|
@ -63,6 +63,9 @@ impl Core {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn irq(&mut self, sb: &mut SysBus) {
|
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() {
|
if !self.cpsr.irq_disabled() {
|
||||||
let lr = self.get_next_pc() + 4;
|
let lr = self.get_next_pc() + 4;
|
||||||
self.exception(sb, Exception::Irq, lr)
|
self.exception(sb, Exception::Irq, lr)
|
||||||
|
|
|
@ -76,7 +76,10 @@ impl GameBoyAdvance {
|
||||||
};
|
};
|
||||||
|
|
||||||
let cycles = if !io.dmac.perform_work(&mut self.sysbus, &mut irqs) {
|
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);
|
self.cpu.irq(&mut self.sysbus);
|
||||||
io.haltcnt = HaltState::Running;
|
io.haltcnt = HaltState::Running;
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue