use std::fmt;
#[derive(PartialEq)]
pub enum RiscvException {
NoException,
UserSoftwareInterrupt(u32 ),
SupervisorSoftwareInterrupt(u32 ),
MachineSoftwareInterrupt(u32 ),
UserTimerInterrupt(u32 ),
SupervisorTimerInterrupt(u32 ),
MachineTimerInterrupt(u32 ),
UserExternalInterrupt(u32 ),
SupervisorExternalInterrupt(u32 ),
MachineExternalInterrupt(u32 ),
ReservedInterrupt(u32 , u32 ),
InstructionAddressMisaligned(u32 , u32 ),
InstructionAccessFault(u32 , u32 ),
IllegalInstruction(u32 , u32 ),
Breakpoint(u32 ),
LoadAddressMisaligned(u32 , u32 ),
LoadAccessFault(u32 , u32 ),
StoreAddressMisaligned(u32 , u32 ),
StoreAccessFault(u32 , u32 ),
CallFromUMode(u32 ),
CallFromSMode(u32 ),
CallFromMMode(u32 ),
InstructionPageFault(u32 , u32 ),
LoadPageFault(u32 , u32 ),
StorePageFault(u32 , u32 ),
ReservedFault(
u32,
u32,
u32,
),
}
impl fmt::Display for RiscvException {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
use RiscvException::*;
match *self {
NoException => write!(f, "No trap"),
UserSoftwareInterrupt(epc) => write!(f, "User swi from 0x{:08x}", epc),
SupervisorSoftwareInterrupt(epc) => write!(f, "Supervisor swi from 0x{:08x}", epc),
MachineSoftwareInterrupt(epc) => write!(f, "Machine swi at 0x{:08x}", epc),
UserTimerInterrupt(epc) => write!(f, "User timer interrupt at 0x{:08x}", epc),
SupervisorTimerInterrupt(epc) => {
write!(f, "Supervisor timer interrupt at 0x{:08x}", epc)
}
MachineTimerInterrupt(epc) => write!(f, "Machine timer interrupt at 0x{:08x}", epc),
UserExternalInterrupt(epc) => write!(f, "User external interrupt at 0x{:08x}", epc),
SupervisorExternalInterrupt(epc) => {
write!(f, "Machine external interrupt at 0x{:08x}", epc)
}
MachineExternalInterrupt(epc) => {
write!(f, "Supervisor external interrupt at 0x{:08x}", epc)
}
ReservedInterrupt(code, epc) => {
write!(f, "Reserved interrupt 0x{:08x} at 0x{:08x}", code, epc)
}
InstructionAddressMisaligned(epc, mtval) => write!(
f,
"Misaligned address instruction 0x{:08x} at 0x{:08x}",
mtval, epc
),
InstructionAccessFault(epc, mtval) => write!(
f,
"Instruction access fault to 0x{:08x} at 0x{:08x}",
mtval, epc
),
IllegalInstruction(epc, mtval) => {
write!(f, "Illegal instruction 0x{:08x} at 0x{:08x}", mtval, epc)
}
Breakpoint(epc) => write!(f, "Breakpoint at 0x{:08x}", epc),
LoadAddressMisaligned(epc, mtval) => write!(
f,
"Misaligned load address of 0x{:08x} at 0x{:08x}",
mtval, epc
),
LoadAccessFault(epc, mtval) => {
write!(f, "Load access fault from 0x{:08x} at 0x{:08x}", mtval, epc)
}
StoreAddressMisaligned(epc, mtval) => write!(
f,
"Misaligned store address of 0x{:08x} at 0x{:08x}",
mtval, epc
),
StoreAccessFault(epc, mtval) => {
write!(f, "Store access fault to 0x{:08x} at 0x{:08x}", mtval, epc)
}
CallFromUMode(epc) => write!(f, "Call from User mode at 0x{:08x}", epc),
CallFromSMode(epc) => write!(f, "Call from Supervisor mode at 0x{:08x}", epc),
CallFromMMode(epc) => write!(f, "Call from Machine mode at 0x{:08x}", epc),
InstructionPageFault(epc, mtval) => write!(
f,
"Instruction page fault of 0x{:08x} at 0x{:08x}",
mtval, epc
),
LoadPageFault(epc, mtval) => {
write!(f, "Load page fault of 0x{:08x} at 0x{:08x}", mtval, epc)
}
StorePageFault(epc, mtval) => {
write!(f, "Load page fault of 0x{:08x} at 0x{:08x}", mtval, epc)
}
ReservedFault(code, epc, mtval) => write!(
f,
"Reserved interrupt 0x{:08x} with cause 0x{:08x} at 0x{:08x}",
code, mtval, epc
),
}
}
}
impl RiscvException {
pub fn from_regs(mcause: u32, mepc: u32, mtval: u32) -> RiscvException {
use RiscvException::*;
if mepc == 0 && mtval == 0 {
return NoException;
}
match mcause {
0x8000_0000 => UserSoftwareInterrupt(mepc),
0x8000_0001 => SupervisorSoftwareInterrupt(mepc),
0x8000_0003 => MachineSoftwareInterrupt(mepc),
0x8000_0004 => UserTimerInterrupt(mepc),
0x8000_0005 => SupervisorTimerInterrupt(mepc),
0x8000_0007 => MachineTimerInterrupt(mepc),
0x8000_0008 => UserExternalInterrupt(mepc),
0x8000_0009 => SupervisorExternalInterrupt(mepc),
0x8000_000b => MachineExternalInterrupt(mepc),
x @ 0x8000_0002 | x @ 0x8000_0006 | x @ 0x8000_000a | x @ 0x8000_000c..=0xffff_ffff => {
ReservedInterrupt(x & 0x7fff_ffff, mepc)
}
0 => InstructionAddressMisaligned(mepc, mtval),
1 => InstructionAccessFault(mepc, mtval),
2 => IllegalInstruction(mepc, mtval),
3 => Breakpoint(mepc),
4 => LoadAddressMisaligned(mepc, mtval),
5 => LoadAccessFault(mepc, mtval),
6 => StoreAddressMisaligned(mepc, mtval),
7 => StoreAccessFault(mepc, mtval),
8 => CallFromUMode(mepc),
9 => CallFromSMode(mepc),
11 => CallFromMMode(mepc),
12 => InstructionPageFault(mepc, mtval),
13 => LoadPageFault(mepc, mtval),
15 => StorePageFault(mepc, mtval),
x @ 10 | x @ 14 | x @ 16..=0x7fff_ffff => ReservedFault(x, mepc, mtval),
}
}
}