diff --git a/src/register/macros.rs b/src/register/macros.rs index db38665..a922443 100644 --- a/src/register/macros.rs +++ b/src/register/macros.rs @@ -17,6 +17,25 @@ macro_rules! read_csr { }; } +macro_rules! read_csr_rv32 { + ($csr_number:expr) => { + /// Reads the CSR + #[inline] + #[cfg(target_arch = "riscv32")] + unsafe fn _read() -> usize { + let r: usize; + asm!("csrrs $0, $1, x0" : "=r"(r) : "i"($csr_number) :: "volatile"); + r + } + + #[inline] + #[cfg(not(target_arch = "riscv32"))] + unsafe fn _read() -> usize { + unimplemented!() + } + }; +} + macro_rules! read_csr_as { ($register:ident, $csr_number:expr) => { read_csr!($csr_number); @@ -28,6 +47,7 @@ macro_rules! read_csr_as { } }; } + macro_rules! read_csr_as_usize { ($csr_number:expr) => { read_csr!($csr_number); @@ -40,6 +60,18 @@ macro_rules! read_csr_as_usize { }; } +macro_rules! read_csr_as_usize_rv32 { + ($csr_number:expr) => { + read_csr_rv32!($csr_number); + + /// Reads the CSR + #[inline] + pub fn read() -> usize { + unsafe{ _read() } + } + }; +} + macro_rules! write_csr { ($csr_number:expr) => { /// Writes the CSR diff --git a/src/register/mcause.rs b/src/register/mcause.rs index 7cf307b..e659383 100644 --- a/src/register/mcause.rs +++ b/src/register/mcause.rs @@ -136,19 +136,4 @@ impl Mcause { } } -/// Reads the CSR -#[inline] -pub fn read() -> Mcause { - match () { - #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] - () => { - let r: usize; - unsafe { - asm!("csrrs $0, 0x342, x0" : "=r"(r) ::: "volatile"); - } - Mcause { bits: r } - } - #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] - () => unimplemented!(), - } -} +read_csr_as!(Mcause, 0x342); diff --git a/src/register/mcycle.rs b/src/register/mcycle.rs index 3c066e1..f2905fc 100644 --- a/src/register/mcycle.rs +++ b/src/register/mcycle.rs @@ -1,18 +1,3 @@ //! mcycle register -/// Reads the CSR -#[inline] -pub fn read() -> usize { - match () { - #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] - () => { - let r: usize; - unsafe { - asm!("csrrs $0, 0xB00, x0" : "=r"(r) ::: "volatile"); - } - r - } - #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] - () => unimplemented!(), - } -} +read_csr_as_usize!(0xB00); diff --git a/src/register/mcycleh.rs b/src/register/mcycleh.rs index 161e7fd..31ca70c 100644 --- a/src/register/mcycleh.rs +++ b/src/register/mcycleh.rs @@ -1,18 +1,3 @@ //! mcycleh register -/// Reads the CSR -#[inline] -pub fn read() -> usize { - match () { - #[cfg(target_arch = "riscv32")] - () => { - let r: usize; - unsafe { - asm!("csrrs $0, 0xB80, x0" : "=r"(r) ::: "volatile"); - } - r - } - #[cfg(not(target_arch = "riscv32"))] - () => unimplemented!(), - } -} +read_csr_as_usize_rv32!(0xB80); diff --git a/src/register/mepc.rs b/src/register/mepc.rs index 3a1a7d0..4fc7863 100644 --- a/src/register/mepc.rs +++ b/src/register/mepc.rs @@ -1,18 +1,3 @@ //! mepc register -/// Reads the CSR -#[inline] -pub fn read() -> usize { - match () { - #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] - () => { - let r: usize; - unsafe { - asm!("csrrs $0, 0x341, x0" : "=r"(r) ::: "volatile"); - } - r - }, - #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] - () => unimplemented!(), - } -} +read_csr_as_usize!(0x341); diff --git a/src/register/mie.rs b/src/register/mie.rs index fd0daad..0828cd8 100644 --- a/src/register/mie.rs +++ b/src/register/mie.rs @@ -68,71 +68,9 @@ impl Mie { } } -/// Reads the CSR -#[inline] -pub fn read() -> Mie { - match () { - #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] - () => { - let r: usize; - unsafe { - asm!("csrrs $0, 0x304, x0" : "=r"(r) ::: "volatile"); - } - Mie { bits: r } - } - #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] - () => unimplemented!(), - } -} - -/// Sets the CSR -#[cfg_attr(not(any(target_arch = "riscv32", target_arch = "riscv64")), allow(unused_variables))] -#[inline] -unsafe fn set(bits: usize) { - match () { - #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] - () => asm!("csrrs x0, 0x304, $0" :: "r"(bits) :: "volatile"), - #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] - () => unimplemented!(), - } -} - -/// Clears the CSR -#[cfg_attr(not(any(target_arch = "riscv32", target_arch = "riscv64")), allow(unused_variables))] -#[inline] -unsafe fn clear(bits: usize) { - match () { - #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] - () => asm!("csrrc x0, 0x304, $0" :: "r"(bits) :: "volatile"), - #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] - () => unimplemented!(), - } -} - -macro_rules! set_csr { - ($set_field:ident, $e:expr) => { - #[inline] - pub unsafe fn $set_field() { - set($e); - } - } -} - -macro_rules! clear_csr { - ($clear_field:ident, $e:expr) => { - #[inline] - pub unsafe fn $clear_field() { - clear($e); - } - } -} - -macro_rules! set_clear_csr { - ($set_field:ident, $clear_field:ident, $e:expr) => { - set_csr!($set_field, $e); - clear_csr!($clear_field, $e); - } -} +read_csr_as!(Mie, 0x304); +set!(0x304); +clear!(0x304); /// User Software Interrupt Enable set_clear_csr!(set_usoft, clear_usoft, 1 << 0); diff --git a/src/register/minstret.rs b/src/register/minstret.rs index b89aa32..aa072fd 100644 --- a/src/register/minstret.rs +++ b/src/register/minstret.rs @@ -1,18 +1,3 @@ //! minstret register -/// Reads the CSR -#[inline] -pub fn read() -> usize { - match () { - #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] - () => { - let r: usize; - unsafe { - asm!("csrrs $0, 0xB02, x0" : "=r"(r) ::: "volatile"); - } - r - } - #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] - () => unimplemented!(), - } -} +read_csr_as_usize!(0xB02); diff --git a/src/register/minstreth.rs b/src/register/minstreth.rs index ee149fc..5548399 100644 --- a/src/register/minstreth.rs +++ b/src/register/minstreth.rs @@ -1,18 +1,3 @@ //! minstreth register -/// Reads the CSR -#[inline] -pub fn read() -> usize { - match () { - #[cfg(target_arch = "riscv32")] - () => { - let r: usize; - unsafe { - asm!("csrrs $0, 0xB82, x0" : "=r"(r) ::: "volatile"); - } - r - }, - #[cfg(not(target_arch = "riscv32"))] - () => unimplemented!(), - } -} +read_csr_as_usize_rv32!(0xB82); diff --git a/src/register/mip.rs b/src/register/mip.rs index 35ebb23..39f1edd 100644 --- a/src/register/mip.rs +++ b/src/register/mip.rs @@ -68,19 +68,4 @@ impl Mip { } } -/// Reads the CSR -#[inline] -pub fn read() -> Mip { - match () { - #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] - () => { - let r: usize; - unsafe { - asm!("csrrs $0, 0x344, x0" : "=r"(r) ::: "volatile"); - } - Mip { bits: r } - } - #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] - () => unimplemented!(), - } -} +read_csr_as!(Mip, 0x344); diff --git a/src/register/misa.rs b/src/register/misa.rs index 8a1f061..9a2482d 100644 --- a/src/register/misa.rs +++ b/src/register/misa.rs @@ -47,21 +47,13 @@ impl Misa { } } +read_csr!(0x301); + /// Reads the CSR #[inline] pub fn read() -> Option { - match () { - #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] - () => { - let r: usize; - unsafe { - asm!("csrrs $0, 0x301, x0" : "=r"(r) ::: "volatile"); - } - // When misa is hardwired to zero it means that the misa csr - // isn't implemented. - NonZeroUsize::new(r).map(|bits| Misa { bits }) - }, - #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] - () => unimplemented!(), - } + let r = unsafe{ _read() }; + // When misa is hardwired to zero it means that the misa csr + // isn't implemented. + NonZeroUsize::new(r).map(|bits| Misa { bits }) } diff --git a/src/register/mstatus.rs b/src/register/mstatus.rs index 138a8ba..30ba4ec 100644 --- a/src/register/mstatus.rs +++ b/src/register/mstatus.rs @@ -79,71 +79,9 @@ impl Mstatus { } -/// Reads the CSR -#[inline] -pub fn read() -> Mstatus { - match () { - #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] - () => { - let r: usize; - unsafe { - asm!("csrrs $0, 0x300, x0" : "=r"(r) ::: "volatile"); - } - Mstatus { bits: r } - } - #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] - () => unimplemented!(), - } -} - -/// Sets the CSR -#[cfg_attr(not(any(target_arch = "riscv32", target_arch = "riscv64")), allow(unused_variables))] -#[inline] -unsafe fn set(bits: usize) { - match () { - #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] - () => asm!("csrrs x0, 0x300, $0" :: "r"(bits) :: "volatile"), - #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] - () => unimplemented!(), - } -} - -/// Clears the CSR -#[cfg_attr(not(any(target_arch = "riscv32", target_arch = "riscv64")), allow(unused_variables))] -#[inline] -unsafe fn clear(bits: usize) { - match () { - #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] - () => asm!("csrrc x0, 0x300, $0" :: "r"(bits) :: "volatile"), - #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] - () => unimplemented!(), - } -} - -macro_rules! set_csr { - ($set_field:ident, $e:expr) => { - #[inline] - pub unsafe fn $set_field() { - set($e); - } - } -} - -macro_rules! clear_csr { - ($clear_field:ident, $e:expr) => { - #[inline] - pub unsafe fn $clear_field() { - clear($e); - } - } -} - -macro_rules! set_clear_csr { - ($set_field:ident, $clear_field:ident, $e:expr) => { - set_csr!($set_field, $e); - clear_csr!($clear_field, $e); - } -} +read_csr_as!(Mstatus, 0x300); +set!(0x300); +clear!(0x300); /// User Interrupt Enable set_clear_csr!(set_uie, clear_uie, 1 << 0); @@ -160,10 +98,10 @@ set_csr!(set_mpie, 1 << 7); /// Supervisor Previous Privilege Mode #[inline] pub unsafe fn set_spp(spp: SPP) { - set((spp as usize) << 8); + _set((spp as usize) << 8); } /// Machine Previous Privilege Mode #[inline] pub unsafe fn set_mpp(mpp: MPP) { - set((mpp as usize) << 11); + _set((mpp as usize) << 11); } diff --git a/src/register/mtvec.rs b/src/register/mtvec.rs index d2b60dd..efa475e 100644 --- a/src/register/mtvec.rs +++ b/src/register/mtvec.rs @@ -34,32 +34,13 @@ impl Mtvec { } } -/// Reads the CSR -#[inline] -pub fn read() -> Mtvec { - match () { - #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] - () => { - let r: usize; - unsafe { - asm!("csrrs $0, 0x305, x0" : "=r"(r) ::: "volatile"); - } - Mtvec { bits: r } - } - #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] - () => unimplemented!(), - } -} +read_csr_as!(Mtvec, 0x305); + +write_csr!(0x305); /// Writes the CSR -#[cfg_attr(not(any(target_arch = "riscv32", target_arch = "riscv64")), allow(unused_variables))] #[inline] pub unsafe fn write(addr: usize, mode: TrapMode) { let bits = addr + mode as usize; - match () { - #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] - () => asm!("csrrw x0, 0x305, $0" :: "r"(bits) :: "volatile"), - #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] - () => unimplemented!(), - } + _write(bits); } diff --git a/src/register/mvendorid.rs b/src/register/mvendorid.rs index 37071dc..c2f831f 100644 --- a/src/register/mvendorid.rs +++ b/src/register/mvendorid.rs @@ -20,21 +20,13 @@ impl Mvendorid { } } +read_csr!(0xF11); + /// Reads the CSR #[inline] pub fn read() -> Option { - match () { - #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] - () => { - let r: usize; - unsafe { - asm!("csrrs $0, 0xF11, x0" : "=r"(r) ::: "volatile"); - } - // When mvendorid is hardwired to zero it means that the mvendorid - // csr isn't implemented. - NonZeroUsize::new(r).map(|bits| Mvendorid { bits }) - } - #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] - () => unimplemented!(), - } + let r = unsafe{ _read() }; + // When mvendorid is hardwired to zero it means that the mvendorid + // csr isn't implemented. + NonZeroUsize::new(r).map(|bits| Mvendorid { bits }) } diff --git a/src/register/timeh.rs b/src/register/timeh.rs index 97c4965..884c9ab 100644 --- a/src/register/timeh.rs +++ b/src/register/timeh.rs @@ -1,18 +1,3 @@ //! timeh register -/// Reads the CSR -#[inline] -pub fn read() -> usize { - match () { - #[cfg(target_arch = "riscv32")] - () => { - let r: usize; - unsafe { - asm!("csrrs $0, 0xC81, x0" : "=r"(r) ::: "volatile"); - } - r - } - #[cfg(not(target_arch = "riscv32"))] - () => unimplemented!(), - } -} \ No newline at end of file +read_csr_as_usize_rv32!(0xC81);