ab_riscv_primitives/registers/
machine.rs1use crate::registers::general_purpose::{RegType, Register};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8#[repr(u16)]
9pub enum MCsr {
10 Mvendorid = 0xF11,
12 Marchid = 0xF12,
14 Mimpid = 0xF13,
16 Mhartid = 0xF14,
18
19 Mstatus = 0x300,
21 Misa = 0x301,
23 Mie = 0x304,
25 Mtvec = 0x305,
27
28 Mscratch = 0x340,
30 Mepc = 0x341,
32 Mcause = 0x342,
34 Mtval = 0x343,
36 Mip = 0x344,
38}
39
40impl MCsr {
41 #[inline(always)]
43 pub const fn from_index(index: u16) -> Option<Self> {
44 match index {
45 0xF11 => Some(Self::Mvendorid),
46 0xF12 => Some(Self::Marchid),
47 0xF13 => Some(Self::Mimpid),
48 0xF14 => Some(Self::Mhartid),
49 0x300 => Some(Self::Mstatus),
50 0x301 => Some(Self::Misa),
51 0x304 => Some(Self::Mie),
52 0x305 => Some(Self::Mtvec),
53 0x340 => Some(Self::Mscratch),
54 0x341 => Some(Self::Mepc),
55 0x342 => Some(Self::Mcause),
56 0x343 => Some(Self::Mtval),
57 0x344 => Some(Self::Mip),
58 _ => None,
59 }
60 }
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq)]
65#[repr(u32)]
66pub enum MCauseException {
67 InstructionAddressMisaligned = 0,
69 InstructionAccessFault = 1,
71 IllegalInstruction = 2,
73 Breakpoint = 3,
75 LoadAddressMisaligned = 4,
77 LoadAccessFault = 5,
79 StoreAddressMisaligned = 6,
81 StoreAccessFault = 7,
83 UserEnvironmentCall = 8,
85 SupervisorEnvironmentCall = 9,
87 MachineEnvironmentCall = 11,
89 InstructionPageFault = 12,
91 LoadPageFault = 13,
93 StorePageFault = 15,
95}
96
97impl MCauseException {
98 #[inline(always)]
101 pub const fn from_code(code: u64) -> Option<Self> {
102 match code {
103 0 => Some(Self::InstructionAddressMisaligned),
104 1 => Some(Self::InstructionAccessFault),
105 2 => Some(Self::IllegalInstruction),
106 3 => Some(Self::Breakpoint),
107 4 => Some(Self::LoadAddressMisaligned),
108 5 => Some(Self::LoadAccessFault),
109 6 => Some(Self::StoreAddressMisaligned),
110 7 => Some(Self::StoreAccessFault),
111 8 => Some(Self::UserEnvironmentCall),
112 9 => Some(Self::SupervisorEnvironmentCall),
113 11 => Some(Self::MachineEnvironmentCall),
114 12 => Some(Self::InstructionPageFault),
115 13 => Some(Self::LoadPageFault),
116 15 => Some(Self::StorePageFault),
117 _ => None,
118 }
119 }
120
121 #[inline(always)]
123 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
124 pub const fn to_raw<Reg>(self) -> Reg::Type
125 where
126 Reg: [const] Register,
127 {
128 Reg::Type::from(self as u32)
129 }
130}
131
132#[derive(Debug, Clone, Copy, PartialEq, Eq)]
134#[repr(u32)]
135pub enum MCauseInterrupt {
136 UserSoftware = 0,
138 SupervisorSoftware = 1,
140 MachineSoftware = 3,
142 UserTimer = 4,
144 SupervisorTimer = 5,
146 MachineTimer = 7,
148 UserExternal = 8,
150 SupervisorExternal = 9,
152 MachineExternal = 11,
154}
155
156impl MCauseInterrupt {
157 #[inline(always)]
160 pub const fn from_code(code: u64) -> Option<Self> {
161 match code {
162 0 => Some(Self::UserSoftware),
163 1 => Some(Self::SupervisorSoftware),
164 3 => Some(Self::MachineSoftware),
165 4 => Some(Self::UserTimer),
166 5 => Some(Self::SupervisorTimer),
167 7 => Some(Self::MachineTimer),
168 8 => Some(Self::UserExternal),
169 9 => Some(Self::SupervisorExternal),
170 11 => Some(Self::MachineExternal),
171 _ => None,
172 }
173 }
174
175 #[inline(always)]
177 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
178 pub const fn to_raw<Reg>(self) -> Reg::Type
179 where
180 Reg: [const] Register,
181 {
182 Reg::Type::from(self as u32) | (Reg::Type::from(1u8) << (Reg::XLEN - 1))
183 }
184}
185
186#[derive(Debug, Clone, Copy, PartialEq, Eq)]
188pub enum MCause {
189 Exception(MCauseException),
190 Interrupt(MCauseInterrupt),
191}
192
193impl From<MCauseException> for MCause {
194 #[inline(always)]
195 fn from(cause: MCauseException) -> Self {
196 Self::Exception(cause)
197 }
198}
199
200impl From<MCauseInterrupt> for MCause {
201 #[inline(always)]
202 fn from(cause: MCauseInterrupt) -> Self {
203 Self::Interrupt(cause)
204 }
205}
206
207impl MCause {
208 #[inline(always)]
210 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
211 pub const fn from_raw<Reg>(raw: Reg::Type) -> Option<Self>
212 where
213 Reg: [const] Register,
214 {
215 let raw = raw.as_u64();
216 let is_interrupt = (raw & (1u64 << (Reg::XLEN - 1))) != 0;
217 let code = raw & !(1u64 << (Reg::XLEN - 1));
218
219 if is_interrupt {
220 MCauseInterrupt::from_code(code).map(Self::Interrupt)
221 } else {
222 MCauseException::from_code(code).map(Self::Exception)
223 }
224 }
225
226 #[inline(always)]
228 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
229 pub const fn to_raw<Reg>(self) -> Reg::Type
230 where
231 Reg: [const] Register,
232 {
233 match self {
234 MCause::Exception(exception) => exception.to_raw::<Reg>(),
235 MCause::Interrupt(interrupt) => interrupt.to_raw::<Reg>(),
236 }
237 }
238}