xous-kernel/xous-riscv/src/register/mcause.rs

140 lines
3.6 KiB
Rust

//! 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);