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
70impl const RegType for u32 {
71 const BITS: u8 = u32::BITS as u8;
72
73 #[inline(always)]
74 fn as_u64(&self) -> u64 {
75 u64::from(*self)
76 }
77}
78
79impl const RegType for u64 {
80 const BITS: u8 = u64::BITS as u8;
81
82 #[inline(always)]
83 fn as_u64(&self) -> u64 {
84 *self
85 }
86}
87
88pub const trait Register:
90 fmt::Display
91 + fmt::Debug
92 + [const] Default
93 + [const] Eq
94 + [const] Destruct
95 + Copy
96 + Send
97 + Sync
98 + Sized
99 + 'static
100{
101 const XLEN: u8 = Self::Type::BITS;
104 const ZERO: Self;
106 const SP: Self;
108 const RA: Self;
110 const A0: Self;
112 const A1: Self;
114 type Type: [const] RegType;
118
119 fn from_bits(bits: u8) -> Option<Self>;
121}
122
123#[derive(Clone, Copy)]
127#[repr(u8)]
128pub enum EReg<Type> {
129 Zero = 0,
131 Ra = 1,
133 Sp = 2,
135 Gp = 3,
137 Tp = 4,
139 T0 = 5,
141 T1 = 6,
143 T2 = 7,
145 S0 = 8,
147 S1 = 9,
149 A0 = 10,
151 A1 = 11,
153 A2 = 12,
155 A3 = 13,
157 A4 = 14,
159 A5 = 15,
161 #[doc(hidden)]
163 Phantom(PhantomRegister<Type>),
164}
165
166impl<Type> const Default for EReg<Type> {
167 #[inline(always)]
168 fn default() -> Self {
169 Self::Zero
170 }
171}
172
173impl<Type> fmt::Display for EReg<Type> {
174 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
175 match self {
176 Self::Zero => write!(f, "zero"),
177 Self::Ra => write!(f, "ra"),
178 Self::Sp => write!(f, "sp"),
179 Self::Gp => write!(f, "gp"),
180 Self::Tp => write!(f, "tp"),
181 Self::T0 => write!(f, "t0"),
182 Self::T1 => write!(f, "t1"),
183 Self::T2 => write!(f, "t2"),
184 Self::S0 => write!(f, "s0"),
185 Self::S1 => write!(f, "s1"),
186 Self::A0 => write!(f, "a0"),
187 Self::A1 => write!(f, "a1"),
188 Self::A2 => write!(f, "a2"),
189 Self::A3 => write!(f, "a3"),
190 Self::A4 => write!(f, "a4"),
191 Self::A5 => write!(f, "a5"),
192 Self::Phantom(_) => {
193 unsafe { unreachable_unchecked() }
195 }
196 }
197 }
198}
199
200impl<Type> fmt::Debug for EReg<Type> {
201 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
202 fmt::Display::fmt(self, f)
203 }
204}
205
206impl<Type> const PartialEq for EReg<Type> {
207 #[inline(always)]
208 fn eq(&self, other: &Self) -> bool {
209 matches!(
211 (self, other),
212 (Self::Zero, Self::Zero)
213 | (Self::Ra, Self::Ra)
214 | (Self::Sp, Self::Sp)
215 | (Self::Gp, Self::Gp)
216 | (Self::Tp, Self::Tp)
217 | (Self::T0, Self::T0)
218 | (Self::T1, Self::T1)
219 | (Self::T2, Self::T2)
220 | (Self::S0, Self::S0)
221 | (Self::S1, Self::S1)
222 | (Self::A0, Self::A0)
223 | (Self::A1, Self::A1)
224 | (Self::A2, Self::A2)
225 | (Self::A3, Self::A3)
226 | (Self::A4, Self::A4)
227 | (Self::A5, Self::A5)
228 | (Self::Phantom(_), Self::Phantom(_))
229 )
230 }
231}
232
233impl<Type> const Eq for EReg<Type> {}
234
235impl const Register for EReg<u32> {
236 const ZERO: Self = Self::Zero;
237 const SP: Self = Self::Sp;
238 const RA: Self = Self::Ra;
239 const A0: Self = Self::A0;
240 const A1: Self = Self::A1;
241 type Type = u32;
242
243 #[inline(always)]
244 fn from_bits(bits: u8) -> Option<Self> {
245 match bits {
246 0 => Some(Self::Zero),
247 1 => Some(Self::Ra),
248 2 => Some(Self::Sp),
249 3 => Some(Self::Gp),
250 4 => Some(Self::Tp),
251 5 => Some(Self::T0),
252 6 => Some(Self::T1),
253 7 => Some(Self::T2),
254 8 => Some(Self::S0),
255 9 => Some(Self::S1),
256 10 => Some(Self::A0),
257 11 => Some(Self::A1),
258 12 => Some(Self::A2),
259 13 => Some(Self::A3),
260 14 => Some(Self::A4),
261 15 => Some(Self::A5),
262 _ => None,
263 }
264 }
265}
266
267impl const Register for EReg<u64> {
268 const ZERO: Self = Self::Zero;
269 const SP: Self = Self::Sp;
270 const RA: Self = Self::Ra;
271 const A0: Self = Self::A0;
272 const A1: Self = Self::A1;
273 type Type = u64;
274
275 #[inline(always)]
276 fn from_bits(bits: u8) -> Option<Self> {
277 match bits {
278 0 => Some(Self::Zero),
279 1 => Some(Self::Ra),
280 2 => Some(Self::Sp),
281 3 => Some(Self::Gp),
282 4 => Some(Self::Tp),
283 5 => Some(Self::T0),
284 6 => Some(Self::T1),
285 7 => Some(Self::T2),
286 8 => Some(Self::S0),
287 9 => Some(Self::S1),
288 10 => Some(Self::A0),
289 11 => Some(Self::A1),
290 12 => Some(Self::A2),
291 13 => Some(Self::A3),
292 14 => Some(Self::A4),
293 15 => Some(Self::A5),
294 _ => None,
295 }
296 }
297}
298
299#[derive(Clone, Copy)]
303#[repr(u8)]
304pub enum Reg<Type> {
305 Zero = 0,
307 Ra = 1,
309 Sp = 2,
311 Gp = 3,
313 Tp = 4,
315 T0 = 5,
317 T1 = 6,
319 T2 = 7,
321 S0 = 8,
323 S1 = 9,
325 A0 = 10,
327 A1 = 11,
329 A2 = 12,
331 A3 = 13,
333 A4 = 14,
335 A5 = 15,
337 A6 = 16,
339 A7 = 17,
341 S2 = 18,
343 S3 = 19,
345 S4 = 20,
347 S5 = 21,
349 S6 = 22,
351 S7 = 23,
353 S8 = 24,
355 S9 = 25,
357 S10 = 26,
359 S11 = 27,
361 T3 = 28,
363 T4 = 29,
365 T5 = 30,
367 T6 = 31,
369 #[doc(hidden)]
371 Phantom(PhantomRegister<Type>),
372}
373
374impl<Type> const Default for Reg<Type> {
375 #[inline(always)]
376 fn default() -> Self {
377 Self::Zero
378 }
379}
380
381impl<Type> const From<EReg<u64>> for Reg<Type> {
382 #[inline(always)]
383 fn from(reg: EReg<u64>) -> Self {
384 match reg {
385 EReg::Zero => Self::Zero,
386 EReg::Ra => Self::Ra,
387 EReg::Sp => Self::Sp,
388 EReg::Gp => Self::Gp,
389 EReg::Tp => Self::Tp,
390 EReg::T0 => Self::T0,
391 EReg::T1 => Self::T1,
392 EReg::T2 => Self::T2,
393 EReg::S0 => Self::S0,
394 EReg::S1 => Self::S1,
395 EReg::A0 => Self::A0,
396 EReg::A1 => Self::A1,
397 EReg::A2 => Self::A2,
398 EReg::A3 => Self::A3,
399 EReg::A4 => Self::A4,
400 EReg::A5 => Self::A5,
401 EReg::Phantom(_) => {
402 unsafe { unreachable_unchecked() }
404 }
405 }
406 }
407}
408
409impl<Type> fmt::Display for Reg<Type> {
410 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
411 match self {
412 Self::Zero => write!(f, "zero"),
413 Self::Ra => write!(f, "ra"),
414 Self::Sp => write!(f, "sp"),
415 Self::Gp => write!(f, "gp"),
416 Self::Tp => write!(f, "tp"),
417 Self::T0 => write!(f, "t0"),
418 Self::T1 => write!(f, "t1"),
419 Self::T2 => write!(f, "t2"),
420 Self::S0 => write!(f, "s0"),
421 Self::S1 => write!(f, "s1"),
422 Self::A0 => write!(f, "a0"),
423 Self::A1 => write!(f, "a1"),
424 Self::A2 => write!(f, "a2"),
425 Self::A3 => write!(f, "a3"),
426 Self::A4 => write!(f, "a4"),
427 Self::A5 => write!(f, "a5"),
428 Self::A6 => write!(f, "a6"),
429 Self::A7 => write!(f, "a7"),
430 Self::S2 => write!(f, "s2"),
431 Self::S3 => write!(f, "s3"),
432 Self::S4 => write!(f, "s4"),
433 Self::S5 => write!(f, "s5"),
434 Self::S6 => write!(f, "s6"),
435 Self::S7 => write!(f, "s7"),
436 Self::S8 => write!(f, "s8"),
437 Self::S9 => write!(f, "s9"),
438 Self::S10 => write!(f, "s10"),
439 Self::S11 => write!(f, "s11"),
440 Self::T3 => write!(f, "t3"),
441 Self::T4 => write!(f, "t4"),
442 Self::T5 => write!(f, "t5"),
443 Self::T6 => write!(f, "t6"),
444 Self::Phantom(_) => {
445 unsafe { unreachable_unchecked() }
447 }
448 }
449 }
450}
451
452impl<Type> fmt::Debug for Reg<Type> {
453 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
454 fmt::Display::fmt(self, f)
455 }
456}
457
458impl<Type> const PartialEq for Reg<Type> {
459 #[inline(always)]
460 fn eq(&self, other: &Self) -> bool {
461 matches!(
463 (self, other),
464 (Self::Zero, Self::Zero)
465 | (Self::Ra, Self::Ra)
466 | (Self::Sp, Self::Sp)
467 | (Self::Gp, Self::Gp)
468 | (Self::Tp, Self::Tp)
469 | (Self::T0, Self::T0)
470 | (Self::T1, Self::T1)
471 | (Self::T2, Self::T2)
472 | (Self::S0, Self::S0)
473 | (Self::S1, Self::S1)
474 | (Self::A0, Self::A0)
475 | (Self::A1, Self::A1)
476 | (Self::A2, Self::A2)
477 | (Self::A3, Self::A3)
478 | (Self::A4, Self::A4)
479 | (Self::A5, Self::A5)
480 | (Self::A6, Self::A6)
481 | (Self::A7, Self::A7)
482 | (Self::S2, Self::S2)
483 | (Self::S3, Self::S3)
484 | (Self::S4, Self::S4)
485 | (Self::S5, Self::S5)
486 | (Self::S6, Self::S6)
487 | (Self::S7, Self::S7)
488 | (Self::S8, Self::S8)
489 | (Self::S9, Self::S9)
490 | (Self::S10, Self::S10)
491 | (Self::S11, Self::S11)
492 | (Self::T3, Self::T3)
493 | (Self::T4, Self::T4)
494 | (Self::T5, Self::T5)
495 | (Self::T6, Self::T6)
496 | (Self::Phantom(_), Self::Phantom(_))
497 )
498 }
499}
500
501impl<Type> const Eq for Reg<Type> {}
502
503impl const Register for Reg<u32> {
504 const ZERO: Self = Self::Zero;
505 const SP: Self = Self::Sp;
506 const RA: Self = Self::Ra;
507 const A0: Self = Self::A0;
508 const A1: Self = Self::A1;
509 type Type = u32;
510
511 #[inline(always)]
512 fn from_bits(bits: u8) -> Option<Self> {
513 match bits {
514 0 => Some(Self::Zero),
515 1 => Some(Self::Ra),
516 2 => Some(Self::Sp),
517 3 => Some(Self::Gp),
518 4 => Some(Self::Tp),
519 5 => Some(Self::T0),
520 6 => Some(Self::T1),
521 7 => Some(Self::T2),
522 8 => Some(Self::S0),
523 9 => Some(Self::S1),
524 10 => Some(Self::A0),
525 11 => Some(Self::A1),
526 12 => Some(Self::A2),
527 13 => Some(Self::A3),
528 14 => Some(Self::A4),
529 15 => Some(Self::A5),
530 16 => Some(Self::A6),
531 17 => Some(Self::A7),
532 18 => Some(Self::S2),
533 19 => Some(Self::S3),
534 20 => Some(Self::S4),
535 21 => Some(Self::S5),
536 22 => Some(Self::S6),
537 23 => Some(Self::S7),
538 24 => Some(Self::S8),
539 25 => Some(Self::S9),
540 26 => Some(Self::S10),
541 27 => Some(Self::S11),
542 28 => Some(Self::T3),
543 29 => Some(Self::T4),
544 30 => Some(Self::T5),
545 31 => Some(Self::T6),
546 _ => None,
547 }
548 }
549}
550
551impl const Register for Reg<u64> {
552 const ZERO: Self = Self::Zero;
553 const SP: Self = Self::Sp;
554 const RA: Self = Self::Ra;
555 const A0: Self = Self::A0;
556 const A1: Self = Self::A1;
557 type Type = u64;
558
559 #[inline(always)]
560 fn from_bits(bits: u8) -> Option<Self> {
561 match bits {
562 0 => Some(Self::Zero),
563 1 => Some(Self::Ra),
564 2 => Some(Self::Sp),
565 3 => Some(Self::Gp),
566 4 => Some(Self::Tp),
567 5 => Some(Self::T0),
568 6 => Some(Self::T1),
569 7 => Some(Self::T2),
570 8 => Some(Self::S0),
571 9 => Some(Self::S1),
572 10 => Some(Self::A0),
573 11 => Some(Self::A1),
574 12 => Some(Self::A2),
575 13 => Some(Self::A3),
576 14 => Some(Self::A4),
577 15 => Some(Self::A5),
578 16 => Some(Self::A6),
579 17 => Some(Self::A7),
580 18 => Some(Self::S2),
581 19 => Some(Self::S3),
582 20 => Some(Self::S4),
583 21 => Some(Self::S5),
584 22 => Some(Self::S6),
585 23 => Some(Self::S7),
586 24 => Some(Self::S8),
587 25 => Some(Self::S9),
588 26 => Some(Self::S10),
589 27 => Some(Self::S11),
590 28 => Some(Self::T3),
591 29 => Some(Self::T4),
592 30 => Some(Self::T5),
593 31 => Some(Self::T6),
594 _ => None,
595 }
596 }
597}