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