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
20 Mstatus = 0x300,
22 Misa = 0x301,
24 Mie = 0x304,
26 Mtvec = 0x305,
28 Mstatush = 0x310,
30 Mcountinhibit = 0x320,
32
33 Mscratch = 0x340,
35 Mepc = 0x341,
37 Mcause = 0x342,
39 Mtval = 0x343,
41 Mip = 0x344,
43}
44
45impl MCsr {
46 #[inline(always)]
48 pub const fn from_index(index: u16) -> Option<Self> {
49 match index {
50 0xF11 => Some(Self::Mvendorid),
51 0xF12 => Some(Self::Marchid),
52 0xF13 => Some(Self::Mimpid),
53 0xF14 => Some(Self::Mhartid),
54 0x300 => Some(Self::Mstatus),
55 0x301 => Some(Self::Misa),
56 0x304 => Some(Self::Mie),
57 0x305 => Some(Self::Mtvec),
58 0x310 => Some(Self::Mstatush),
59 0x320 => Some(Self::Mcountinhibit),
60 0x340 => Some(Self::Mscratch),
61 0x341 => Some(Self::Mepc),
62 0x342 => Some(Self::Mcause),
63 0x343 => Some(Self::Mtval),
64 0x344 => Some(Self::Mip),
65 _ => None,
66 }
67 }
68}
69
70#[derive(Debug, Clone, Copy)]
72#[derive_const(PartialEq, Eq)]
73#[repr(u32)]
74pub enum MCauseException {
75 InstructionAddressMisaligned = 0,
77 InstructionAccessFault = 1,
79 IllegalInstruction = 2,
81 Breakpoint = 3,
83 LoadAddressMisaligned = 4,
85 LoadAccessFault = 5,
87 StoreAddressMisaligned = 6,
89 StoreAccessFault = 7,
91 UserEnvironmentCall = 8,
93 SupervisorEnvironmentCall = 9,
95 MachineEnvironmentCall = 11,
97 InstructionPageFault = 12,
99 LoadPageFault = 13,
101 StorePageFault = 15,
103}
104
105impl MCauseException {
106 #[inline(always)]
109 pub const fn from_code(code: u64) -> Option<Self> {
110 match code {
111 0 => Some(Self::InstructionAddressMisaligned),
112 1 => Some(Self::InstructionAccessFault),
113 2 => Some(Self::IllegalInstruction),
114 3 => Some(Self::Breakpoint),
115 4 => Some(Self::LoadAddressMisaligned),
116 5 => Some(Self::LoadAccessFault),
117 6 => Some(Self::StoreAddressMisaligned),
118 7 => Some(Self::StoreAccessFault),
119 8 => Some(Self::UserEnvironmentCall),
120 9 => Some(Self::SupervisorEnvironmentCall),
121 11 => Some(Self::MachineEnvironmentCall),
122 12 => Some(Self::InstructionPageFault),
123 13 => Some(Self::LoadPageFault),
124 15 => Some(Self::StorePageFault),
125 _ => None,
126 }
127 }
128
129 #[inline(always)]
131 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
132 pub const fn to_raw<Reg>(self) -> Reg::Type
133 where
134 Reg: [const] Register,
135 {
136 Reg::Type::from(self as u32)
137 }
138}
139
140#[derive(Debug, Clone, Copy)]
142#[derive_const(PartialEq, Eq)]
143#[repr(u32)]
144pub enum MCauseInterrupt {
145 UserSoftware = 0,
147 SupervisorSoftware = 1,
149 MachineSoftware = 3,
151 UserTimer = 4,
153 SupervisorTimer = 5,
155 MachineTimer = 7,
157 UserExternal = 8,
159 SupervisorExternal = 9,
161 MachineExternal = 11,
163}
164
165impl MCauseInterrupt {
166 #[inline(always)]
169 pub const fn from_code(code: u64) -> Option<Self> {
170 match code {
171 0 => Some(Self::UserSoftware),
172 1 => Some(Self::SupervisorSoftware),
173 3 => Some(Self::MachineSoftware),
174 4 => Some(Self::UserTimer),
175 5 => Some(Self::SupervisorTimer),
176 7 => Some(Self::MachineTimer),
177 8 => Some(Self::UserExternal),
178 9 => Some(Self::SupervisorExternal),
179 11 => Some(Self::MachineExternal),
180 _ => None,
181 }
182 }
183
184 #[inline(always)]
186 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
187 pub const fn to_raw<Reg>(self) -> Reg::Type
188 where
189 Reg: [const] Register,
190 {
191 Reg::Type::from(self as u32) | (Reg::Type::from(1u8) << (Reg::XLEN - 1))
192 }
193}
194
195#[derive(Debug, Clone, Copy)]
197#[derive_const(PartialEq, Eq)]
198pub enum MCause {
199 Exception(MCauseException),
200 Interrupt(MCauseInterrupt),
201}
202
203impl From<MCauseException> for MCause {
204 #[inline(always)]
205 fn from(cause: MCauseException) -> Self {
206 Self::Exception(cause)
207 }
208}
209
210impl From<MCauseInterrupt> for MCause {
211 #[inline(always)]
212 fn from(cause: MCauseInterrupt) -> Self {
213 Self::Interrupt(cause)
214 }
215}
216
217impl MCause {
218 #[inline(always)]
220 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
221 pub const fn from_raw<Reg>(raw: Reg::Type) -> Option<Self>
222 where
223 Reg: [const] Register,
224 {
225 let raw = raw.as_u64();
226 let is_interrupt = (raw & (1u64 << (Reg::XLEN - 1))) != 0;
227 let code = raw & !(1u64 << (Reg::XLEN - 1));
228
229 if is_interrupt {
230 MCauseInterrupt::from_code(code).map(Self::Interrupt)
231 } else {
232 MCauseException::from_code(code).map(Self::Exception)
233 }
234 }
235
236 #[inline(always)]
238 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
239 pub const fn to_raw<Reg>(self) -> Reg::Type
240 where
241 Reg: [const] Register,
242 {
243 match self {
244 MCause::Exception(exception) => exception.to_raw::<Reg>(),
245 MCause::Interrupt(interrupt) => interrupt.to_raw::<Reg>(),
246 }
247 }
248}