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