1#[cfg(test)]
4mod tests;
5
6use crate::registers::general_purpose::private::PhantomRegister;
7use core::fmt;
8use core::hint::unreachable_unchecked;
9use core::marker::Destruct;
10use core::ops::{
11 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Shl, Shr,
12 Sub, SubAssign,
13};
14
15mod private {
16 use core::marker::PhantomData;
17
18 #[derive(Debug, Clone, Copy)]
19 pub struct PhantomRegister<Type>(PhantomData<Type>);
20}
21
22pub const trait RegType
26where
27 Self: [const] Default
28 + [const] From<bool>
29 + [const] From<u8>
30 + [const] From<u16>
31 + [const] From<u32>
32 + [const] Eq
33 + [const] Ord
34 + [const] Add<Output = Self>
35 + [const] AddAssign
36 + [const] Sub<Output = Self>
37 + [const] SubAssign
38 + [const] BitAnd<Output = Self>
39 + [const] BitAndAssign
40 + [const] BitOr<Output = Self>
41 + [const] BitOrAssign
42 + [const] BitXor<Output = Self>
43 + [const] BitXorAssign
44 + [const] Not<Output = Self>
45 + [const] Shl<u8, Output = Self>
46 + [const] Shl<u16, Output = Self>
47 + [const] Shl<u32, Output = Self>
48 + [const] Shl<i32, Output = Self>
49 + [const] Shr<u8, Output = Self>
50 + [const] Shr<u16, Output = Self>
51 + [const] Shr<u32, Output = Self>
52 + [const] Shr<i32, Output = Self>
53 + fmt::Display
54 + fmt::LowerHex
55 + fmt::UpperHex
56 + fmt::Debug
57 + Copy
58 + Send
59 + Sync
60 + Sized
61 + 'static,
62{
63 fn as_u64(&self) -> u64;
65}
66
67impl const RegType for u32 {
68 #[inline(always)]
69 fn as_u64(&self) -> u64 {
70 u64::from(*self)
71 }
72}
73
74impl const RegType for u64 {
75 #[inline(always)]
76 fn as_u64(&self) -> u64 {
77 *self
78 }
79}
80
81pub const unsafe trait Register:
86 fmt::Display + fmt::Debug + [const] Eq + [const] Destruct + Copy + Send + Sync + Sized + 'static
87{
88 const N: usize;
92 const XLEN: u8 = size_of::<Self::Type>() as u8 * u8::BITS as u8;
94 type Type: [const] RegType;
98
99 fn is_zero(&self) -> bool;
101
102 fn from_bits(bits: u8) -> Option<Self>;
104
105 fn offset(self) -> usize;
107}
108
109#[derive(Debug, Clone, Copy)]
111#[repr(align(16))]
112pub struct Registers<Reg>
113where
114 Reg: Register,
115 [(); Reg::N]:,
116{
117 regs: [Reg::Type; Reg::N],
118}
119
120impl<Reg> Default for Registers<Reg>
121where
122 Reg: Register,
123 [(); Reg::N]:,
124{
125 #[inline(always)]
126 fn default() -> Self {
127 Self {
128 regs: [Reg::Type::default(); Reg::N],
129 }
130 }
131}
132
133const impl<Reg> Registers<Reg>
134where
135 Reg: Register + [const] Eq,
136 [(); Reg::N]:,
137{
138 #[inline(always)]
140 pub fn read(&self, reg: Reg) -> Reg::Type
141 where
142 Reg: [const] Register,
143 {
144 if reg.is_zero() {
145 return Reg::Type::default();
147 }
148
149 *unsafe { self.regs.get_unchecked(reg.offset()) }
151 }
152
153 #[inline(always)]
155 pub fn write(&mut self, reg: Reg, value: Reg::Type)
156 where
157 Reg: [const] Register,
158 {
159 if reg.is_zero() {
160 return;
162 }
163
164 *unsafe { self.regs.get_unchecked_mut(reg.offset()) } = value;
166 }
167}
168
169#[derive(Clone, Copy)]
173#[repr(u8)]
174pub enum EReg<Type> {
175 Zero = 0,
177 Ra = 1,
179 Sp = 2,
181 Gp = 3,
183 Tp = 4,
185 T0 = 5,
187 T1 = 6,
189 T2 = 7,
191 S0 = 8,
193 S1 = 9,
195 A0 = 10,
197 A1 = 11,
199 A2 = 12,
201 A3 = 13,
203 A4 = 14,
205 A5 = 15,
207 #[doc(hidden)]
209 Phantom(PhantomRegister<Type>),
210}
211
212impl<Type> fmt::Display for EReg<Type> {
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214 match self {
215 Self::Zero => write!(f, "zero"),
216 Self::Ra => write!(f, "ra"),
217 Self::Sp => write!(f, "sp"),
218 Self::Gp => write!(f, "gp"),
219 Self::Tp => write!(f, "tp"),
220 Self::T0 => write!(f, "t0"),
221 Self::T1 => write!(f, "t1"),
222 Self::T2 => write!(f, "t2"),
223 Self::S0 => write!(f, "s0"),
224 Self::S1 => write!(f, "s1"),
225 Self::A0 => write!(f, "a0"),
226 Self::A1 => write!(f, "a1"),
227 Self::A2 => write!(f, "a2"),
228 Self::A3 => write!(f, "a3"),
229 Self::A4 => write!(f, "a4"),
230 Self::A5 => write!(f, "a5"),
231 Self::Phantom(_) => {
232 unsafe { unreachable_unchecked() }
234 }
235 }
236 }
237}
238
239impl<Type> fmt::Debug for EReg<Type> {
240 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
241 fmt::Display::fmt(self, f)
242 }
243}
244
245impl<Type> const PartialEq for EReg<Type> {
246 #[inline(always)]
247 fn eq(&self, other: &Self) -> bool {
248 matches!(
250 (self, other),
251 (Self::Zero, Self::Zero)
252 | (Self::Ra, Self::Ra)
253 | (Self::Sp, Self::Sp)
254 | (Self::Gp, Self::Gp)
255 | (Self::Tp, Self::Tp)
256 | (Self::T0, Self::T0)
257 | (Self::T1, Self::T1)
258 | (Self::T2, Self::T2)
259 | (Self::S0, Self::S0)
260 | (Self::S1, Self::S1)
261 | (Self::A0, Self::A0)
262 | (Self::A1, Self::A1)
263 | (Self::A2, Self::A2)
264 | (Self::A3, Self::A3)
265 | (Self::A4, Self::A4)
266 | (Self::A5, Self::A5)
267 | (Self::Phantom(_), Self::Phantom(_))
268 )
269 }
270}
271
272impl<Type> const Eq for EReg<Type> {}
273
274unsafe impl const Register for EReg<u32> {
276 const N: usize = 16;
277 type Type = u32;
278
279 #[inline(always)]
280 fn is_zero(&self) -> bool {
281 matches!(self, Self::Zero)
282 }
283
284 #[inline(always)]
285 fn from_bits(bits: u8) -> Option<Self> {
286 match bits {
287 0 => Some(Self::Zero),
288 1 => Some(Self::Ra),
289 2 => Some(Self::Sp),
290 3 => Some(Self::Gp),
291 4 => Some(Self::Tp),
292 5 => Some(Self::T0),
293 6 => Some(Self::T1),
294 7 => Some(Self::T2),
295 8 => Some(Self::S0),
296 9 => Some(Self::S1),
297 10 => Some(Self::A0),
298 11 => Some(Self::A1),
299 12 => Some(Self::A2),
300 13 => Some(Self::A3),
301 14 => Some(Self::A4),
302 15 => Some(Self::A5),
303 _ => None,
304 }
305 }
306
307 #[inline(always)]
308 fn offset(self) -> usize {
309 usize::from(unsafe { core::mem::transmute::<Self, u8>(self) })
313 }
336}
337
338unsafe impl const Register for EReg<u64> {
340 const N: usize = 16;
341 type Type = u64;
342
343 #[inline(always)]
344 fn is_zero(&self) -> bool {
345 matches!(self, Self::Zero)
346 }
347
348 #[inline(always)]
349 fn from_bits(bits: u8) -> Option<Self> {
350 match bits {
351 0 => Some(Self::Zero),
352 1 => Some(Self::Ra),
353 2 => Some(Self::Sp),
354 3 => Some(Self::Gp),
355 4 => Some(Self::Tp),
356 5 => Some(Self::T0),
357 6 => Some(Self::T1),
358 7 => Some(Self::T2),
359 8 => Some(Self::S0),
360 9 => Some(Self::S1),
361 10 => Some(Self::A0),
362 11 => Some(Self::A1),
363 12 => Some(Self::A2),
364 13 => Some(Self::A3),
365 14 => Some(Self::A4),
366 15 => Some(Self::A5),
367 _ => None,
368 }
369 }
370
371 #[inline(always)]
372 fn offset(self) -> usize {
373 usize::from(unsafe { core::mem::transmute::<Self, u8>(self) })
377 }
400}
401
402#[derive(Clone, Copy)]
406#[repr(u8)]
407pub enum Reg<Type> {
408 Zero = 0,
410 Ra = 1,
412 Sp = 2,
414 Gp = 3,
416 Tp = 4,
418 T0 = 5,
420 T1 = 6,
422 T2 = 7,
424 S0 = 8,
426 S1 = 9,
428 A0 = 10,
430 A1 = 11,
432 A2 = 12,
434 A3 = 13,
436 A4 = 14,
438 A5 = 15,
440 A6 = 16,
442 A7 = 17,
444 S2 = 18,
446 S3 = 19,
448 S4 = 20,
450 S5 = 21,
452 S6 = 22,
454 S7 = 23,
456 S8 = 24,
458 S9 = 25,
460 S10 = 26,
462 S11 = 27,
464 T3 = 28,
466 T4 = 29,
468 T5 = 30,
470 T6 = 31,
472 #[doc(hidden)]
474 Phantom(PhantomRegister<Type>),
475}
476
477impl<Type> const From<EReg<u64>> for Reg<Type> {
478 #[inline(always)]
479 fn from(reg: EReg<u64>) -> Self {
480 match reg {
481 EReg::Zero => Self::Zero,
482 EReg::Ra => Self::Ra,
483 EReg::Sp => Self::Sp,
484 EReg::Gp => Self::Gp,
485 EReg::Tp => Self::Tp,
486 EReg::T0 => Self::T0,
487 EReg::T1 => Self::T1,
488 EReg::T2 => Self::T2,
489 EReg::S0 => Self::S0,
490 EReg::S1 => Self::S1,
491 EReg::A0 => Self::A0,
492 EReg::A1 => Self::A1,
493 EReg::A2 => Self::A2,
494 EReg::A3 => Self::A3,
495 EReg::A4 => Self::A4,
496 EReg::A5 => Self::A5,
497 EReg::Phantom(_) => {
498 unsafe { unreachable_unchecked() }
500 }
501 }
502 }
503}
504
505impl<Type> fmt::Display for Reg<Type> {
506 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
507 match self {
508 Self::Zero => write!(f, "zero"),
509 Self::Ra => write!(f, "ra"),
510 Self::Sp => write!(f, "sp"),
511 Self::Gp => write!(f, "gp"),
512 Self::Tp => write!(f, "tp"),
513 Self::T0 => write!(f, "t0"),
514 Self::T1 => write!(f, "t1"),
515 Self::T2 => write!(f, "t2"),
516 Self::S0 => write!(f, "s0"),
517 Self::S1 => write!(f, "s1"),
518 Self::A0 => write!(f, "a0"),
519 Self::A1 => write!(f, "a1"),
520 Self::A2 => write!(f, "a2"),
521 Self::A3 => write!(f, "a3"),
522 Self::A4 => write!(f, "a4"),
523 Self::A5 => write!(f, "a5"),
524 Self::A6 => write!(f, "a6"),
525 Self::A7 => write!(f, "a7"),
526 Self::S2 => write!(f, "s2"),
527 Self::S3 => write!(f, "s3"),
528 Self::S4 => write!(f, "s4"),
529 Self::S5 => write!(f, "s5"),
530 Self::S6 => write!(f, "s6"),
531 Self::S7 => write!(f, "s7"),
532 Self::S8 => write!(f, "s8"),
533 Self::S9 => write!(f, "s9"),
534 Self::S10 => write!(f, "s10"),
535 Self::S11 => write!(f, "s11"),
536 Self::T3 => write!(f, "t3"),
537 Self::T4 => write!(f, "t4"),
538 Self::T5 => write!(f, "t5"),
539 Self::T6 => write!(f, "t6"),
540 Self::Phantom(_) => {
541 unsafe { unreachable_unchecked() }
543 }
544 }
545 }
546}
547
548impl<Type> fmt::Debug for Reg<Type> {
549 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
550 fmt::Display::fmt(self, f)
551 }
552}
553
554impl<Type> const PartialEq for Reg<Type> {
555 #[inline(always)]
556 fn eq(&self, other: &Self) -> bool {
557 matches!(
559 (self, other),
560 (Self::Zero, Self::Zero)
561 | (Self::Ra, Self::Ra)
562 | (Self::Sp, Self::Sp)
563 | (Self::Gp, Self::Gp)
564 | (Self::Tp, Self::Tp)
565 | (Self::T0, Self::T0)
566 | (Self::T1, Self::T1)
567 | (Self::T2, Self::T2)
568 | (Self::S0, Self::S0)
569 | (Self::S1, Self::S1)
570 | (Self::A0, Self::A0)
571 | (Self::A1, Self::A1)
572 | (Self::A2, Self::A2)
573 | (Self::A3, Self::A3)
574 | (Self::A4, Self::A4)
575 | (Self::A5, Self::A5)
576 | (Self::A6, Self::A6)
577 | (Self::A7, Self::A7)
578 | (Self::S2, Self::S2)
579 | (Self::S3, Self::S3)
580 | (Self::S4, Self::S4)
581 | (Self::S5, Self::S5)
582 | (Self::S6, Self::S6)
583 | (Self::S7, Self::S7)
584 | (Self::S8, Self::S8)
585 | (Self::S9, Self::S9)
586 | (Self::S10, Self::S10)
587 | (Self::S11, Self::S11)
588 | (Self::T3, Self::T3)
589 | (Self::T4, Self::T4)
590 | (Self::T5, Self::T5)
591 | (Self::T6, Self::T6)
592 | (Self::Phantom(_), Self::Phantom(_))
593 )
594 }
595}
596
597impl<Type> const Eq for Reg<Type> {}
598
599unsafe impl const Register for Reg<u32> {
601 const N: usize = 32;
602 type Type = u32;
603
604 #[inline(always)]
605 fn is_zero(&self) -> bool {
606 matches!(self, Self::Zero)
607 }
608
609 #[inline(always)]
610 fn from_bits(bits: u8) -> Option<Self> {
611 match bits {
612 0 => Some(Self::Zero),
613 1 => Some(Self::Ra),
614 2 => Some(Self::Sp),
615 3 => Some(Self::Gp),
616 4 => Some(Self::Tp),
617 5 => Some(Self::T0),
618 6 => Some(Self::T1),
619 7 => Some(Self::T2),
620 8 => Some(Self::S0),
621 9 => Some(Self::S1),
622 10 => Some(Self::A0),
623 11 => Some(Self::A1),
624 12 => Some(Self::A2),
625 13 => Some(Self::A3),
626 14 => Some(Self::A4),
627 15 => Some(Self::A5),
628 16 => Some(Self::A6),
629 17 => Some(Self::A7),
630 18 => Some(Self::S2),
631 19 => Some(Self::S3),
632 20 => Some(Self::S4),
633 21 => Some(Self::S5),
634 22 => Some(Self::S6),
635 23 => Some(Self::S7),
636 24 => Some(Self::S8),
637 25 => Some(Self::S9),
638 26 => Some(Self::S10),
639 27 => Some(Self::S11),
640 28 => Some(Self::T3),
641 29 => Some(Self::T4),
642 30 => Some(Self::T5),
643 31 => Some(Self::T6),
644 _ => None,
645 }
646 }
647
648 #[inline(always)]
649 fn offset(self) -> usize {
650 usize::from(unsafe { core::mem::transmute::<Self, u8>(self) })
654 }
693}
694
695unsafe impl const Register for Reg<u64> {
697 const N: usize = 32;
698 type Type = u64;
699
700 #[inline(always)]
701 fn is_zero(&self) -> bool {
702 matches!(self, Self::Zero)
703 }
704
705 #[inline(always)]
706 fn from_bits(bits: u8) -> Option<Self> {
707 match bits {
708 0 => Some(Self::Zero),
709 1 => Some(Self::Ra),
710 2 => Some(Self::Sp),
711 3 => Some(Self::Gp),
712 4 => Some(Self::Tp),
713 5 => Some(Self::T0),
714 6 => Some(Self::T1),
715 7 => Some(Self::T2),
716 8 => Some(Self::S0),
717 9 => Some(Self::S1),
718 10 => Some(Self::A0),
719 11 => Some(Self::A1),
720 12 => Some(Self::A2),
721 13 => Some(Self::A3),
722 14 => Some(Self::A4),
723 15 => Some(Self::A5),
724 16 => Some(Self::A6),
725 17 => Some(Self::A7),
726 18 => Some(Self::S2),
727 19 => Some(Self::S3),
728 20 => Some(Self::S4),
729 21 => Some(Self::S5),
730 22 => Some(Self::S6),
731 23 => Some(Self::S7),
732 24 => Some(Self::S8),
733 25 => Some(Self::S9),
734 26 => Some(Self::S10),
735 27 => Some(Self::S11),
736 28 => Some(Self::T3),
737 29 => Some(Self::T4),
738 30 => Some(Self::T5),
739 31 => Some(Self::T6),
740 _ => None,
741 }
742 }
743
744 #[inline(always)]
745 fn offset(self) -> usize {
746 usize::from(unsafe { core::mem::transmute::<Self, u8>(self) })
750 }
789}