1#[cfg(test)]
2mod tests;
3
4use crate::registers::private::{PhantomRegister, RegisterInternal};
5use core::fmt;
6use core::hint::unreachable_unchecked;
7use core::marker::Destruct;
8use core::ops::{Add, AddAssign, Sub, SubAssign};
9
10mod private {
11 use core::marker::PhantomData;
12
13 pub const trait RegisterInternal<Type> {
14 fn is_zero(&self) -> bool;
16
17 fn offset(self) -> usize;
19 }
20
21 #[derive(Debug, Clone, Copy)]
22 pub struct PhantomRegister<Type>(PhantomData<Type>);
23}
24
25pub const trait Register:
27 fmt::Display
28 + fmt::Debug
29 + [const] Eq
30 + [const] RegisterInternal<Self::Type>
31 + [const] Destruct
32 + Copy
33 + Sized
34{
35 const N: usize;
39 type Type: [const] Default
43 + [const] From<u8>
44 + [const] Into<u64>
45 + [const] Eq
46 + [const] Add
47 + [const] AddAssign
48 + [const] Sub
49 + [const] SubAssign
50 + fmt::Display
51 + fmt::Debug
52 + Copy
53 + Sized;
54
55 fn from_bits(bits: u8) -> Option<Self>;
57}
58
59#[derive(Debug, Clone, Copy)]
61pub struct Registers<Reg>
62where
63 Reg: Register,
64 [(); Reg::N]:,
65{
66 regs: [Reg::Type; Reg::N],
67}
68
69impl<Reg> Default for Registers<Reg>
70where
71 Reg: Register,
72 [(); Reg::N]: Default,
73{
74 #[inline(always)]
75 fn default() -> Self {
76 Self {
77 regs: [Reg::Type::default(); Reg::N],
78 }
79 }
80}
81
82const impl<Reg> Registers<Reg>
83where
84 Reg: Register + [const] Eq,
85 [(); Reg::N]:,
86{
87 #[inline(always)]
88 pub fn read(&self, reg: Reg) -> Reg::Type
89 where
90 Reg: [const] Register,
91 {
92 if reg.is_zero() {
93 return Reg::Type::default();
95 }
96
97 *unsafe { self.regs.get_unchecked(reg.offset()) }
99 }
100
101 #[inline(always)]
102 pub fn write(&mut self, reg: Reg, value: Reg::Type)
103 where
104 Reg: [const] Register,
105 {
106 if reg.is_zero() {
107 return;
109 }
110
111 *unsafe { self.regs.get_unchecked_mut(reg.offset()) } = value;
113 }
114}
115
116#[derive(Clone, Copy)]
120#[repr(u8)]
121pub enum EReg<Type> {
122 Zero = 0,
124 Ra = 1,
126 Sp = 2,
128 Gp = 3,
130 Tp = 4,
132 T0 = 5,
134 T1 = 6,
136 T2 = 7,
138 S0 = 8,
140 S1 = 9,
142 A0 = 10,
144 A1 = 11,
146 A2 = 12,
148 A3 = 13,
150 A4 = 14,
152 A5 = 15,
154 #[doc(hidden)]
156 Phantom(PhantomRegister<Type>),
157}
158
159impl<Type> fmt::Display for EReg<Type> {
160 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161 match self {
162 Self::Zero => write!(f, "zero"),
163 Self::Ra => write!(f, "ra"),
164 Self::Sp => write!(f, "sp"),
165 Self::Gp => write!(f, "gp"),
166 Self::Tp => write!(f, "tp"),
167 Self::T0 => write!(f, "t0"),
168 Self::T1 => write!(f, "t1"),
169 Self::T2 => write!(f, "t2"),
170 Self::S0 => write!(f, "s0"),
171 Self::S1 => write!(f, "s1"),
172 Self::A0 => write!(f, "a0"),
173 Self::A1 => write!(f, "a1"),
174 Self::A2 => write!(f, "a2"),
175 Self::A3 => write!(f, "a3"),
176 Self::A4 => write!(f, "a4"),
177 Self::A5 => write!(f, "a5"),
178 Self::Phantom(_) => {
179 unsafe { unreachable_unchecked() }
181 }
182 }
183 }
184}
185
186impl<Type> fmt::Debug for EReg<Type> {
187 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
188 fmt::Display::fmt(self, f)
189 }
190}
191
192impl<Type> const PartialEq for EReg<Type> {
193 #[inline(always)]
194 fn eq(&self, other: &Self) -> bool {
195 matches!(
197 (self, other),
198 (Self::Zero, Self::Zero)
199 | (Self::Ra, Self::Ra)
200 | (Self::Sp, Self::Sp)
201 | (Self::Gp, Self::Gp)
202 | (Self::Tp, Self::Tp)
203 | (Self::T0, Self::T0)
204 | (Self::T1, Self::T1)
205 | (Self::T2, Self::T2)
206 | (Self::S0, Self::S0)
207 | (Self::S1, Self::S1)
208 | (Self::A0, Self::A0)
209 | (Self::A1, Self::A1)
210 | (Self::A2, Self::A2)
211 | (Self::A3, Self::A3)
212 | (Self::A4, Self::A4)
213 | (Self::A5, Self::A5)
214 | (Self::Phantom(_), Self::Phantom(_))
215 )
216 }
217}
218
219impl<Type> const Eq for EReg<Type> {}
220
221impl const RegisterInternal<u32> for EReg<u32> {
222 #[inline(always)]
223 fn is_zero(&self) -> bool {
224 matches!(self, Self::Zero)
225 }
226
227 #[inline(always)]
228 fn offset(self) -> usize {
229 usize::from(unsafe { core::mem::transmute::<Self, u8>(self) })
233 }
256}
257
258impl const RegisterInternal<u64> for EReg<u64> {
259 #[inline(always)]
260 fn is_zero(&self) -> bool {
261 matches!(self, Self::Zero)
262 }
263
264 #[inline(always)]
265 fn offset(self) -> usize {
266 usize::from(unsafe { core::mem::transmute::<Self, u8>(self) })
270 }
293}
294
295impl const Register for EReg<u32> {
296 const N: usize = 16;
297 type Type = u32;
298
299 #[inline(always)]
300 fn from_bits(bits: u8) -> Option<Self> {
301 match bits {
302 0 => Some(Self::Zero),
303 1 => Some(Self::Ra),
304 2 => Some(Self::Sp),
305 3 => Some(Self::Gp),
306 4 => Some(Self::Tp),
307 5 => Some(Self::T0),
308 6 => Some(Self::T1),
309 7 => Some(Self::T2),
310 8 => Some(Self::S0),
311 9 => Some(Self::S1),
312 10 => Some(Self::A0),
313 11 => Some(Self::A1),
314 12 => Some(Self::A2),
315 13 => Some(Self::A3),
316 14 => Some(Self::A4),
317 15 => Some(Self::A5),
318 _ => None,
319 }
320 }
321}
322
323impl const Register for EReg<u64> {
324 const N: usize = 16;
325 type Type = u64;
326
327 #[inline(always)]
328 fn from_bits(bits: u8) -> Option<Self> {
329 match bits {
330 0 => Some(Self::Zero),
331 1 => Some(Self::Ra),
332 2 => Some(Self::Sp),
333 3 => Some(Self::Gp),
334 4 => Some(Self::Tp),
335 5 => Some(Self::T0),
336 6 => Some(Self::T1),
337 7 => Some(Self::T2),
338 8 => Some(Self::S0),
339 9 => Some(Self::S1),
340 10 => Some(Self::A0),
341 11 => Some(Self::A1),
342 12 => Some(Self::A2),
343 13 => Some(Self::A3),
344 14 => Some(Self::A4),
345 15 => Some(Self::A5),
346 _ => None,
347 }
348 }
349}
350
351#[derive(Clone, Copy)]
355#[repr(u8)]
356pub enum Reg<Type> {
357 Zero = 0,
359 Ra = 1,
361 Sp = 2,
363 Gp = 3,
365 Tp = 4,
367 T0 = 5,
369 T1 = 6,
371 T2 = 7,
373 S0 = 8,
375 S1 = 9,
377 A0 = 10,
379 A1 = 11,
381 A2 = 12,
383 A3 = 13,
385 A4 = 14,
387 A5 = 15,
389 A6 = 16,
391 A7 = 17,
393 S2 = 18,
395 S3 = 19,
397 S4 = 20,
399 S5 = 21,
401 S6 = 22,
403 S7 = 23,
405 S8 = 24,
407 S9 = 25,
409 S10 = 26,
411 S11 = 27,
413 T3 = 28,
415 T4 = 29,
417 T5 = 30,
419 T6 = 31,
421 #[doc(hidden)]
423 Phantom(PhantomRegister<Type>),
424}
425
426impl<Type> const From<EReg<u64>> for Reg<Type> {
427 #[inline(always)]
428 fn from(reg: EReg<u64>) -> Self {
429 match reg {
430 EReg::Zero => Self::Zero,
431 EReg::Ra => Self::Ra,
432 EReg::Sp => Self::Sp,
433 EReg::Gp => Self::Gp,
434 EReg::Tp => Self::Tp,
435 EReg::T0 => Self::T0,
436 EReg::T1 => Self::T1,
437 EReg::T2 => Self::T2,
438 EReg::S0 => Self::S0,
439 EReg::S1 => Self::S1,
440 EReg::A0 => Self::A0,
441 EReg::A1 => Self::A1,
442 EReg::A2 => Self::A2,
443 EReg::A3 => Self::A3,
444 EReg::A4 => Self::A4,
445 EReg::A5 => Self::A5,
446 EReg::Phantom(_) => {
447 unsafe { unreachable_unchecked() }
449 }
450 }
451 }
452}
453
454impl<Type> fmt::Display for Reg<Type> {
455 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
456 match self {
457 Self::Zero => write!(f, "zero"),
458 Self::Ra => write!(f, "ra"),
459 Self::Sp => write!(f, "sp"),
460 Self::Gp => write!(f, "gp"),
461 Self::Tp => write!(f, "tp"),
462 Self::T0 => write!(f, "t0"),
463 Self::T1 => write!(f, "t1"),
464 Self::T2 => write!(f, "t2"),
465 Self::S0 => write!(f, "s0"),
466 Self::S1 => write!(f, "s1"),
467 Self::A0 => write!(f, "a0"),
468 Self::A1 => write!(f, "a1"),
469 Self::A2 => write!(f, "a2"),
470 Self::A3 => write!(f, "a3"),
471 Self::A4 => write!(f, "a4"),
472 Self::A5 => write!(f, "a5"),
473 Self::A6 => write!(f, "a6"),
474 Self::A7 => write!(f, "a7"),
475 Self::S2 => write!(f, "s2"),
476 Self::S3 => write!(f, "s3"),
477 Self::S4 => write!(f, "s4"),
478 Self::S5 => write!(f, "s5"),
479 Self::S6 => write!(f, "s6"),
480 Self::S7 => write!(f, "s7"),
481 Self::S8 => write!(f, "s8"),
482 Self::S9 => write!(f, "s9"),
483 Self::S10 => write!(f, "s10"),
484 Self::S11 => write!(f, "s11"),
485 Self::T3 => write!(f, "t3"),
486 Self::T4 => write!(f, "t4"),
487 Self::T5 => write!(f, "t5"),
488 Self::T6 => write!(f, "t6"),
489 Self::Phantom(_) => {
490 unsafe { unreachable_unchecked() }
492 }
493 }
494 }
495}
496
497impl<Type> fmt::Debug for Reg<Type> {
498 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
499 fmt::Display::fmt(self, f)
500 }
501}
502
503impl<Type> const PartialEq for Reg<Type> {
504 #[inline(always)]
505 fn eq(&self, other: &Self) -> bool {
506 matches!(
508 (self, other),
509 (Self::Zero, Self::Zero)
510 | (Self::Ra, Self::Ra)
511 | (Self::Sp, Self::Sp)
512 | (Self::Gp, Self::Gp)
513 | (Self::Tp, Self::Tp)
514 | (Self::T0, Self::T0)
515 | (Self::T1, Self::T1)
516 | (Self::T2, Self::T2)
517 | (Self::S0, Self::S0)
518 | (Self::S1, Self::S1)
519 | (Self::A0, Self::A0)
520 | (Self::A1, Self::A1)
521 | (Self::A2, Self::A2)
522 | (Self::A3, Self::A3)
523 | (Self::A4, Self::A4)
524 | (Self::A5, Self::A5)
525 | (Self::A6, Self::A6)
526 | (Self::A7, Self::A7)
527 | (Self::S2, Self::S2)
528 | (Self::S3, Self::S3)
529 | (Self::S4, Self::S4)
530 | (Self::S5, Self::S5)
531 | (Self::S6, Self::S6)
532 | (Self::S7, Self::S7)
533 | (Self::S8, Self::S8)
534 | (Self::S9, Self::S9)
535 | (Self::S10, Self::S10)
536 | (Self::S11, Self::S11)
537 | (Self::T3, Self::T3)
538 | (Self::T4, Self::T4)
539 | (Self::T5, Self::T5)
540 | (Self::T6, Self::T6)
541 | (Self::Phantom(_), Self::Phantom(_))
542 )
543 }
544}
545
546impl<Type> const Eq for Reg<Type> {}
547
548impl const RegisterInternal<u32> for Reg<u32> {
549 #[inline(always)]
550 fn is_zero(&self) -> bool {
551 matches!(self, Self::Zero)
552 }
553
554 #[inline(always)]
555 fn offset(self) -> usize {
556 usize::from(unsafe { core::mem::transmute::<Self, u8>(self) })
560 }
599}
600
601impl const RegisterInternal<u64> for Reg<u64> {
602 #[inline(always)]
603 fn is_zero(&self) -> bool {
604 matches!(self, Self::Zero)
605 }
606
607 #[inline(always)]
608 fn offset(self) -> usize {
609 usize::from(unsafe { core::mem::transmute::<Self, u8>(self) })
613 }
652}
653
654impl const Register for Reg<u32> {
655 const N: usize = 32;
656 type Type = u32;
657
658 #[inline(always)]
659 fn from_bits(bits: u8) -> Option<Self> {
660 match bits {
661 0 => Some(Self::Zero),
662 1 => Some(Self::Ra),
663 2 => Some(Self::Sp),
664 3 => Some(Self::Gp),
665 4 => Some(Self::Tp),
666 5 => Some(Self::T0),
667 6 => Some(Self::T1),
668 7 => Some(Self::T2),
669 8 => Some(Self::S0),
670 9 => Some(Self::S1),
671 10 => Some(Self::A0),
672 11 => Some(Self::A1),
673 12 => Some(Self::A2),
674 13 => Some(Self::A3),
675 14 => Some(Self::A4),
676 15 => Some(Self::A5),
677 16 => Some(Self::A6),
678 17 => Some(Self::A7),
679 18 => Some(Self::S2),
680 19 => Some(Self::S3),
681 20 => Some(Self::S4),
682 21 => Some(Self::S5),
683 22 => Some(Self::S6),
684 23 => Some(Self::S7),
685 24 => Some(Self::S8),
686 25 => Some(Self::S9),
687 26 => Some(Self::S10),
688 27 => Some(Self::S11),
689 28 => Some(Self::T3),
690 29 => Some(Self::T4),
691 30 => Some(Self::T5),
692 31 => Some(Self::T6),
693 _ => None,
694 }
695 }
696}
697
698impl const Register for Reg<u64> {
699 const N: usize = 32;
700 type Type = u64;
701
702 #[inline(always)]
703 fn from_bits(bits: u8) -> Option<Self> {
704 match bits {
705 0 => Some(Self::Zero),
706 1 => Some(Self::Ra),
707 2 => Some(Self::Sp),
708 3 => Some(Self::Gp),
709 4 => Some(Self::Tp),
710 5 => Some(Self::T0),
711 6 => Some(Self::T1),
712 7 => Some(Self::T2),
713 8 => Some(Self::S0),
714 9 => Some(Self::S1),
715 10 => Some(Self::A0),
716 11 => Some(Self::A1),
717 12 => Some(Self::A2),
718 13 => Some(Self::A3),
719 14 => Some(Self::A4),
720 15 => Some(Self::A5),
721 16 => Some(Self::A6),
722 17 => Some(Self::A7),
723 18 => Some(Self::S2),
724 19 => Some(Self::S3),
725 20 => Some(Self::S4),
726 21 => Some(Self::S5),
727 22 => Some(Self::S6),
728 23 => Some(Self::S7),
729 24 => Some(Self::S8),
730 25 => Some(Self::S9),
731 26 => Some(Self::S10),
732 27 => Some(Self::S11),
733 28 => Some(Self::T3),
734 29 => Some(Self::T4),
735 30 => Some(Self::T5),
736 31 => Some(Self::T6),
737 _ => None,
738 }
739 }
740}