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