140 lines
3.6 KiB
Rust
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);
|