ab_riscv_primitives/registers/
machine.rs1use crate::registers::general_purpose::{RegType, Register};
4
5#[derive(Debug, Clone, Copy)]
8#[derive_const(PartialEq, Eq)]
9#[repr(u16)]
10pub enum MCsr {
11 Mvendorid = 0xF11,
13 Marchid = 0xF12,
15 Mimpid = 0xF13,
17 Mhartid = 0xF14,
19 Mconfigptr = 0xF15,
21
22 Mstatus = 0x300,
24 Misa = 0x301,
26 Mie = 0x304,
28 Mtvec = 0x305,
30 Menvcfg = 0x30A,
32 Mstatush = 0x310,
34 Menvcfgh = 0x31A,
36 Mcountinhibit = 0x320,
38 Mseccfg = 0x747,
40 Mseccfgh = 0x757,
42
43 Mscratch = 0x340,
45 Mepc = 0x341,
47 Mcause = 0x342,
49 Mtval = 0x343,
51 Mip = 0x344,
53
54 Mcycle = 0xB00,
56 Minstret = 0xB02,
58 Mcycleh = 0xB80,
60 Minstreth = 0xB82,
62}
63
64impl MCsr {
65 #[inline(always)]
67 pub const fn from_index(index: u16) -> Option<Self> {
68 match index {
69 0xF11 => Some(Self::Mvendorid),
70 0xF12 => Some(Self::Marchid),
71 0xF13 => Some(Self::Mimpid),
72 0xF14 => Some(Self::Mhartid),
73 0xF15 => Some(Self::Mconfigptr),
74 0x300 => Some(Self::Mstatus),
75 0x301 => Some(Self::Misa),
76 0x304 => Some(Self::Mie),
77 0x305 => Some(Self::Mtvec),
78 0x30A => Some(Self::Menvcfg),
79 0x310 => Some(Self::Mstatush),
80 0x31A => Some(Self::Menvcfgh),
81 0x320 => Some(Self::Mcountinhibit),
82 0x747 => Some(Self::Mseccfg),
83 0x757 => Some(Self::Mseccfgh),
84 0x340 => Some(Self::Mscratch),
85 0x341 => Some(Self::Mepc),
86 0x342 => Some(Self::Mcause),
87 0x343 => Some(Self::Mtval),
88 0x344 => Some(Self::Mip),
89 0xB00 => Some(Self::Mcycle),
90 0xB02 => Some(Self::Minstret),
91 0xB80 => Some(Self::Mcycleh),
92 0xB82 => Some(Self::Minstreth),
93 _ => None,
94 }
95 }
96}
97
98#[derive(Debug, Clone, Copy)]
100#[derive_const(PartialEq, Eq)]
101#[repr(u32)]
102pub enum MCauseException {
103 InstructionAddressMisaligned = 0,
105 InstructionAccessFault = 1,
107 IllegalInstruction = 2,
109 Breakpoint = 3,
111 LoadAddressMisaligned = 4,
113 LoadAccessFault = 5,
115 StoreAddressMisaligned = 6,
117 StoreAccessFault = 7,
119 UserEnvironmentCall = 8,
121 SupervisorEnvironmentCall = 9,
123 MachineEnvironmentCall = 11,
125 InstructionPageFault = 12,
127 LoadPageFault = 13,
129 StorePageFault = 15,
131}
132
133impl MCauseException {
134 #[inline(always)]
137 pub const fn from_code(code: u64) -> Option<Self> {
138 match code {
139 0 => Some(Self::InstructionAddressMisaligned),
140 1 => Some(Self::InstructionAccessFault),
141 2 => Some(Self::IllegalInstruction),
142 3 => Some(Self::Breakpoint),
143 4 => Some(Self::LoadAddressMisaligned),
144 5 => Some(Self::LoadAccessFault),
145 6 => Some(Self::StoreAddressMisaligned),
146 7 => Some(Self::StoreAccessFault),
147 8 => Some(Self::UserEnvironmentCall),
148 9 => Some(Self::SupervisorEnvironmentCall),
149 11 => Some(Self::MachineEnvironmentCall),
150 12 => Some(Self::InstructionPageFault),
151 13 => Some(Self::LoadPageFault),
152 15 => Some(Self::StorePageFault),
153 _ => None,
154 }
155 }
156
157 #[inline(always)]
159 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
160 pub const fn to_raw<Reg>(self) -> Reg::Type
161 where
162 Reg: [const] Register,
163 {
164 Reg::Type::from(self as u32)
165 }
166}
167
168#[derive(Debug, Clone, Copy)]
170#[derive_const(PartialEq, Eq)]
171#[repr(u32)]
172pub enum MCauseInterrupt {
173 UserSoftware = 0,
175 SupervisorSoftware = 1,
177 MachineSoftware = 3,
179 UserTimer = 4,
181 SupervisorTimer = 5,
183 MachineTimer = 7,
185 UserExternal = 8,
187 SupervisorExternal = 9,
189 MachineExternal = 11,
191}
192
193impl MCauseInterrupt {
194 #[inline(always)]
197 pub const fn from_code(code: u64) -> Option<Self> {
198 match code {
199 0 => Some(Self::UserSoftware),
200 1 => Some(Self::SupervisorSoftware),
201 3 => Some(Self::MachineSoftware),
202 4 => Some(Self::UserTimer),
203 5 => Some(Self::SupervisorTimer),
204 7 => Some(Self::MachineTimer),
205 8 => Some(Self::UserExternal),
206 9 => Some(Self::SupervisorExternal),
207 11 => Some(Self::MachineExternal),
208 _ => None,
209 }
210 }
211
212 #[inline(always)]
214 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
215 pub const fn to_raw<Reg>(self) -> Reg::Type
216 where
217 Reg: [const] Register,
218 {
219 Reg::Type::from(self as u32) | (Reg::Type::from(1u8) << (Reg::XLEN - 1))
220 }
221}
222
223#[derive(Debug, Clone, Copy)]
225#[derive_const(PartialEq, Eq)]
226pub enum MCause {
227 Exception(MCauseException),
228 Interrupt(MCauseInterrupt),
229}
230
231impl From<MCauseException> for MCause {
232 #[inline(always)]
233 fn from(cause: MCauseException) -> Self {
234 Self::Exception(cause)
235 }
236}
237
238impl From<MCauseInterrupt> for MCause {
239 #[inline(always)]
240 fn from(cause: MCauseInterrupt) -> Self {
241 Self::Interrupt(cause)
242 }
243}
244
245impl MCause {
246 #[inline(always)]
248 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
249 pub const fn from_raw<Reg>(raw: Reg::Type) -> Option<Self>
250 where
251 Reg: [const] Register,
252 {
253 let raw = raw.as_u64();
254 let is_interrupt = (raw & (1u64 << (Reg::XLEN - 1))) != 0;
255 let code = raw & !(1u64 << (Reg::XLEN - 1));
256
257 if is_interrupt {
258 MCauseInterrupt::from_code(code).map(Self::Interrupt)
259 } else {
260 MCauseException::from_code(code).map(Self::Exception)
261 }
262 }
263
264 #[inline(always)]
266 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
267 pub const fn to_raw<Reg>(self) -> Reg::Type
268 where
269 Reg: [const] Register,
270 {
271 match self {
272 MCause::Exception(exception) => exception.to_raw::<Reg>(),
273 MCause::Interrupt(interrupt) => interrupt.to_raw::<Reg>(),
274 }
275 }
276}