diff --git a/riscv/CHANGELOG.md b/riscv/CHANGELOG.md index fbe28bfa..3a0e1b40 100644 --- a/riscv/CHANGELOG.md +++ b/riscv/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added +- Add `read_bits`/`try_read_bits` and `write_bits`/`try_write_bits` to the CSR modules generated by `read_write_csr!` `read_only_csr!` and `write_only_csr!`. - Add `mireg` CSR - Add `stopei` and `vstopei` CSRs (AIA supervisor/virtual-supervisor top external interrupt), completing the `*topei` set alongside `mtopei`. diff --git a/riscv/src/register/macros.rs b/riscv/src/register/macros.rs index 3488868e..798940d6 100644 --- a/riscv/src/register/macros.rs +++ b/riscv/src/register/macros.rs @@ -70,6 +70,17 @@ macro_rules! read_csr_as { bits: unsafe { _read() }, } } + + /// Reads the raw bits of the CSR. + /// + /// Unlike [read], the value is not narrowed to the bitfields the + /// register type defines. + /// + /// **WARNING**: panics on non-`riscv` targets. + #[inline] + pub fn read_bits() -> usize { + unsafe { _read() } + } }; ($register:ident, $csr_number:literal, $($cfg:meta),*) => { @@ -82,6 +93,12 @@ macro_rules! read_csr_as { bits: unsafe { _try_read()? }, }) } + + /// Attempts to read the raw bits of the CSR. + #[inline] + pub fn try_read_bits() -> $crate::result::Result { + unsafe { _try_read() } + } }; ($register:ident, $csr_number:literal, $sentinel:tt, $($cfg:meta),*) => { @@ -95,6 +112,15 @@ macro_rules! read_csr_as { bits => Ok($register { bits }), } } + + /// Attempts to read the raw bits of the CSR. + #[inline] + pub fn try_read_bits() -> $crate::result::Result { + match unsafe { _try_read()? } { + $sentinel => Err($crate::result::Error::Unimplemented), + bits => Ok(bits), + } + } }; } @@ -214,6 +240,23 @@ macro_rules! write_csr_as { pub unsafe fn try_write(value: $csr_type) -> $crate::result::Result<()> { _try_write(value.bits) } + + /// Writes raw bits to the CSR. + /// + /// Unlike [write()], the bits are not narrowed to the bitfields the + /// register type defines. + /// + /// **WARNING**: panics on non-`riscv` targets. + #[inline] + pub unsafe fn write_bits(bits: usize) { + _write(bits); + } + + /// Attempts to write raw bits to the CSR. + #[inline] + pub unsafe fn try_write_bits(bits: usize) -> $crate::result::Result<()> { + _try_write(bits) + } }; (safe $csr_type:ty, $csr_number:literal, $($cfg:meta),*) => { $crate::write_csr!($csr_number, $($cfg),*); @@ -231,6 +274,23 @@ macro_rules! write_csr_as { pub fn try_write(value: $csr_type) -> $crate::result::Result<()> { unsafe { _try_write(value.bits) } } + + /// Writes raw bits to the CSR. + /// + /// Unlike [write()], the bits are not narrowed to the bitfields the + /// register type defines. + /// + /// **WARNING**: panics on non-`riscv` targets. + #[inline] + pub fn write_bits(bits: usize) { + unsafe { _write(bits) } + } + + /// Attempts to write raw bits to the CSR. + #[inline] + pub fn try_write_bits(bits: usize) -> $crate::result::Result<()> { + unsafe { _try_write(bits) } + } }; } diff --git a/riscv/src/register/tests/read_only_csr.rs b/riscv/src/register/tests/read_only_csr.rs index 64a36f17..27f46fcd 100644 --- a/riscv/src/register/tests/read_only_csr.rs +++ b/riscv/src/register/tests/read_only_csr.rs @@ -53,6 +53,21 @@ pub fn _try_read_csr() -> Result { try_read() } +#[allow(unused)] +pub fn _read_csr_bits() -> usize { + read_bits() +} + +#[allow(unused)] +pub fn _try_read_csr_bits() -> Result { + try_read_bits() +} + +#[test] +fn test_mtest_raw_bits() { + assert_eq!(try_read_bits(), Err(Error::Unimplemented)); +} + #[test] fn test_mtest_read_only() { let mut mtest = Mtest::from_bits(0); diff --git a/riscv/src/register/tests/read_write_csr.rs b/riscv/src/register/tests/read_write_csr.rs index d2a3d901..04a5fd88 100644 --- a/riscv/src/register/tests/read_write_csr.rs +++ b/riscv/src/register/tests/read_write_csr.rs @@ -63,6 +63,35 @@ pub fn _try_write_csr(csr: Mtest) { unsafe { try_write(csr) }; } +#[allow(unused)] +pub fn _read_csr_bits() -> usize { + read_bits() +} + +#[allow(unused)] +pub fn _try_read_csr_bits() -> Result { + try_read_bits() +} + +#[allow(unused)] +pub fn _write_csr_bits(bits: usize) { + unsafe { write_bits(bits) }; +} + +#[allow(unused)] +pub fn _try_write_csr_bits(bits: usize) -> Result<()> { + unsafe { try_write_bits(bits) } +} + +#[test] +fn test_mtest_raw_bits() { + assert_eq!(try_read_bits(), Err(Error::Unimplemented)); + assert_eq!( + unsafe { try_write_bits(!Mtest::BITMASK) }, + Err(Error::Unimplemented) + ); +} + #[test] fn test_mtest_read_write() { let mut mtest = Mtest::from_bits(0); diff --git a/riscv/src/register/tests/write_only_csr.rs b/riscv/src/register/tests/write_only_csr.rs index 94d37b31..6a845687 100644 --- a/riscv/src/register/tests/write_only_csr.rs +++ b/riscv/src/register/tests/write_only_csr.rs @@ -53,6 +53,24 @@ pub fn _try_write_csr(csr: Mtest) -> Result<()> { unsafe { try_write(csr) } } +#[allow(unused)] +pub fn _write_csr_bits(bits: usize) { + unsafe { write_bits(bits) }; +} + +#[allow(unused)] +pub fn _try_write_csr_bits(bits: usize) -> Result<()> { + unsafe { try_write_bits(bits) } +} + +#[test] +fn test_mtest_raw_bits() { + assert_eq!( + unsafe { try_write_bits(!Mtest::BITMASK) }, + Err(Error::Unimplemented) + ); +} + #[test] fn test_mtest_write_only() { let mut mtest = Mtest::from_bits(0);