This repository has been archived on 2024-12-14. You can view files and clone it, but cannot push or open issues or pull requests.
rustboyadvance-ng/src/arm7tdmi/exception.rs
Michel Heily 98eee121fc Correct F flag behaviour when entrying an exception.
Former-commit-id: b0ef6352d9f0c027657c6e5eeb615a131e9523d2
2019-06-29 23:01:23 +03:00

53 lines
1.4 KiB
Rust

use super::{cpu::Core, CpuMode, CpuState};
use colored::*;
#[derive(Debug, Clone, Copy, PartialEq)]
#[allow(dead_code)]
/// Models a CPU exception, and maps to the relavnt entry in the exception vector
pub enum Exception {
Reset = 0x00,
UndefinedInstruction = 0x04,
SoftwareInterrupt = 0x08,
PrefatchAbort = 0x0c,
DataAbort = 0x10,
Reserved = 0x14,
Irq = 0x18,
Fiq = 0x1c,
}
impl From<Exception> for CpuMode {
/// Return cpu mode upon entry
fn from(e: Exception) -> CpuMode {
use Exception::*;
match e {
Reset | SoftwareInterrupt | Reserved => CpuMode::Supervisor,
PrefatchAbort | DataAbort => CpuMode::Abort,
UndefinedInstruction => CpuMode::Undefined,
Irq => CpuMode::Irq,
Fiq => CpuMode::Fiq,
}
}
}
impl Core {
pub fn exception(&mut self, e: Exception) {
let vector = e as u32;
let new_mode = CpuMode::from(e);
if self.verbose {
println!("{}: {:?}, new_mode: {:?}", "Exception".cyan(), e, new_mode);
}
self.change_mode(new_mode);
// Set appropriate CPSR bits
self.cpsr.set_state(CpuState::ARM);
self.cpsr.set_mode(new_mode);
self.cpsr.set_irq_disabled(true);
if e == Exception::Reset || e == Exception::Fiq {
self.cpsr.set_fiq_disabled(true);
}
// Set PC to vector address
self.pc = vector;
}
}