#[cfg(test)]
mod tests;
use crate::registers::general_purpose::private::PhantomRegister;
use core::fmt;
use core::hint::unreachable_unchecked;
use core::marker::Destruct;
use core::ops::{
Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Shl, Shr,
Sub, SubAssign,
};
mod private {
use core::marker::PhantomData;
#[derive(Debug, Clone, Copy)]
pub struct PhantomRegister<Type>(PhantomData<Type>);
}
pub const trait RegType
where
Self: [const] Default
+ [const] From<bool>
+ [const] From<u8>
+ [const] From<u16>
+ [const] From<u32>
+ [const] Eq
+ [const] Ord
+ [const] Add<Output = Self>
+ [const] AddAssign
+ [const] Sub<Output = Self>
+ [const] SubAssign
+ [const] BitAnd<Output = Self>
+ [const] BitAndAssign
+ [const] BitOr<Output = Self>
+ [const] BitOrAssign
+ [const] BitXor<Output = Self>
+ [const] BitXorAssign
+ [const] Not<Output = Self>
+ [const] Shl<u8, Output = Self>
+ [const] Shl<u16, Output = Self>
+ [const] Shl<u32, Output = Self>
+ [const] Shl<i32, Output = Self>
+ [const] Shr<u8, Output = Self>
+ [const] Shr<u16, Output = Self>
+ [const] Shr<u32, Output = Self>
+ [const] Shr<i32, Output = Self>
+ fmt::Display
+ fmt::LowerHex
+ fmt::UpperHex
+ fmt::Debug
+ Copy
+ Send
+ Sync
+ Sized
+ 'static,
{
const BITS: u8;
fn as_u64(&self) -> u64;
}
impl const RegType for u32 {
const BITS: u8 = u32::BITS as u8;
#[inline(always)]
fn as_u64(&self) -> u64 {
u64::from(*self)
}
}
impl const RegType for u64 {
const BITS: u8 = u64::BITS as u8;
#[inline(always)]
fn as_u64(&self) -> u64 {
*self
}
}
pub const trait Register:
fmt::Display + fmt::Debug + [const] Eq + [const] Destruct + Copy + Send + Sync + Sized + 'static
{
const XLEN: u8 = Self::Type::BITS;
const ZERO: Self;
const SP: Self;
const RA: Self;
const A0: Self;
const A1: Self;
type Type: [const] RegType;
fn from_bits(bits: u8) -> Option<Self>;
}
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum EReg<Type> {
Zero = 0,
Ra = 1,
Sp = 2,
Gp = 3,
Tp = 4,
T0 = 5,
T1 = 6,
T2 = 7,
S0 = 8,
S1 = 9,
A0 = 10,
A1 = 11,
A2 = 12,
A3 = 13,
A4 = 14,
A5 = 15,
#[doc(hidden)]
Phantom(PhantomRegister<Type>),
}
impl<Type> fmt::Display for EReg<Type> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Zero => write!(f, "zero"),
Self::Ra => write!(f, "ra"),
Self::Sp => write!(f, "sp"),
Self::Gp => write!(f, "gp"),
Self::Tp => write!(f, "tp"),
Self::T0 => write!(f, "t0"),
Self::T1 => write!(f, "t1"),
Self::T2 => write!(f, "t2"),
Self::S0 => write!(f, "s0"),
Self::S1 => write!(f, "s1"),
Self::A0 => write!(f, "a0"),
Self::A1 => write!(f, "a1"),
Self::A2 => write!(f, "a2"),
Self::A3 => write!(f, "a3"),
Self::A4 => write!(f, "a4"),
Self::A5 => write!(f, "a5"),
Self::Phantom(_) => {
unsafe { unreachable_unchecked() }
}
}
}
}
impl<Type> fmt::Debug for EReg<Type> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self, f)
}
}
impl<Type> const PartialEq for EReg<Type> {
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
matches!(
(self, other),
(Self::Zero, Self::Zero)
| (Self::Ra, Self::Ra)
| (Self::Sp, Self::Sp)
| (Self::Gp, Self::Gp)
| (Self::Tp, Self::Tp)
| (Self::T0, Self::T0)
| (Self::T1, Self::T1)
| (Self::T2, Self::T2)
| (Self::S0, Self::S0)
| (Self::S1, Self::S1)
| (Self::A0, Self::A0)
| (Self::A1, Self::A1)
| (Self::A2, Self::A2)
| (Self::A3, Self::A3)
| (Self::A4, Self::A4)
| (Self::A5, Self::A5)
| (Self::Phantom(_), Self::Phantom(_))
)
}
}
impl<Type> const Eq for EReg<Type> {}
impl const Register for EReg<u32> {
const ZERO: Self = Self::Zero;
const SP: Self = Self::Sp;
const RA: Self = Self::Ra;
const A0: Self = Self::A0;
const A1: Self = Self::A1;
type Type = u32;
#[inline(always)]
fn from_bits(bits: u8) -> Option<Self> {
match bits {
0 => Some(Self::Zero),
1 => Some(Self::Ra),
2 => Some(Self::Sp),
3 => Some(Self::Gp),
4 => Some(Self::Tp),
5 => Some(Self::T0),
6 => Some(Self::T1),
7 => Some(Self::T2),
8 => Some(Self::S0),
9 => Some(Self::S1),
10 => Some(Self::A0),
11 => Some(Self::A1),
12 => Some(Self::A2),
13 => Some(Self::A3),
14 => Some(Self::A4),
15 => Some(Self::A5),
_ => None,
}
}
}
impl const Register for EReg<u64> {
const ZERO: Self = Self::Zero;
const SP: Self = Self::Sp;
const RA: Self = Self::Ra;
const A0: Self = Self::A0;
const A1: Self = Self::A1;
type Type = u64;
#[inline(always)]
fn from_bits(bits: u8) -> Option<Self> {
match bits {
0 => Some(Self::Zero),
1 => Some(Self::Ra),
2 => Some(Self::Sp),
3 => Some(Self::Gp),
4 => Some(Self::Tp),
5 => Some(Self::T0),
6 => Some(Self::T1),
7 => Some(Self::T2),
8 => Some(Self::S0),
9 => Some(Self::S1),
10 => Some(Self::A0),
11 => Some(Self::A1),
12 => Some(Self::A2),
13 => Some(Self::A3),
14 => Some(Self::A4),
15 => Some(Self::A5),
_ => None,
}
}
}
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum Reg<Type> {
Zero = 0,
Ra = 1,
Sp = 2,
Gp = 3,
Tp = 4,
T0 = 5,
T1 = 6,
T2 = 7,
S0 = 8,
S1 = 9,
A0 = 10,
A1 = 11,
A2 = 12,
A3 = 13,
A4 = 14,
A5 = 15,
A6 = 16,
A7 = 17,
S2 = 18,
S3 = 19,
S4 = 20,
S5 = 21,
S6 = 22,
S7 = 23,
S8 = 24,
S9 = 25,
S10 = 26,
S11 = 27,
T3 = 28,
T4 = 29,
T5 = 30,
T6 = 31,
#[doc(hidden)]
Phantom(PhantomRegister<Type>),
}
impl<Type> const From<EReg<u64>> for Reg<Type> {
#[inline(always)]
fn from(reg: EReg<u64>) -> Self {
match reg {
EReg::Zero => Self::Zero,
EReg::Ra => Self::Ra,
EReg::Sp => Self::Sp,
EReg::Gp => Self::Gp,
EReg::Tp => Self::Tp,
EReg::T0 => Self::T0,
EReg::T1 => Self::T1,
EReg::T2 => Self::T2,
EReg::S0 => Self::S0,
EReg::S1 => Self::S1,
EReg::A0 => Self::A0,
EReg::A1 => Self::A1,
EReg::A2 => Self::A2,
EReg::A3 => Self::A3,
EReg::A4 => Self::A4,
EReg::A5 => Self::A5,
EReg::Phantom(_) => {
unsafe { unreachable_unchecked() }
}
}
}
}
impl<Type> fmt::Display for Reg<Type> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Zero => write!(f, "zero"),
Self::Ra => write!(f, "ra"),
Self::Sp => write!(f, "sp"),
Self::Gp => write!(f, "gp"),
Self::Tp => write!(f, "tp"),
Self::T0 => write!(f, "t0"),
Self::T1 => write!(f, "t1"),
Self::T2 => write!(f, "t2"),
Self::S0 => write!(f, "s0"),
Self::S1 => write!(f, "s1"),
Self::A0 => write!(f, "a0"),
Self::A1 => write!(f, "a1"),
Self::A2 => write!(f, "a2"),
Self::A3 => write!(f, "a3"),
Self::A4 => write!(f, "a4"),
Self::A5 => write!(f, "a5"),
Self::A6 => write!(f, "a6"),
Self::A7 => write!(f, "a7"),
Self::S2 => write!(f, "s2"),
Self::S3 => write!(f, "s3"),
Self::S4 => write!(f, "s4"),
Self::S5 => write!(f, "s5"),
Self::S6 => write!(f, "s6"),
Self::S7 => write!(f, "s7"),
Self::S8 => write!(f, "s8"),
Self::S9 => write!(f, "s9"),
Self::S10 => write!(f, "s10"),
Self::S11 => write!(f, "s11"),
Self::T3 => write!(f, "t3"),
Self::T4 => write!(f, "t4"),
Self::T5 => write!(f, "t5"),
Self::T6 => write!(f, "t6"),
Self::Phantom(_) => {
unsafe { unreachable_unchecked() }
}
}
}
}
impl<Type> fmt::Debug for Reg<Type> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self, f)
}
}
impl<Type> const PartialEq for Reg<Type> {
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
matches!(
(self, other),
(Self::Zero, Self::Zero)
| (Self::Ra, Self::Ra)
| (Self::Sp, Self::Sp)
| (Self::Gp, Self::Gp)
| (Self::Tp, Self::Tp)
| (Self::T0, Self::T0)
| (Self::T1, Self::T1)
| (Self::T2, Self::T2)
| (Self::S0, Self::S0)
| (Self::S1, Self::S1)
| (Self::A0, Self::A0)
| (Self::A1, Self::A1)
| (Self::A2, Self::A2)
| (Self::A3, Self::A3)
| (Self::A4, Self::A4)
| (Self::A5, Self::A5)
| (Self::A6, Self::A6)
| (Self::A7, Self::A7)
| (Self::S2, Self::S2)
| (Self::S3, Self::S3)
| (Self::S4, Self::S4)
| (Self::S5, Self::S5)
| (Self::S6, Self::S6)
| (Self::S7, Self::S7)
| (Self::S8, Self::S8)
| (Self::S9, Self::S9)
| (Self::S10, Self::S10)
| (Self::S11, Self::S11)
| (Self::T3, Self::T3)
| (Self::T4, Self::T4)
| (Self::T5, Self::T5)
| (Self::T6, Self::T6)
| (Self::Phantom(_), Self::Phantom(_))
)
}
}
impl<Type> const Eq for Reg<Type> {}
impl const Register for Reg<u32> {
const ZERO: Self = Self::Zero;
const SP: Self = Self::Sp;
const RA: Self = Self::Ra;
const A0: Self = Self::A0;
const A1: Self = Self::A1;
type Type = u32;
#[inline(always)]
fn from_bits(bits: u8) -> Option<Self> {
match bits {
0 => Some(Self::Zero),
1 => Some(Self::Ra),
2 => Some(Self::Sp),
3 => Some(Self::Gp),
4 => Some(Self::Tp),
5 => Some(Self::T0),
6 => Some(Self::T1),
7 => Some(Self::T2),
8 => Some(Self::S0),
9 => Some(Self::S1),
10 => Some(Self::A0),
11 => Some(Self::A1),
12 => Some(Self::A2),
13 => Some(Self::A3),
14 => Some(Self::A4),
15 => Some(Self::A5),
16 => Some(Self::A6),
17 => Some(Self::A7),
18 => Some(Self::S2),
19 => Some(Self::S3),
20 => Some(Self::S4),
21 => Some(Self::S5),
22 => Some(Self::S6),
23 => Some(Self::S7),
24 => Some(Self::S8),
25 => Some(Self::S9),
26 => Some(Self::S10),
27 => Some(Self::S11),
28 => Some(Self::T3),
29 => Some(Self::T4),
30 => Some(Self::T5),
31 => Some(Self::T6),
_ => None,
}
}
}
impl const Register for Reg<u64> {
const ZERO: Self = Self::Zero;
const SP: Self = Self::Sp;
const RA: Self = Self::Ra;
const A0: Self = Self::A0;
const A1: Self = Self::A1;
type Type = u64;
#[inline(always)]
fn from_bits(bits: u8) -> Option<Self> {
match bits {
0 => Some(Self::Zero),
1 => Some(Self::Ra),
2 => Some(Self::Sp),
3 => Some(Self::Gp),
4 => Some(Self::Tp),
5 => Some(Self::T0),
6 => Some(Self::T1),
7 => Some(Self::T2),
8 => Some(Self::S0),
9 => Some(Self::S1),
10 => Some(Self::A0),
11 => Some(Self::A1),
12 => Some(Self::A2),
13 => Some(Self::A3),
14 => Some(Self::A4),
15 => Some(Self::A5),
16 => Some(Self::A6),
17 => Some(Self::A7),
18 => Some(Self::S2),
19 => Some(Self::S3),
20 => Some(Self::S4),
21 => Some(Self::S5),
22 => Some(Self::S6),
23 => Some(Self::S7),
24 => Some(Self::S8),
25 => Some(Self::S9),
26 => Some(Self::S10),
27 => Some(Self::S11),
28 => Some(Self::T3),
29 => Some(Self::T4),
30 => Some(Self::T5),
31 => Some(Self::T6),
_ => None,
}
}
}