1#[cfg(test)]
4mod tests;
5
6use core::marker::{Destruct, PhantomData};
7use core::ops::{
8 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Shl, Shr,
9 Sub, SubAssign,
10};
11use core::{fmt, ptr};
12
13pub const trait RegType
17where
18 Self: const Default
19 + const Destruct
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 truncate_from_u64(value: u64) -> Self;
63
64 fn as_i64(&self) -> i64;
66
67 fn wrapping_add_signed(&self, offset: i32) -> Self;
69}
70
71const impl RegType for u32 {
72 const BITS: u8 = u32::BITS as u8;
73
74 #[inline(always)]
75 fn as_u64(&self) -> u64 {
76 u64::from(*self)
77 }
78
79 #[inline(always)]
80 fn truncate_from_u64(value: u64) -> Self {
81 value as Self
82 }
83
84 #[inline(always)]
85 fn as_i64(&self) -> i64 {
86 i64::from(self.cast_signed())
87 }
88
89 #[inline(always)]
90 fn wrapping_add_signed(&self, offset: i32) -> Self {
91 u32::wrapping_add_signed(*self, offset)
92 }
93}
94
95const impl RegType for u64 {
96 const BITS: u8 = u64::BITS as u8;
97
98 #[inline(always)]
99 fn as_u64(&self) -> u64 {
100 *self
101 }
102
103 #[inline(always)]
104 fn truncate_from_u64(value: u64) -> Self {
105 value
106 }
107
108 #[inline(always)]
109 fn as_i64(&self) -> i64 {
110 self.cast_signed()
111 }
112
113 #[inline(always)]
114 fn wrapping_add_signed(&self, offset: i32) -> Self {
115 u64::wrapping_add_signed(*self, i64::from(offset))
116 }
117}
118
119pub const trait Register:
121 fmt::Display
122 + fmt::Debug
123 + const Default
124 + const Eq
125 + const Destruct
126 + Copy
127 + Send
128 + Sync
129 + Sized
130 + 'static
131{
132 const XLEN: u8 = Self::Type::BITS;
136 const RVE: bool;
138 const ZERO: Self;
140 const SP: Self;
142 const RA: Self;
144 const A0: Self;
146 const A1: Self;
148 type Type: const RegType;
152
153 fn from_bits(bits: u8) -> Option<Self>;
155}
156
157#[derive(Clone, Copy)]
161#[derive_const(Default)]
162#[repr(u8)]
163pub enum EReg<Type> {
164 #[default]
166 Zero = 0,
167 Ra = 1,
169 Sp = 2,
171 Gp = 3,
173 Tp = 4,
175 T0 = 5,
177 T1 = 6,
179 T2 = 7,
181 S0 = 8,
183 S1 = 9,
185 A0 = 10,
187 A1 = 11,
189 A2 = 12,
191 A3 = 13,
193 A4 = 14,
195 A5 = 15,
197 #[doc(hidden)]
199 Phantom(!, PhantomData<Type>),
200}
201
202impl<Type> fmt::Display for EReg<Type> {
203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204 match self {
205 Self::Zero => write!(f, "zero"),
206 Self::Ra => write!(f, "ra"),
207 Self::Sp => write!(f, "sp"),
208 Self::Gp => write!(f, "gp"),
209 Self::Tp => write!(f, "tp"),
210 Self::T0 => write!(f, "t0"),
211 Self::T1 => write!(f, "t1"),
212 Self::T2 => write!(f, "t2"),
213 Self::S0 => write!(f, "s0"),
214 Self::S1 => write!(f, "s1"),
215 Self::A0 => write!(f, "a0"),
216 Self::A1 => write!(f, "a1"),
217 Self::A2 => write!(f, "a2"),
218 Self::A3 => write!(f, "a3"),
219 Self::A4 => write!(f, "a4"),
220 Self::A5 => write!(f, "a5"),
221 Self::Phantom(never, _) => *never,
222 }
223 }
224}
225
226impl<Type> fmt::Debug for EReg<Type> {
227 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
228 fmt::Display::fmt(self, f)
229 }
230}
231
232const impl<Type> PartialEq for EReg<Type> {
233 #[inline(always)]
234 fn eq(&self, other: &Self) -> bool {
235 unsafe { *ptr::from_ref(self).cast::<u8>() == *ptr::from_ref(other).cast::<u8>() }
237 }
238}
239
240const impl<Type> Eq for EReg<Type> {}
241
242const impl Register for EReg<u32> {
243 const RVE: bool = true;
244 const ZERO: Self = Self::Zero;
245 const SP: Self = Self::Sp;
246 const RA: Self = Self::Ra;
247 const A0: Self = Self::A0;
248 const A1: Self = Self::A1;
249 type Type = u32;
250
251 #[inline(always)]
252 fn from_bits(bits: u8) -> Option<Self> {
253 match bits {
254 0 => Some(Self::Zero),
255 1 => Some(Self::Ra),
256 2 => Some(Self::Sp),
257 3 => Some(Self::Gp),
258 4 => Some(Self::Tp),
259 5 => Some(Self::T0),
260 6 => Some(Self::T1),
261 7 => Some(Self::T2),
262 8 => Some(Self::S0),
263 9 => Some(Self::S1),
264 10 => Some(Self::A0),
265 11 => Some(Self::A1),
266 12 => Some(Self::A2),
267 13 => Some(Self::A3),
268 14 => Some(Self::A4),
269 15 => Some(Self::A5),
270 _ => None,
271 }
272 }
273}
274
275const impl Register for EReg<u64> {
276 const RVE: bool = true;
277 const ZERO: Self = Self::Zero;
278 const SP: Self = Self::Sp;
279 const RA: Self = Self::Ra;
280 const A0: Self = Self::A0;
281 const A1: Self = Self::A1;
282 type Type = u64;
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
308#[derive(Clone, Copy)]
312#[derive_const(Default)]
313#[repr(u8)]
314pub enum Reg<Type> {
315 #[default]
317 Zero = 0,
318 Ra = 1,
320 Sp = 2,
322 Gp = 3,
324 Tp = 4,
326 T0 = 5,
328 T1 = 6,
330 T2 = 7,
332 S0 = 8,
334 S1 = 9,
336 A0 = 10,
338 A1 = 11,
340 A2 = 12,
342 A3 = 13,
344 A4 = 14,
346 A5 = 15,
348 A6 = 16,
350 A7 = 17,
352 S2 = 18,
354 S3 = 19,
356 S4 = 20,
358 S5 = 21,
360 S6 = 22,
362 S7 = 23,
364 S8 = 24,
366 S9 = 25,
368 S10 = 26,
370 S11 = 27,
372 T3 = 28,
374 T4 = 29,
376 T5 = 30,
378 T6 = 31,
380 #[doc(hidden)]
382 Phantom(!, PhantomData<Type>),
383}
384
385const impl<Type> From<EReg<Type>> for Reg<Type> {
386 #[inline(always)]
387 fn from(reg: EReg<Type>) -> Self {
388 match reg {
389 EReg::Zero => Self::Zero,
390 EReg::Ra => Self::Ra,
391 EReg::Sp => Self::Sp,
392 EReg::Gp => Self::Gp,
393 EReg::Tp => Self::Tp,
394 EReg::T0 => Self::T0,
395 EReg::T1 => Self::T1,
396 EReg::T2 => Self::T2,
397 EReg::S0 => Self::S0,
398 EReg::S1 => Self::S1,
399 EReg::A0 => Self::A0,
400 EReg::A1 => Self::A1,
401 EReg::A2 => Self::A2,
402 EReg::A3 => Self::A3,
403 EReg::A4 => Self::A4,
404 EReg::A5 => Self::A5,
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(never, _) => *never,
445 }
446 }
447}
448
449impl<Type> fmt::Debug for Reg<Type> {
450 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
451 fmt::Display::fmt(self, f)
452 }
453}
454
455const impl<Type> PartialEq for Reg<Type> {
456 #[inline(always)]
457 fn eq(&self, other: &Self) -> bool {
458 unsafe { *ptr::from_ref(self).cast::<u8>() == *ptr::from_ref(other).cast::<u8>() }
460 }
461}
462
463const impl<Type> Eq for Reg<Type> {}
464
465const impl Register for Reg<u32> {
466 const RVE: bool = false;
467 const ZERO: Self = Self::Zero;
468 const SP: Self = Self::Sp;
469 const RA: Self = Self::Ra;
470 const A0: Self = Self::A0;
471 const A1: Self = Self::A1;
472 type Type = u32;
473
474 #[inline(always)]
475 fn from_bits(bits: u8) -> Option<Self> {
476 match bits {
477 0 => Some(Self::Zero),
478 1 => Some(Self::Ra),
479 2 => Some(Self::Sp),
480 3 => Some(Self::Gp),
481 4 => Some(Self::Tp),
482 5 => Some(Self::T0),
483 6 => Some(Self::T1),
484 7 => Some(Self::T2),
485 8 => Some(Self::S0),
486 9 => Some(Self::S1),
487 10 => Some(Self::A0),
488 11 => Some(Self::A1),
489 12 => Some(Self::A2),
490 13 => Some(Self::A3),
491 14 => Some(Self::A4),
492 15 => Some(Self::A5),
493 16 => Some(Self::A6),
494 17 => Some(Self::A7),
495 18 => Some(Self::S2),
496 19 => Some(Self::S3),
497 20 => Some(Self::S4),
498 21 => Some(Self::S5),
499 22 => Some(Self::S6),
500 23 => Some(Self::S7),
501 24 => Some(Self::S8),
502 25 => Some(Self::S9),
503 26 => Some(Self::S10),
504 27 => Some(Self::S11),
505 28 => Some(Self::T3),
506 29 => Some(Self::T4),
507 30 => Some(Self::T5),
508 31 => Some(Self::T6),
509 _ => None,
510 }
511 }
512}
513
514const impl Register for Reg<u64> {
515 const RVE: bool = false;
516 const ZERO: Self = Self::Zero;
517 const SP: Self = Self::Sp;
518 const RA: Self = Self::Ra;
519 const A0: Self = Self::A0;
520 const A1: Self = Self::A1;
521 type Type = u64;
522
523 #[inline(always)]
524 fn from_bits(bits: u8) -> Option<Self> {
525 match bits {
526 0 => Some(Self::Zero),
527 1 => Some(Self::Ra),
528 2 => Some(Self::Sp),
529 3 => Some(Self::Gp),
530 4 => Some(Self::Tp),
531 5 => Some(Self::T0),
532 6 => Some(Self::T1),
533 7 => Some(Self::T2),
534 8 => Some(Self::S0),
535 9 => Some(Self::S1),
536 10 => Some(Self::A0),
537 11 => Some(Self::A1),
538 12 => Some(Self::A2),
539 13 => Some(Self::A3),
540 14 => Some(Self::A4),
541 15 => Some(Self::A5),
542 16 => Some(Self::A6),
543 17 => Some(Self::A7),
544 18 => Some(Self::S2),
545 19 => Some(Self::S3),
546 20 => Some(Self::S4),
547 21 => Some(Self::S5),
548 22 => Some(Self::S6),
549 23 => Some(Self::S7),
550 24 => Some(Self::S8),
551 25 => Some(Self::S9),
552 26 => Some(Self::S10),
553 27 => Some(Self::S11),
554 28 => Some(Self::T3),
555 29 => Some(Self::T4),
556 30 => Some(Self::T5),
557 31 => Some(Self::T6),
558 _ => None,
559 }
560 }
561}