1#[cfg(test)]
4mod tests;
5
6use core::hint::unreachable_unchecked;
7use core::marker::{Destruct, PhantomData};
8use core::ops::{
9 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Shl, Shr,
10 Sub, SubAssign,
11};
12use core::{fmt, ptr};
13
14pub const trait RegType
18where
19 Self: const Default
20 + const Destruct
21 + const From<bool>
22 + const From<u8>
23 + const From<u16>
24 + const From<u32>
25 + const Eq
26 + const Ord
27 + const Add<Output = Self>
28 + const AddAssign
29 + const Sub<Output = Self>
30 + const SubAssign
31 + const BitAnd<Output = Self>
32 + const BitAndAssign
33 + const BitOr<Output = Self>
34 + const BitOrAssign
35 + const BitXor<Output = Self>
36 + const BitXorAssign
37 + const Not<Output = Self>
38 + const Shl<u8, Output = Self>
39 + const Shl<u16, Output = Self>
40 + const Shl<u32, Output = Self>
41 + const Shl<i32, Output = Self>
42 + const Shr<u8, Output = Self>
43 + const Shr<u16, Output = Self>
44 + const Shr<u32, Output = Self>
45 + const Shr<i32, Output = Self>
46 + fmt::Display
47 + fmt::LowerHex
48 + fmt::UpperHex
49 + fmt::Debug
50 + Copy
51 + Send
52 + Sync
53 + Sized
54 + 'static,
55{
56 const BITS: u8;
58
59 fn as_u64(&self) -> u64;
61
62 fn truncate_from_u64(value: u64) -> Self;
64
65 fn as_i64(&self) -> i64;
67
68 fn wrapping_add_signed(&self, offset: i32) -> Self;
70}
71
72const impl RegType for u32 {
73 const BITS: u8 = u32::BITS as u8;
74
75 #[inline(always)]
76 fn as_u64(&self) -> u64 {
77 u64::from(*self)
78 }
79
80 #[inline(always)]
81 fn truncate_from_u64(value: u64) -> Self {
82 value as Self
83 }
84
85 #[inline(always)]
86 fn as_i64(&self) -> i64 {
87 i64::from(self.cast_signed())
88 }
89
90 #[inline(always)]
91 fn wrapping_add_signed(&self, offset: i32) -> Self {
92 u32::wrapping_add_signed(*self, offset)
93 }
94}
95
96const impl RegType for u64 {
97 const BITS: u8 = u64::BITS as u8;
98
99 #[inline(always)]
100 fn as_u64(&self) -> u64 {
101 *self
102 }
103
104 #[inline(always)]
105 fn truncate_from_u64(value: u64) -> Self {
106 value
107 }
108
109 #[inline(always)]
110 fn as_i64(&self) -> i64 {
111 self.cast_signed()
112 }
113
114 #[inline(always)]
115 fn wrapping_add_signed(&self, offset: i32) -> Self {
116 u64::wrapping_add_signed(*self, i64::from(offset))
117 }
118}
119
120pub const trait Register:
122 fmt::Display
123 + fmt::Debug
124 + const Default
125 + const Eq
126 + const Destruct
127 + Copy
128 + Send
129 + Sync
130 + Sized
131 + 'static
132{
133 const XLEN: u8 = Self::Type::BITS;
136 const ZERO: Self;
138 const SP: Self;
140 const RA: Self;
142 const A0: Self;
144 const A1: Self;
146 type Type: const RegType;
150
151 fn from_bits(bits: u8) -> Option<Self>;
153}
154
155#[derive(Clone, Copy)]
159#[derive_const(Default)]
160#[repr(u8)]
161pub enum EReg<Type> {
162 #[default]
164 Zero = 0,
165 Ra = 1,
167 Sp = 2,
169 Gp = 3,
171 Tp = 4,
173 T0 = 5,
175 T1 = 6,
177 T2 = 7,
179 S0 = 8,
181 S1 = 9,
183 A0 = 10,
185 A1 = 11,
187 A2 = 12,
189 A3 = 13,
191 A4 = 14,
193 A5 = 15,
195 #[doc(hidden)]
197 Phantom(PhantomData<(!, Type)>),
198}
199
200impl<Type> fmt::Display for EReg<Type> {
201 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
202 match self {
203 Self::Zero => write!(f, "zero"),
204 Self::Ra => write!(f, "ra"),
205 Self::Sp => write!(f, "sp"),
206 Self::Gp => write!(f, "gp"),
207 Self::Tp => write!(f, "tp"),
208 Self::T0 => write!(f, "t0"),
209 Self::T1 => write!(f, "t1"),
210 Self::T2 => write!(f, "t2"),
211 Self::S0 => write!(f, "s0"),
212 Self::S1 => write!(f, "s1"),
213 Self::A0 => write!(f, "a0"),
214 Self::A1 => write!(f, "a1"),
215 Self::A2 => write!(f, "a2"),
216 Self::A3 => write!(f, "a3"),
217 Self::A4 => write!(f, "a4"),
218 Self::A5 => write!(f, "a5"),
219 Self::Phantom(_) => {
220 unsafe { unreachable_unchecked() }
222 }
223 }
224 }
225}
226
227impl<Type> fmt::Debug for EReg<Type> {
228 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
229 fmt::Display::fmt(self, f)
230 }
231}
232
233const impl<Type> PartialEq for EReg<Type> {
234 #[inline(always)]
235 fn eq(&self, other: &Self) -> bool {
236 unsafe { *ptr::from_ref(self).cast::<u8>() == *ptr::from_ref(other).cast::<u8>() }
238 }
239}
240
241const impl<Type> Eq for EReg<Type> {}
242
243const impl Register for EReg<u32> {
244 const ZERO: Self = Self::Zero;
245 const SP: Self = Self::Sp;
246 const RA: Self = Self::Ra;
247 const A0: Self = Self::A0;
248 const A1: Self = Self::A1;
249 type Type = u32;
250
251 #[inline(always)]
252 fn from_bits(bits: u8) -> Option<Self> {
253 match bits {
254 0 => Some(Self::Zero),
255 1 => Some(Self::Ra),
256 2 => Some(Self::Sp),
257 3 => Some(Self::Gp),
258 4 => Some(Self::Tp),
259 5 => Some(Self::T0),
260 6 => Some(Self::T1),
261 7 => Some(Self::T2),
262 8 => Some(Self::S0),
263 9 => Some(Self::S1),
264 10 => Some(Self::A0),
265 11 => Some(Self::A1),
266 12 => Some(Self::A2),
267 13 => Some(Self::A3),
268 14 => Some(Self::A4),
269 15 => Some(Self::A5),
270 _ => None,
271 }
272 }
273}
274
275const impl Register for EReg<u64> {
276 const ZERO: Self = Self::Zero;
277 const SP: Self = Self::Sp;
278 const RA: Self = Self::Ra;
279 const A0: Self = Self::A0;
280 const A1: Self = Self::A1;
281 type Type = u64;
282
283 #[inline(always)]
284 fn from_bits(bits: u8) -> Option<Self> {
285 match bits {
286 0 => Some(Self::Zero),
287 1 => Some(Self::Ra),
288 2 => Some(Self::Sp),
289 3 => Some(Self::Gp),
290 4 => Some(Self::Tp),
291 5 => Some(Self::T0),
292 6 => Some(Self::T1),
293 7 => Some(Self::T2),
294 8 => Some(Self::S0),
295 9 => Some(Self::S1),
296 10 => Some(Self::A0),
297 11 => Some(Self::A1),
298 12 => Some(Self::A2),
299 13 => Some(Self::A3),
300 14 => Some(Self::A4),
301 15 => Some(Self::A5),
302 _ => None,
303 }
304 }
305}
306
307#[derive(Clone, Copy)]
311#[derive_const(Default)]
312#[repr(u8)]
313pub enum Reg<Type> {
314 #[default]
316 Zero = 0,
317 Ra = 1,
319 Sp = 2,
321 Gp = 3,
323 Tp = 4,
325 T0 = 5,
327 T1 = 6,
329 T2 = 7,
331 S0 = 8,
333 S1 = 9,
335 A0 = 10,
337 A1 = 11,
339 A2 = 12,
341 A3 = 13,
343 A4 = 14,
345 A5 = 15,
347 A6 = 16,
349 A7 = 17,
351 S2 = 18,
353 S3 = 19,
355 S4 = 20,
357 S5 = 21,
359 S6 = 22,
361 S7 = 23,
363 S8 = 24,
365 S9 = 25,
367 S10 = 26,
369 S11 = 27,
371 T3 = 28,
373 T4 = 29,
375 T5 = 30,
377 T6 = 31,
379 #[doc(hidden)]
381 Phantom(PhantomData<(!, Type)>),
382}
383
384const impl<Type> From<EReg<u64>> for Reg<Type> {
385 #[inline(always)]
386 fn from(reg: EReg<u64>) -> Self {
387 match reg {
388 EReg::Zero => Self::Zero,
389 EReg::Ra => Self::Ra,
390 EReg::Sp => Self::Sp,
391 EReg::Gp => Self::Gp,
392 EReg::Tp => Self::Tp,
393 EReg::T0 => Self::T0,
394 EReg::T1 => Self::T1,
395 EReg::T2 => Self::T2,
396 EReg::S0 => Self::S0,
397 EReg::S1 => Self::S1,
398 EReg::A0 => Self::A0,
399 EReg::A1 => Self::A1,
400 EReg::A2 => Self::A2,
401 EReg::A3 => Self::A3,
402 EReg::A4 => Self::A4,
403 EReg::A5 => Self::A5,
404 EReg::Phantom(_) => {
405 unsafe { unreachable_unchecked() }
407 }
408 }
409 }
410}
411
412impl<Type> fmt::Display for Reg<Type> {
413 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
414 match self {
415 Self::Zero => write!(f, "zero"),
416 Self::Ra => write!(f, "ra"),
417 Self::Sp => write!(f, "sp"),
418 Self::Gp => write!(f, "gp"),
419 Self::Tp => write!(f, "tp"),
420 Self::T0 => write!(f, "t0"),
421 Self::T1 => write!(f, "t1"),
422 Self::T2 => write!(f, "t2"),
423 Self::S0 => write!(f, "s0"),
424 Self::S1 => write!(f, "s1"),
425 Self::A0 => write!(f, "a0"),
426 Self::A1 => write!(f, "a1"),
427 Self::A2 => write!(f, "a2"),
428 Self::A3 => write!(f, "a3"),
429 Self::A4 => write!(f, "a4"),
430 Self::A5 => write!(f, "a5"),
431 Self::A6 => write!(f, "a6"),
432 Self::A7 => write!(f, "a7"),
433 Self::S2 => write!(f, "s2"),
434 Self::S3 => write!(f, "s3"),
435 Self::S4 => write!(f, "s4"),
436 Self::S5 => write!(f, "s5"),
437 Self::S6 => write!(f, "s6"),
438 Self::S7 => write!(f, "s7"),
439 Self::S8 => write!(f, "s8"),
440 Self::S9 => write!(f, "s9"),
441 Self::S10 => write!(f, "s10"),
442 Self::S11 => write!(f, "s11"),
443 Self::T3 => write!(f, "t3"),
444 Self::T4 => write!(f, "t4"),
445 Self::T5 => write!(f, "t5"),
446 Self::T6 => write!(f, "t6"),
447 Self::Phantom(_) => {
448 unsafe { unreachable_unchecked() }
450 }
451 }
452 }
453}
454
455impl<Type> fmt::Debug for Reg<Type> {
456 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
457 fmt::Display::fmt(self, f)
458 }
459}
460
461const impl<Type> PartialEq for Reg<Type> {
462 #[inline(always)]
463 fn eq(&self, other: &Self) -> bool {
464 unsafe { *ptr::from_ref(self).cast::<u8>() == *ptr::from_ref(other).cast::<u8>() }
466 }
467}
468
469const impl<Type> Eq for Reg<Type> {}
470
471const impl Register for Reg<u32> {
472 const ZERO: Self = Self::Zero;
473 const SP: Self = Self::Sp;
474 const RA: Self = Self::Ra;
475 const A0: Self = Self::A0;
476 const A1: Self = Self::A1;
477 type Type = u32;
478
479 #[inline(always)]
480 fn from_bits(bits: u8) -> Option<Self> {
481 match bits {
482 0 => Some(Self::Zero),
483 1 => Some(Self::Ra),
484 2 => Some(Self::Sp),
485 3 => Some(Self::Gp),
486 4 => Some(Self::Tp),
487 5 => Some(Self::T0),
488 6 => Some(Self::T1),
489 7 => Some(Self::T2),
490 8 => Some(Self::S0),
491 9 => Some(Self::S1),
492 10 => Some(Self::A0),
493 11 => Some(Self::A1),
494 12 => Some(Self::A2),
495 13 => Some(Self::A3),
496 14 => Some(Self::A4),
497 15 => Some(Self::A5),
498 16 => Some(Self::A6),
499 17 => Some(Self::A7),
500 18 => Some(Self::S2),
501 19 => Some(Self::S3),
502 20 => Some(Self::S4),
503 21 => Some(Self::S5),
504 22 => Some(Self::S6),
505 23 => Some(Self::S7),
506 24 => Some(Self::S8),
507 25 => Some(Self::S9),
508 26 => Some(Self::S10),
509 27 => Some(Self::S11),
510 28 => Some(Self::T3),
511 29 => Some(Self::T4),
512 30 => Some(Self::T5),
513 31 => Some(Self::T6),
514 _ => None,
515 }
516 }
517}
518
519const impl Register for Reg<u64> {
520 const ZERO: Self = Self::Zero;
521 const SP: Self = Self::Sp;
522 const RA: Self = Self::Ra;
523 const A0: Self = Self::A0;
524 const A1: Self = Self::A1;
525 type Type = u64;
526
527 #[inline(always)]
528 fn from_bits(bits: u8) -> Option<Self> {
529 match bits {
530 0 => Some(Self::Zero),
531 1 => Some(Self::Ra),
532 2 => Some(Self::Sp),
533 3 => Some(Self::Gp),
534 4 => Some(Self::Tp),
535 5 => Some(Self::T0),
536 6 => Some(Self::T1),
537 7 => Some(Self::T2),
538 8 => Some(Self::S0),
539 9 => Some(Self::S1),
540 10 => Some(Self::A0),
541 11 => Some(Self::A1),
542 12 => Some(Self::A2),
543 13 => Some(Self::A3),
544 14 => Some(Self::A4),
545 15 => Some(Self::A5),
546 16 => Some(Self::A6),
547 17 => Some(Self::A7),
548 18 => Some(Self::S2),
549 19 => Some(Self::S3),
550 20 => Some(Self::S4),
551 21 => Some(Self::S5),
552 22 => Some(Self::S6),
553 23 => Some(Self::S7),
554 24 => Some(Self::S8),
555 25 => Some(Self::S9),
556 26 => Some(Self::S10),
557 27 => Some(Self::S11),
558 28 => Some(Self::T3),
559 29 => Some(Self::T4),
560 30 => Some(Self::T5),
561 31 => Some(Self::T6),
562 _ => None,
563 }
564 }
565}