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 const BITS: u8;
65
66 fn as_u64(&self) -> u64;
68
69 fn as_i64(&self) -> i64;
71}
72
73impl const RegType for u32 {
74 const BITS: u8 = u32::BITS as u8;
75
76 #[inline(always)]
77 fn as_u64(&self) -> u64 {
78 u64::from(*self)
79 }
80
81 #[inline(always)]
82 fn as_i64(&self) -> i64 {
83 i64::from(self.cast_signed())
84 }
85}
86
87impl const RegType for u64 {
88 const BITS: u8 = u64::BITS as u8;
89
90 #[inline(always)]
91 fn as_u64(&self) -> u64 {
92 *self
93 }
94
95 #[inline(always)]
96 fn as_i64(&self) -> i64 {
97 self.cast_signed()
98 }
99}
100
101pub const trait Register:
103 fmt::Display
104 + fmt::Debug
105 + [const] Default
106 + [const] Eq
107 + [const] Destruct
108 + Copy
109 + Send
110 + Sync
111 + Sized
112 + 'static
113{
114 const XLEN: u8 = Self::Type::BITS;
117 const ZERO: Self;
119 const SP: Self;
121 const RA: Self;
123 const A0: Self;
125 const A1: Self;
127 type Type: [const] RegType;
131
132 fn from_bits(bits: u8) -> Option<Self>;
134}
135
136#[derive(Clone, Copy)]
140#[repr(u8)]
141pub enum EReg<Type> {
142 Zero = 0,
144 Ra = 1,
146 Sp = 2,
148 Gp = 3,
150 Tp = 4,
152 T0 = 5,
154 T1 = 6,
156 T2 = 7,
158 S0 = 8,
160 S1 = 9,
162 A0 = 10,
164 A1 = 11,
166 A2 = 12,
168 A3 = 13,
170 A4 = 14,
172 A5 = 15,
174 #[doc(hidden)]
176 Phantom(PhantomRegister<Type>),
177}
178
179impl<Type> const Default for EReg<Type> {
180 #[inline(always)]
181 fn default() -> Self {
182 Self::Zero
183 }
184}
185
186impl<Type> fmt::Display for EReg<Type> {
187 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
188 match self {
189 Self::Zero => write!(f, "zero"),
190 Self::Ra => write!(f, "ra"),
191 Self::Sp => write!(f, "sp"),
192 Self::Gp => write!(f, "gp"),
193 Self::Tp => write!(f, "tp"),
194 Self::T0 => write!(f, "t0"),
195 Self::T1 => write!(f, "t1"),
196 Self::T2 => write!(f, "t2"),
197 Self::S0 => write!(f, "s0"),
198 Self::S1 => write!(f, "s1"),
199 Self::A0 => write!(f, "a0"),
200 Self::A1 => write!(f, "a1"),
201 Self::A2 => write!(f, "a2"),
202 Self::A3 => write!(f, "a3"),
203 Self::A4 => write!(f, "a4"),
204 Self::A5 => write!(f, "a5"),
205 Self::Phantom(_) => {
206 unsafe { unreachable_unchecked() }
208 }
209 }
210 }
211}
212
213impl<Type> fmt::Debug for EReg<Type> {
214 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215 fmt::Display::fmt(self, f)
216 }
217}
218
219impl<Type> const PartialEq for EReg<Type> {
220 #[inline(always)]
221 fn eq(&self, other: &Self) -> bool {
222 matches!(
224 (self, other),
225 (Self::Zero, Self::Zero)
226 | (Self::Ra, Self::Ra)
227 | (Self::Sp, Self::Sp)
228 | (Self::Gp, Self::Gp)
229 | (Self::Tp, Self::Tp)
230 | (Self::T0, Self::T0)
231 | (Self::T1, Self::T1)
232 | (Self::T2, Self::T2)
233 | (Self::S0, Self::S0)
234 | (Self::S1, Self::S1)
235 | (Self::A0, Self::A0)
236 | (Self::A1, Self::A1)
237 | (Self::A2, Self::A2)
238 | (Self::A3, Self::A3)
239 | (Self::A4, Self::A4)
240 | (Self::A5, Self::A5)
241 | (Self::Phantom(_), Self::Phantom(_))
242 )
243 }
244}
245
246impl<Type> const Eq for EReg<Type> {}
247
248impl const Register for EReg<u32> {
249 const ZERO: Self = Self::Zero;
250 const SP: Self = Self::Sp;
251 const RA: Self = Self::Ra;
252 const A0: Self = Self::A0;
253 const A1: Self = Self::A1;
254 type Type = u32;
255
256 #[inline(always)]
257 fn from_bits(bits: u8) -> Option<Self> {
258 match bits {
259 0 => Some(Self::Zero),
260 1 => Some(Self::Ra),
261 2 => Some(Self::Sp),
262 3 => Some(Self::Gp),
263 4 => Some(Self::Tp),
264 5 => Some(Self::T0),
265 6 => Some(Self::T1),
266 7 => Some(Self::T2),
267 8 => Some(Self::S0),
268 9 => Some(Self::S1),
269 10 => Some(Self::A0),
270 11 => Some(Self::A1),
271 12 => Some(Self::A2),
272 13 => Some(Self::A3),
273 14 => Some(Self::A4),
274 15 => Some(Self::A5),
275 _ => None,
276 }
277 }
278}
279
280impl const Register for EReg<u64> {
281 const ZERO: Self = Self::Zero;
282 const SP: Self = Self::Sp;
283 const RA: Self = Self::Ra;
284 const A0: Self = Self::A0;
285 const A1: Self = Self::A1;
286 type Type = u64;
287
288 #[inline(always)]
289 fn from_bits(bits: u8) -> Option<Self> {
290 match bits {
291 0 => Some(Self::Zero),
292 1 => Some(Self::Ra),
293 2 => Some(Self::Sp),
294 3 => Some(Self::Gp),
295 4 => Some(Self::Tp),
296 5 => Some(Self::T0),
297 6 => Some(Self::T1),
298 7 => Some(Self::T2),
299 8 => Some(Self::S0),
300 9 => Some(Self::S1),
301 10 => Some(Self::A0),
302 11 => Some(Self::A1),
303 12 => Some(Self::A2),
304 13 => Some(Self::A3),
305 14 => Some(Self::A4),
306 15 => Some(Self::A5),
307 _ => None,
308 }
309 }
310}
311
312#[derive(Clone, Copy)]
316#[repr(u8)]
317pub enum Reg<Type> {
318 Zero = 0,
320 Ra = 1,
322 Sp = 2,
324 Gp = 3,
326 Tp = 4,
328 T0 = 5,
330 T1 = 6,
332 T2 = 7,
334 S0 = 8,
336 S1 = 9,
338 A0 = 10,
340 A1 = 11,
342 A2 = 12,
344 A3 = 13,
346 A4 = 14,
348 A5 = 15,
350 A6 = 16,
352 A7 = 17,
354 S2 = 18,
356 S3 = 19,
358 S4 = 20,
360 S5 = 21,
362 S6 = 22,
364 S7 = 23,
366 S8 = 24,
368 S9 = 25,
370 S10 = 26,
372 S11 = 27,
374 T3 = 28,
376 T4 = 29,
378 T5 = 30,
380 T6 = 31,
382 #[doc(hidden)]
384 Phantom(PhantomRegister<Type>),
385}
386
387impl<Type> const Default for Reg<Type> {
388 #[inline(always)]
389 fn default() -> Self {
390 Self::Zero
391 }
392}
393
394impl<Type> const From<EReg<u64>> for Reg<Type> {
395 #[inline(always)]
396 fn from(reg: EReg<u64>) -> Self {
397 match reg {
398 EReg::Zero => Self::Zero,
399 EReg::Ra => Self::Ra,
400 EReg::Sp => Self::Sp,
401 EReg::Gp => Self::Gp,
402 EReg::Tp => Self::Tp,
403 EReg::T0 => Self::T0,
404 EReg::T1 => Self::T1,
405 EReg::T2 => Self::T2,
406 EReg::S0 => Self::S0,
407 EReg::S1 => Self::S1,
408 EReg::A0 => Self::A0,
409 EReg::A1 => Self::A1,
410 EReg::A2 => Self::A2,
411 EReg::A3 => Self::A3,
412 EReg::A4 => Self::A4,
413 EReg::A5 => Self::A5,
414 EReg::Phantom(_) => {
415 unsafe { unreachable_unchecked() }
417 }
418 }
419 }
420}
421
422impl<Type> fmt::Display for Reg<Type> {
423 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
424 match self {
425 Self::Zero => write!(f, "zero"),
426 Self::Ra => write!(f, "ra"),
427 Self::Sp => write!(f, "sp"),
428 Self::Gp => write!(f, "gp"),
429 Self::Tp => write!(f, "tp"),
430 Self::T0 => write!(f, "t0"),
431 Self::T1 => write!(f, "t1"),
432 Self::T2 => write!(f, "t2"),
433 Self::S0 => write!(f, "s0"),
434 Self::S1 => write!(f, "s1"),
435 Self::A0 => write!(f, "a0"),
436 Self::A1 => write!(f, "a1"),
437 Self::A2 => write!(f, "a2"),
438 Self::A3 => write!(f, "a3"),
439 Self::A4 => write!(f, "a4"),
440 Self::A5 => write!(f, "a5"),
441 Self::A6 => write!(f, "a6"),
442 Self::A7 => write!(f, "a7"),
443 Self::S2 => write!(f, "s2"),
444 Self::S3 => write!(f, "s3"),
445 Self::S4 => write!(f, "s4"),
446 Self::S5 => write!(f, "s5"),
447 Self::S6 => write!(f, "s6"),
448 Self::S7 => write!(f, "s7"),
449 Self::S8 => write!(f, "s8"),
450 Self::S9 => write!(f, "s9"),
451 Self::S10 => write!(f, "s10"),
452 Self::S11 => write!(f, "s11"),
453 Self::T3 => write!(f, "t3"),
454 Self::T4 => write!(f, "t4"),
455 Self::T5 => write!(f, "t5"),
456 Self::T6 => write!(f, "t6"),
457 Self::Phantom(_) => {
458 unsafe { unreachable_unchecked() }
460 }
461 }
462 }
463}
464
465impl<Type> fmt::Debug for Reg<Type> {
466 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
467 fmt::Display::fmt(self, f)
468 }
469}
470
471impl<Type> const PartialEq for Reg<Type> {
472 #[inline(always)]
473 fn eq(&self, other: &Self) -> bool {
474 matches!(
476 (self, other),
477 (Self::Zero, Self::Zero)
478 | (Self::Ra, Self::Ra)
479 | (Self::Sp, Self::Sp)
480 | (Self::Gp, Self::Gp)
481 | (Self::Tp, Self::Tp)
482 | (Self::T0, Self::T0)
483 | (Self::T1, Self::T1)
484 | (Self::T2, Self::T2)
485 | (Self::S0, Self::S0)
486 | (Self::S1, Self::S1)
487 | (Self::A0, Self::A0)
488 | (Self::A1, Self::A1)
489 | (Self::A2, Self::A2)
490 | (Self::A3, Self::A3)
491 | (Self::A4, Self::A4)
492 | (Self::A5, Self::A5)
493 | (Self::A6, Self::A6)
494 | (Self::A7, Self::A7)
495 | (Self::S2, Self::S2)
496 | (Self::S3, Self::S3)
497 | (Self::S4, Self::S4)
498 | (Self::S5, Self::S5)
499 | (Self::S6, Self::S6)
500 | (Self::S7, Self::S7)
501 | (Self::S8, Self::S8)
502 | (Self::S9, Self::S9)
503 | (Self::S10, Self::S10)
504 | (Self::S11, Self::S11)
505 | (Self::T3, Self::T3)
506 | (Self::T4, Self::T4)
507 | (Self::T5, Self::T5)
508 | (Self::T6, Self::T6)
509 | (Self::Phantom(_), Self::Phantom(_))
510 )
511 }
512}
513
514impl<Type> const Eq for Reg<Type> {}
515
516impl const Register for Reg<u32> {
517 const ZERO: Self = Self::Zero;
518 const SP: Self = Self::Sp;
519 const RA: Self = Self::Ra;
520 const A0: Self = Self::A0;
521 const A1: Self = Self::A1;
522 type Type = u32;
523
524 #[inline(always)]
525 fn from_bits(bits: u8) -> Option<Self> {
526 match bits {
527 0 => Some(Self::Zero),
528 1 => Some(Self::Ra),
529 2 => Some(Self::Sp),
530 3 => Some(Self::Gp),
531 4 => Some(Self::Tp),
532 5 => Some(Self::T0),
533 6 => Some(Self::T1),
534 7 => Some(Self::T2),
535 8 => Some(Self::S0),
536 9 => Some(Self::S1),
537 10 => Some(Self::A0),
538 11 => Some(Self::A1),
539 12 => Some(Self::A2),
540 13 => Some(Self::A3),
541 14 => Some(Self::A4),
542 15 => Some(Self::A5),
543 16 => Some(Self::A6),
544 17 => Some(Self::A7),
545 18 => Some(Self::S2),
546 19 => Some(Self::S3),
547 20 => Some(Self::S4),
548 21 => Some(Self::S5),
549 22 => Some(Self::S6),
550 23 => Some(Self::S7),
551 24 => Some(Self::S8),
552 25 => Some(Self::S9),
553 26 => Some(Self::S10),
554 27 => Some(Self::S11),
555 28 => Some(Self::T3),
556 29 => Some(Self::T4),
557 30 => Some(Self::T5),
558 31 => Some(Self::T6),
559 _ => None,
560 }
561 }
562}
563
564impl const Register for Reg<u64> {
565 const ZERO: Self = Self::Zero;
566 const SP: Self = Self::Sp;
567 const RA: Self = Self::Ra;
568 const A0: Self = Self::A0;
569 const A1: Self = Self::A1;
570 type Type = u64;
571
572 #[inline(always)]
573 fn from_bits(bits: u8) -> Option<Self> {
574 match bits {
575 0 => Some(Self::Zero),
576 1 => Some(Self::Ra),
577 2 => Some(Self::Sp),
578 3 => Some(Self::Gp),
579 4 => Some(Self::Tp),
580 5 => Some(Self::T0),
581 6 => Some(Self::T1),
582 7 => Some(Self::T2),
583 8 => Some(Self::S0),
584 9 => Some(Self::S1),
585 10 => Some(Self::A0),
586 11 => Some(Self::A1),
587 12 => Some(Self::A2),
588 13 => Some(Self::A3),
589 14 => Some(Self::A4),
590 15 => Some(Self::A5),
591 16 => Some(Self::A6),
592 17 => Some(Self::A7),
593 18 => Some(Self::S2),
594 19 => Some(Self::S3),
595 20 => Some(Self::S4),
596 21 => Some(Self::S5),
597 22 => Some(Self::S6),
598 23 => Some(Self::S7),
599 24 => Some(Self::S8),
600 25 => Some(Self::S9),
601 26 => Some(Self::S10),
602 27 => Some(Self::S11),
603 28 => Some(Self::T3),
604 29 => Some(Self::T4),
605 30 => Some(Self::T5),
606 31 => Some(Self::T6),
607 _ => None,
608 }
609 }
610}