Skip to main content

ab_riscv_primitives/registers/
general_purpose.rs

1//! RISC-V general purpose registers
2
3#[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
22/// Register type.
23///
24/// `u32` for RV32 and `u64` for RV64.
25pub 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    /// The size of this type in bits
64    const BITS: u8;
65
66    /// Convert to `u64`
67    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
88/// GPR (General Purpose Register)
89pub 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    /// Whether this is RVE variant with the number of general purpose registers reduced to 16
102    /// XLEN
103    const XLEN: u8 = Self::Type::BITS;
104    /// Zero register
105    const ZERO: Self;
106    /// Stack pointer register
107    const SP: Self;
108    /// Return address register
109    const RA: Self;
110    /// Function argument register a0
111    const A0: Self;
112    /// Function argument register a1
113    const A1: Self;
114    /// Register type.
115    ///
116    /// `u32` for RV32 and `u64` for RV64.
117    type Type: [const] RegType;
118
119    /// Create a register from its bit representation
120    fn from_bits(bits: u8) -> Option<Self>;
121}
122
123/// RISC-V general purpose register for RV32E/RV64E.
124///
125/// Use `Type = u32` for RV32E and `Type = u64` for RV64E.
126#[derive(Clone, Copy)]
127#[repr(u8)]
128pub enum EReg<Type> {
129    /// Always zero: `x0`
130    Zero = 0,
131    /// Return address: `x1`
132    Ra = 1,
133    /// Stack pointer: `x2`
134    Sp = 2,
135    /// Global pointer: `x3`
136    Gp = 3,
137    /// Thread pointer: `x4`
138    Tp = 4,
139    /// Temporary/alternate return address: `x5`
140    T0 = 5,
141    /// Temporary: `x6`
142    T1 = 6,
143    /// Temporary: `x7`
144    T2 = 7,
145    /// Saved register/frame pointer: `x8`
146    S0 = 8,
147    /// Saved register: `x9`
148    S1 = 9,
149    /// Function argument/return value: `x10`
150    A0 = 10,
151    /// Function argument/return value: `x11`
152    A1 = 11,
153    /// Function argument: `x12`
154    A2 = 12,
155    /// Function argument: `x13`
156    A3 = 13,
157    /// Function argument: `x14`
158    A4 = 14,
159    /// Function argument: `x15`
160    A5 = 15,
161    /// Phantom register that is never constructed and is only used due to type system limitations
162    #[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                // SAFETY: Phantom register is never constructed
194                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        // This is quite ugly, but there doesn't seem to be a much better way with `Phantom` variant
210        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/// RISC-V general purpose register for RV32I/RV64I.
300///
301/// Use `Type = u32` for RV32I and `Type = u64` for RV64I.
302#[derive(Clone, Copy)]
303#[repr(u8)]
304pub enum Reg<Type> {
305    /// Always zero: `x0`
306    Zero = 0,
307    /// Return address: `x1`
308    Ra = 1,
309    /// Stack pointer: `x2`
310    Sp = 2,
311    /// Global pointer: `x3`
312    Gp = 3,
313    /// Thread pointer: `x4`
314    Tp = 4,
315    /// Temporary/alternate return address: `x5`
316    T0 = 5,
317    /// Temporary: `x6`
318    T1 = 6,
319    /// Temporary: `x7`
320    T2 = 7,
321    /// Saved register/frame pointer: `x8`
322    S0 = 8,
323    /// Saved register: `x9`
324    S1 = 9,
325    /// Function argument/return value: `x10`
326    A0 = 10,
327    /// Function argument/return value: `x11`
328    A1 = 11,
329    /// Function argument: `x12`
330    A2 = 12,
331    /// Function argument: `x13`
332    A3 = 13,
333    /// Function argument: `x14`
334    A4 = 14,
335    /// Function argument: `x15`
336    A5 = 15,
337    /// Function argument: `x16`
338    A6 = 16,
339    /// Function argument: `x17`
340    A7 = 17,
341    /// Saved register: `x18`
342    S2 = 18,
343    /// Saved register: `x19`
344    S3 = 19,
345    /// Saved register: `x20`
346    S4 = 20,
347    /// Saved register: `x21`
348    S5 = 21,
349    /// Saved register: `x22`
350    S6 = 22,
351    /// Saved register: `x23`
352    S7 = 23,
353    /// Saved register: `x24`
354    S8 = 24,
355    /// Saved register: `x25`
356    S9 = 25,
357    /// Saved register: `x26`
358    S10 = 26,
359    /// Saved register: `x27`
360    S11 = 27,
361    /// Temporary: `x28`
362    T3 = 28,
363    /// Temporary: `x29`
364    T4 = 29,
365    /// Temporary: `x30`
366    T5 = 30,
367    /// Temporary: `x31`
368    T6 = 31,
369    /// Phantom register that is never constructed and is only used due to type system limitations
370    #[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                // SAFETY: Phantom register is never constructed
403                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                // SAFETY: Phantom register is never constructed
446                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        // This is quite ugly, but there doesn't seem to be a much better way with `Phantom` variant
462        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}