//! mcause register /// mcause register #[derive(Clone, Copy, Debug)] pub struct Mcause { bits: usize, } /// Trap Cause #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Trap { Interrupt(Interrupt), Exception(Exception), } /// Interrupt #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Interrupt { UserSoft, SupervisorSoft, MachineSoft, UserTimer, SupervisorTimer, MachineTimer, UserExternal, SupervisorExternal, MachineExternal, Unknown, } /// Exception #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Exception { InstructionMisaligned, InstructionFault, IllegalInstruction, Breakpoint, LoadMisaligned, LoadFault, StoreMisaligned, StoreFault, UserEnvCall, SupervisorEnvCall, MachineEnvCall, InstructionPageFault, LoadPageFault, StorePageFault, Unknown, } impl Interrupt { pub fn from(nr: usize) -> Self { match nr { 0 => Interrupt::UserSoft, 1 => Interrupt::SupervisorSoft, 3 => Interrupt::MachineSoft, 4 => Interrupt::UserTimer, 5 => Interrupt::SupervisorTimer, 7 => Interrupt::MachineTimer, 8 => Interrupt::UserExternal, 9 => Interrupt::SupervisorExternal, 11 => Interrupt::MachineExternal, _ => Interrupt::Unknown, } } } impl Exception { pub fn from(nr: usize) -> Self { match nr { 0 => Exception::InstructionMisaligned, 1 => Exception::InstructionFault, 2 => Exception::IllegalInstruction, 3 => Exception::Breakpoint, 4 => Exception::LoadMisaligned, 5 => Exception::LoadFault, 6 => Exception::StoreMisaligned, 7 => Exception::StoreFault, 8 => Exception::UserEnvCall, 9 => Exception::SupervisorEnvCall, 11 => Exception::MachineEnvCall, 12 => Exception::InstructionPageFault, 13 => Exception::LoadPageFault, 15 => Exception::StorePageFault, _ => Exception::Unknown, } } } impl Mcause { /// Returns the contents of the register as raw bits #[inline] pub fn bits(&self) -> usize { self.bits } /// Returns the code field pub fn code(&self) -> usize { match () { #[cfg(target_pointer_width = "32")] () => self.bits & !(1 << 31), #[cfg(target_pointer_width = "64")] () => self.bits & !(1 << 63), #[cfg(target_pointer_width = "128")] () => self.bits & !(1 << 127), } } /// Trap Cause #[inline] pub fn cause(&self) -> Trap { if self.is_interrupt() { Trap::Interrupt(Interrupt::from(self.code())) } else { Trap::Exception(Exception::from(self.code())) } } /// Is trap cause an interrupt. #[inline] pub fn is_interrupt(&self) -> bool { match () { #[cfg(target_pointer_width = "32")] () => self.bits & (1 << 31) == 1 << 31, #[cfg(target_pointer_width = "64")] () => self.bits & (1 << 63) == 1 << 63, #[cfg(target_pointer_width = "128")] () => self.bits & (1 << 127) == 1 << 127, } } /// Is trap cause an exception. #[inline] pub fn is_exception(&self) -> bool { !self.is_interrupt() } } read_csr_as!(Mcause, 0x342, __read_mcause);