From 2f9b748866c4e46abe5a546f5398a792f5347304 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 6 May 2024 17:51:02 -0700 Subject: [PATCH 1/8] Add Mstatus helpers to allow setting fields in Mstatus Without needing to touch the CSR. This allows multiple changes in a single register write. --- riscv/CHANGELOG.md | 2 + riscv/src/register/misa.rs | 6 +- riscv/src/register/mstatus.rs | 148 ++++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 3 deletions(-) diff --git a/riscv/CHANGELOG.md b/riscv/CHANGELOG.md index 90f45197..1e3dab78 100644 --- a/riscv/CHANGELOG.md +++ b/riscv/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Add `Mstatus::from(usize)` for use in unit tests - Add `Mstatus.bits()` - Add `Eq` and `PartialEq` for `pmpcfgx::{Range, Permission}` +- Add `Mstatus::set_*` helpers to manipulate Mstatus values without touching the + CSR - Export `riscv::register::macros` module macros for external use ### Fixed diff --git a/riscv/src/register/misa.rs b/riscv/src/register/misa.rs index db2cbc96..fd4f2167 100644 --- a/riscv/src/register/misa.rs +++ b/riscv/src/register/misa.rs @@ -11,9 +11,9 @@ pub struct Misa { /// Base integer ISA width #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum XLEN { - XLEN32, - XLEN64, - XLEN128, + XLEN32 = 1, + XLEN64 = 2, + XLEN128 = 3, } impl XLEN { diff --git a/riscv/src/register/mstatus.rs b/riscv/src/register/mstatus.rs index 6b8f3bc0..ae7c870d 100644 --- a/riscv/src/register/mstatus.rs +++ b/riscv/src/register/mstatus.rs @@ -72,6 +72,15 @@ impl From for Endianness { } impl Mstatus { + /// Helper to insert a bitfield into Mstatus + #[inline] + fn bf_insert(&self, bit: usize, width: usize, val: usize) -> Self { + let mask = (1 << width) - 1; + Self { + bits: self.bits & !(mask << bit) | ((val & mask) << bit), + } + } + /// Returns the contents of the register as raw bits #[inline] pub fn bits(&self) -> usize { @@ -84,30 +93,60 @@ impl Mstatus { self.bits & (1 << 1) != 0 } + /// Set Supervisor Interrupt Enable + #[inline] + pub fn set_sie(&self, sie: bool) -> Self { + self.bf_insert(1, 1, sie as usize) + } + /// Machine Interrupt Enable #[inline] pub fn mie(&self) -> bool { self.bits & (1 << 3) != 0 } + /// Set Machine Interrupt Enable + #[inline] + pub fn set_mie(&self, mie: bool) -> Self { + self.bf_insert(3, 1, mie as usize) + } + /// Supervisor Previous Interrupt Enable #[inline] pub fn spie(&self) -> bool { self.bits & (1 << 5) != 0 } + /// Supervisor Previous Interrupt Enable + #[inline] + pub fn set_spie(&self, spie: bool) -> Self { + self.bf_insert(5, 1, spie as usize) + } + /// U-mode non-instruction-fetch memory endianness #[inline] pub fn ube(&self) -> Endianness { Endianness::from(self.bits & (1 << 6) != 0) } + /// Set U-mode non-instruction-fetch memory endianness + #[inline] + pub fn set_ube(&self, endianness: Endianness) -> Self { + self.bf_insert(6, 1, endianness as usize) + } + /// Machine Previous Interrupt Enable #[inline] pub fn mpie(&self) -> bool { self.bits & (1 << 7) != 0 } + /// Set Machine Previous Interrupt Enable + #[inline] + pub fn set_mpie(&self, mpie: bool) -> Self { + self.bf_insert(7, 1, mpie as usize) + } + /// Supervisor Previous Privilege Mode #[inline] pub fn spp(&self) -> SPP { @@ -117,6 +156,12 @@ impl Mstatus { } } + /// Set Supervisor Previous Privilege Mode + #[inline] + pub fn set_spp(&self, spp: SPP) -> Self { + self.bf_insert(8, 1, spp as usize) + } + /// Machine Previous Privilege Mode #[inline] pub fn mpp(&self) -> MPP { @@ -129,6 +174,12 @@ impl Mstatus { } } + /// Set Machine Previous Privilege Mode + #[inline] + pub fn set_mpp(&self, mpp: MPP) -> Self { + self.bf_insert(11, 2, mpp as usize) + } + /// Floating-point extension state /// /// Encodes the status of the floating-point unit, @@ -145,6 +196,12 @@ impl Mstatus { } } + /// Set Floating-point extension state + #[inline] + pub fn set_fs(&self, fs: FS) -> Self { + self.bf_insert(13, 2, fs as usize) + } + /// Additional extension state /// /// Encodes the status of additional user-mode extensions and associated state. @@ -160,24 +217,48 @@ impl Mstatus { } } + /// Set Additional extension state + #[inline] + pub fn set_xs(&self, xs: XS) -> Self { + self.bf_insert(15, 2, xs as usize) + } + /// Modify Memory PRiVilege #[inline] pub fn mprv(&self) -> bool { self.bits & (1 << 17) != 0 } + /// Set Modify Memory PRiVilege + #[inline] + pub fn set_mprv(&self, mprv: bool) -> Self { + self.bf_insert(17, 1, mprv as usize) + } + /// Permit Supervisor User Memory access #[inline] pub fn sum(&self) -> bool { self.bits & (1 << 18) != 0 } + /// Set Permit Supervisor User Memory access + #[inline] + pub fn set_sum(&self, sum: bool) -> Self { + self.bf_insert(18, 1, sum as usize) + } + /// Make eXecutable Readable #[inline] pub fn mxr(&self) -> bool { self.bits & (1 << 19) != 0 } + /// Set Make eXecutable Readable + #[inline] + pub fn set_mxr(&self, mxr: bool) -> Self { + self.bf_insert(19, 1, mxr as usize) + } + /// Trap Virtual Memory /// /// If this bit is set, reads or writes to `satp` CSR or execute `sfence.vma` @@ -189,6 +270,12 @@ impl Mstatus { self.bits & (1 << 20) != 0 } + /// Set Trap Virtual Memory + #[inline] + pub fn set_tvm(&self, tvm: bool) -> Self { + self.bf_insert(20, 1, tvm as usize) + } + /// Timeout Wait /// /// Indicates that if WFI instruction should be intercepted. @@ -203,6 +290,12 @@ impl Mstatus { self.bits & (1 << 21) != 0 } + /// Set Timeout Wait + #[inline] + pub fn set_tw(&self, tw: bool) -> Self { + self.bf_insert(21, 1, tw as usize) + } + /// Trap SRET /// /// Indicates that if SRET instruction should be trapped to raise illegal @@ -214,6 +307,12 @@ impl Mstatus { self.bits & (1 << 22) != 0 } + /// Set Trap SRET + #[inline] + pub fn set_tsr(&self, tsr: bool) -> Self { + self.bf_insert(22, 1, tsr as usize) + } + /// Effective xlen in U-mode (i.e., `UXLEN`). /// /// In RISCV-32, UXL does not exist, and `UXLEN` is always [`XLEN::XLEN32`]. @@ -227,6 +326,17 @@ impl Mstatus { } } + /// Set Effective xlen in U-mode (i.e., `UXLEN`). + #[inline] + pub fn set_uxl(&self, uxl: XLEN) -> Self { + #[cfg(riscv32)] + { + *self + } + #[cfg(not(riscv32))] + self.bf_insert(32, 2, uxl as usize) + } + /// Effective xlen in S-mode (i.e., `SXLEN`). /// /// In RISCV-32, SXL does not exist, and SXLEN is always [`XLEN::XLEN32`]. @@ -240,6 +350,17 @@ impl Mstatus { } } + /// Set Effective xlen in S-mode (i.e., `SXLEN`). + #[inline] + pub fn set_sxl(&self, sxl: XLEN) -> Self { + #[cfg(riscv32)] + { + *self + } + #[cfg(not(riscv32))] + self.bf_insert(34, 2, sxl as usize) + } + /// S-mode non-instruction-fetch memory endianness. /// /// In RISCV-32, this field is read from the [`crate::register::mstatush`] register. @@ -252,6 +373,17 @@ impl Mstatus { } } + /// Set S-mode non-instruction-fetch memory endianness + #[inline] + pub fn set_sbe(&self, endianness: Endianness) -> Self { + #[cfg(riscv32)] + { + *self + } + #[cfg(not(riscv32))] + self.bf_insert(36, 1, endianness as usize) + } + /// M-mode non-instruction-fetch memory endianness /// /// In RISCV-32, this field is read from the [`crate::register::mstatush`] register @@ -264,11 +396,27 @@ impl Mstatus { } } + /// Set M-mode non-instruction-fetch memory endianness + pub fn set_mbe(&self, endianness: Endianness) -> Self { + #[cfg(riscv32)] + { + *self + } + #[cfg(not(riscv32))] + self.bf_insert(37, 1, endianness as usize) + } + /// Whether either the FS field or XS field signals the presence of some dirty state #[inline] pub fn sd(&self) -> bool { self.bits & (1 << (usize::BITS as usize - 1)) != 0 } + + /// Set whether either the FS field or XS field signals the presence of some dirty state + #[inline] + pub fn set_sd(&self, sd: bool) -> Self { + self.bf_insert(usize::BITS as usize - 1, 1, sd as usize) + } } read_csr_as!(Mstatus, 0x300); From eaac5cdd9e2c2626ee1e75104c14e9ecf30acdef Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 7 May 2024 08:14:42 -0700 Subject: [PATCH 2/8] mstatus: use `update_` for names And add a clarifying doc comment that this is an operation on Mstatus values, not on the CSR itself. --- riscv/CHANGELOG.md | 4 +- riscv/src/register/mstatus.rs | 143 ++++++++++++++++++++++++---------- 2 files changed, 104 insertions(+), 43 deletions(-) diff --git a/riscv/CHANGELOG.md b/riscv/CHANGELOG.md index 1e3dab78..8b26cf7f 100644 --- a/riscv/CHANGELOG.md +++ b/riscv/CHANGELOG.md @@ -13,8 +13,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Add `Mstatus::from(usize)` for use in unit tests - Add `Mstatus.bits()` - Add `Eq` and `PartialEq` for `pmpcfgx::{Range, Permission}` -- Add `Mstatus::set_*` helpers to manipulate Mstatus values without touching the - CSR +- Add `Mstatus::update_*` helpers to manipulate Mstatus values without touching + the CSR - Export `riscv::register::macros` module macros for external use ### Fixed diff --git a/riscv/src/register/mstatus.rs b/riscv/src/register/mstatus.rs index ae7c870d..16cf1997 100644 --- a/riscv/src/register/mstatus.rs +++ b/riscv/src/register/mstatus.rs @@ -93,9 +93,12 @@ impl Mstatus { self.bits & (1 << 1) != 0 } - /// Set Supervisor Interrupt Enable + /// Update Supervisor Interrupt Enable + /// + /// Note this updates the [`Mstatus`] value, but does not affect the mstatus + /// CSR itself. See [`set_sie`]/[`clear_sie`] to directly update the CSR. #[inline] - pub fn set_sie(&self, sie: bool) -> Self { + pub fn update_sie(&self, sie: bool) -> Self { self.bf_insert(1, 1, sie as usize) } @@ -105,9 +108,12 @@ impl Mstatus { self.bits & (1 << 3) != 0 } - /// Set Machine Interrupt Enable + /// Update Machine Interrupt Enable + /// + /// Note this updates the [`Mstatus`] value, but does not affect the mstatus + /// CSR itself. See [`set_mie`]/[`clear_mie`] to directly update the CSR. #[inline] - pub fn set_mie(&self, mie: bool) -> Self { + pub fn update_mie(&self, mie: bool) -> Self { self.bf_insert(3, 1, mie as usize) } @@ -117,9 +123,12 @@ impl Mstatus { self.bits & (1 << 5) != 0 } - /// Supervisor Previous Interrupt Enable + /// Updateervisor Previous Interrupt Enable + /// + /// Note this updates the [`Mstatus`] value, but does not affect the mstatus + /// CSR itself. See [`set_spie`]` to directly update the CSR. #[inline] - pub fn set_spie(&self, spie: bool) -> Self { + pub fn update_spie(&self, spie: bool) -> Self { self.bf_insert(5, 1, spie as usize) } @@ -129,9 +138,12 @@ impl Mstatus { Endianness::from(self.bits & (1 << 6) != 0) } - /// Set U-mode non-instruction-fetch memory endianness + /// Update U-mode non-instruction-fetch memory endianness + /// + /// Note this updates the [`Mstatus`] value, but does not affect the mstatus + /// CSR itself. See [`set_ube`] to directly update the CSR. #[inline] - pub fn set_ube(&self, endianness: Endianness) -> Self { + pub fn update_ube(&self, endianness: Endianness) -> Self { self.bf_insert(6, 1, endianness as usize) } @@ -141,9 +153,12 @@ impl Mstatus { self.bits & (1 << 7) != 0 } - /// Set Machine Previous Interrupt Enable + /// Update Machine Previous Interrupt Enable + /// + /// Note this updates the [`Mstatus`] value, but does not affect the mstatus + /// CSR itself. See [`set_mpie`] to directly update the CSR. #[inline] - pub fn set_mpie(&self, mpie: bool) -> Self { + pub fn update_mpie(&self, mpie: bool) -> Self { self.bf_insert(7, 1, mpie as usize) } @@ -156,9 +171,12 @@ impl Mstatus { } } - /// Set Supervisor Previous Privilege Mode + /// Update Supervisor Previous Privilege Mode + /// + /// Note this updates the [`Mstatus`] value, but does not affect the mstatus + /// CSR itself. See [`set_spp`] to directly update the CSR. #[inline] - pub fn set_spp(&self, spp: SPP) -> Self { + pub fn update_spp(&self, spp: SPP) -> Self { self.bf_insert(8, 1, spp as usize) } @@ -174,9 +192,12 @@ impl Mstatus { } } - /// Set Machine Previous Privilege Mode + /// Update Machine Previous Privilege Mode + /// + /// Note this updates the [`Mstatus`] value, but does not affect the mstatus + /// CSR itself. See [`set_mpp`] to directly update the CSR. #[inline] - pub fn set_mpp(&self, mpp: MPP) -> Self { + pub fn update_mpp(&self, mpp: MPP) -> Self { self.bf_insert(11, 2, mpp as usize) } @@ -196,9 +217,12 @@ impl Mstatus { } } - /// Set Floating-point extension state + /// Update Floating-point extension state + /// + /// Note this updates the [`Mstatus`] value, but does not affect the mstatus + /// CSR itself. See [`set_fs`] to directly update the CSR. #[inline] - pub fn set_fs(&self, fs: FS) -> Self { + pub fn update_fs(&self, fs: FS) -> Self { self.bf_insert(13, 2, fs as usize) } @@ -217,9 +241,12 @@ impl Mstatus { } } - /// Set Additional extension state + /// Update Additional extension state + /// + /// Note this updates the [`Mstatus`] value, but does not affect the mstatus + /// CSR itself. #[inline] - pub fn set_xs(&self, xs: XS) -> Self { + pub fn update_xs(&self, xs: XS) -> Self { self.bf_insert(15, 2, xs as usize) } @@ -229,9 +256,12 @@ impl Mstatus { self.bits & (1 << 17) != 0 } - /// Set Modify Memory PRiVilege + /// Update Modify Memory PRiVilege + /// + /// Note this updates the [`Mstatus`] value, but does not affect the mstatus + /// CSR itself. See [`set_mprv`]/[`clear_mprv`] to directly update the CSR. #[inline] - pub fn set_mprv(&self, mprv: bool) -> Self { + pub fn update_mprv(&self, mprv: bool) -> Self { self.bf_insert(17, 1, mprv as usize) } @@ -241,9 +271,12 @@ impl Mstatus { self.bits & (1 << 18) != 0 } - /// Set Permit Supervisor User Memory access + /// Update Permit Supervisor User Memory access + /// + /// Note this updates the [`Mstatus`] value, but does not affect the mstatus + /// CSR itself. See [`set_sum`]/[`clear_sum`] to directly update the CSR. #[inline] - pub fn set_sum(&self, sum: bool) -> Self { + pub fn update_sum(&self, sum: bool) -> Self { self.bf_insert(18, 1, sum as usize) } @@ -253,9 +286,12 @@ impl Mstatus { self.bits & (1 << 19) != 0 } - /// Set Make eXecutable Readable + /// Update Make eXecutable Readable + /// + /// Note this updates the [`Mstatus`] value, but does not affect the mstatus + /// CSR itself. See [`set_mxr`]/[`clear_mxr`] to directly update the CSR. #[inline] - pub fn set_mxr(&self, mxr: bool) -> Self { + pub fn update_mxr(&self, mxr: bool) -> Self { self.bf_insert(19, 1, mxr as usize) } @@ -270,9 +306,12 @@ impl Mstatus { self.bits & (1 << 20) != 0 } - /// Set Trap Virtual Memory + /// Update Trap Virtual Memory + /// + /// Note this updates the [`Mstatus`] value, but does not affect the mstatus + /// CSR itself. See [`set_tvm`]/[`clear_tvm`] to directly update the CSR. #[inline] - pub fn set_tvm(&self, tvm: bool) -> Self { + pub fn update_tvm(&self, tvm: bool) -> Self { self.bf_insert(20, 1, tvm as usize) } @@ -290,9 +329,12 @@ impl Mstatus { self.bits & (1 << 21) != 0 } - /// Set Timeout Wait + /// Update Timeout Wait + /// + /// Note this updates the [`Mstatus`] value, but does not affect the mstatus + /// CSR itself. See [`set_tw`]/[`clear_tw`] to directly update the CSR. #[inline] - pub fn set_tw(&self, tw: bool) -> Self { + pub fn update_tw(&self, tw: bool) -> Self { self.bf_insert(21, 1, tw as usize) } @@ -307,9 +349,12 @@ impl Mstatus { self.bits & (1 << 22) != 0 } - /// Set Trap SRET + /// Update Trap SRET + /// + /// Note this updates the [`Mstatus`] value, but does not affect the mstatus + /// CSR itself. See [`set_tsr`]/[`clear_tsr`] to directly update the CSR. #[inline] - pub fn set_tsr(&self, tsr: bool) -> Self { + pub fn update_tsr(&self, tsr: bool) -> Self { self.bf_insert(22, 1, tsr as usize) } @@ -326,9 +371,12 @@ impl Mstatus { } } - /// Set Effective xlen in U-mode (i.e., `UXLEN`). + /// Update Effective xlen in U-mode (i.e., `UXLEN`). + /// + /// Note this updates the [`Mstatus`] value, but does not affect the mstatus + /// CSR itself. #[inline] - pub fn set_uxl(&self, uxl: XLEN) -> Self { + pub fn update_uxl(&self, uxl: XLEN) -> Self { #[cfg(riscv32)] { *self @@ -350,9 +398,12 @@ impl Mstatus { } } - /// Set Effective xlen in S-mode (i.e., `SXLEN`). + /// Update Effective xlen in S-mode (i.e., `SXLEN`). + /// + /// Note this updates the [`Mstatus`] value, but does not affect the mstatus + /// CSR itself. #[inline] - pub fn set_sxl(&self, sxl: XLEN) -> Self { + pub fn update_sxl(&self, sxl: XLEN) -> Self { #[cfg(riscv32)] { *self @@ -373,9 +424,12 @@ impl Mstatus { } } - /// Set S-mode non-instruction-fetch memory endianness + /// Update S-mode non-instruction-fetch memory endianness + /// + /// Note this updates the [`Mstatus`] value, but does not affect the mstatus + /// CSR itself. See [`set_sbe`] to directly update the CSR. #[inline] - pub fn set_sbe(&self, endianness: Endianness) -> Self { + pub fn update_sbe(&self, endianness: Endianness) -> Self { #[cfg(riscv32)] { *self @@ -395,9 +449,12 @@ impl Mstatus { () => Endianness::from(self.bits & (1 << 37) != 0), } } - - /// Set M-mode non-instruction-fetch memory endianness - pub fn set_mbe(&self, endianness: Endianness) -> Self { + /// Update M-mode non-instruction-fetch memory endianness + /// + /// Note this updates the [`Mstatus`] value, but does not affect the mstatus + /// CSR itself. See [`set_mbe`] to directly update the CSR. + #[inline] + pub fn update_mbe(&self, endianness: Endianness) -> Self { #[cfg(riscv32)] { *self @@ -412,9 +469,13 @@ impl Mstatus { self.bits & (1 << (usize::BITS as usize - 1)) != 0 } - /// Set whether either the FS field or XS field signals the presence of some dirty state + /// Update whether either the FS field or XS field signals the presence of + /// some dirty state + /// + /// Note this updates the [`Mstatus`] value, but does not affect the mstatus + /// CSR itself. #[inline] - pub fn set_sd(&self, sd: bool) -> Self { + pub fn update_sd(&self, sd: bool) -> Self { self.bf_insert(usize::BITS as usize - 1, 1, sd as usize) } } From b061e7ecae98784fda02c0e36698a12e970232ee Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 7 May 2024 09:17:30 -0700 Subject: [PATCH 3/8] Add `write_csr_as` macro This adds a macro to generate `write(value:T)` function for writing a structured value to a CSR. --- riscv/src/register/macros.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/riscv/src/register/macros.rs b/riscv/src/register/macros.rs index 5343e69f..d2dfcb49 100644 --- a/riscv/src/register/macros.rs +++ b/riscv/src/register/macros.rs @@ -160,6 +160,34 @@ macro_rules! write_csr_rv32 { }; } +/// Convenience macro to write a value with `bits` to a CSR +#[macro_export] +macro_rules! write_csr_as { + ($csr_type:ty, $csr_number:literal) => { + $crate::write_csr!($csr_number); + + /// Writes the CSR + #[inline] + pub fn write(value: $csr_type) { + unsafe { _write(value.bits) } + } + }; +} + +/// Convenience macro to write a value to a CSR register. +#[macro_export] +macro_rules! write_csr_as_rv32 { + ($csr_type:ty, $csr_number:literal) => { + $crate::write_csr_rv32!($csr_number); + + /// Writes the CSR + #[inline] + pub fn write(value: $csr_type) { + unsafe { _write(value.bits) } + } + }; +} + /// Convenience macro to write a [`usize`] value to a CSR register. #[macro_export] macro_rules! write_csr_as_usize { From 47ca030485dd2411b82f32616284e22abf9bb123 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 7 May 2024 09:04:49 -0700 Subject: [PATCH 4/8] Make mstatus::write(Mstatus) available Allow `Mstatus` values to be directly written back to the CSR. --- riscv/src/register/mstatus.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/src/register/mstatus.rs b/riscv/src/register/mstatus.rs index 16cf1997..cb7bdfb6 100644 --- a/riscv/src/register/mstatus.rs +++ b/riscv/src/register/mstatus.rs @@ -481,7 +481,7 @@ impl Mstatus { } read_csr_as!(Mstatus, 0x300); -write_csr!(0x300); +write_csr_as!(Mstatus, 0x300); set!(0x300); clear!(0x300); From c05838a9d30a2a959691ecd8f039139f70f357fa Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 7 May 2024 11:31:21 -0700 Subject: [PATCH 5/8] Add some minimal tests --- riscv/src/register/mstatus.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/riscv/src/register/mstatus.rs b/riscv/src/register/mstatus.rs index cb7bdfb6..286cbabc 100644 --- a/riscv/src/register/mstatus.rs +++ b/riscv/src/register/mstatus.rs @@ -593,3 +593,19 @@ pub unsafe fn set_mbe(endianness: Endianness) { }, } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_mpp() { + let mut mstatus = Mstatus { bits: 0 }; + mstatus = mstatus.update_mpp(MPP::User); + assert_eq!(mstatus.mpp(), MPP::User); + mstatus = mstatus.update_mpp(MPP::Machine); + assert_eq!(mstatus.mpp(), MPP::Machine); + mstatus = mstatus.update_mpp(MPP::Supervisor); + assert_eq!(mstatus.mpp(), MPP::Supervisor); + } +} From 8de908c11a5c39b059973d32e6a0957f7b391f3e Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 8 May 2024 12:11:49 -0700 Subject: [PATCH 6/8] Change back to set_ to match cortex and tweak docs a bit --- riscv/src/register/mstatus.rs | 151 +++++++++++++++++++--------------- 1 file changed, 84 insertions(+), 67 deletions(-) diff --git a/riscv/src/register/mstatus.rs b/riscv/src/register/mstatus.rs index 286cbabc..15243816 100644 --- a/riscv/src/register/mstatus.rs +++ b/riscv/src/register/mstatus.rs @@ -95,10 +95,11 @@ impl Mstatus { /// Update Supervisor Interrupt Enable /// - /// Note this updates the [`Mstatus`] value, but does not affect the mstatus - /// CSR itself. See [`set_sie`]/[`clear_sie`] to directly update the CSR. + /// Note this updates a previously read [`Mstatus`] value, but does not + /// affect the mstatus CSR itself. See [`set_sie`]/[`clear_sie`] to directly + /// update the CSR. #[inline] - pub fn update_sie(&self, sie: bool) -> Self { + pub fn set_sie(&self, sie: bool) -> Self { self.bf_insert(1, 1, sie as usize) } @@ -110,10 +111,11 @@ impl Mstatus { /// Update Machine Interrupt Enable /// - /// Note this updates the [`Mstatus`] value, but does not affect the mstatus - /// CSR itself. See [`set_mie`]/[`clear_mie`] to directly update the CSR. + /// Note this updates a previously read [`Mstatus`] value, but does not + /// affect the mstatus CSR itself. See [`set_mie`]/[`clear_mie`] to directly + /// update the CSR. #[inline] - pub fn update_mie(&self, mie: bool) -> Self { + pub fn set_mie(&self, mie: bool) -> Self { self.bf_insert(3, 1, mie as usize) } @@ -123,12 +125,13 @@ impl Mstatus { self.bits & (1 << 5) != 0 } - /// Updateervisor Previous Interrupt Enable + /// Update Supervisor Previous Interrupt Enable /// - /// Note this updates the [`Mstatus`] value, but does not affect the mstatus - /// CSR itself. See [`set_spie`]` to directly update the CSR. + /// Note this updates a previously read [`Mstatus`] value, but does not + /// affect the mstatus CSR itself. See [`set_spie`]` to directly update the + /// CSR. #[inline] - pub fn update_spie(&self, spie: bool) -> Self { + pub fn set_spie(&self, spie: bool) -> Self { self.bf_insert(5, 1, spie as usize) } @@ -140,10 +143,11 @@ impl Mstatus { /// Update U-mode non-instruction-fetch memory endianness /// - /// Note this updates the [`Mstatus`] value, but does not affect the mstatus - /// CSR itself. See [`set_ube`] to directly update the CSR. + /// Note this updates a previously read [`Mstatus`] value, but does not + /// affect the mstatus CSR itself. See [`set_ube`] to directly update the + /// CSR. #[inline] - pub fn update_ube(&self, endianness: Endianness) -> Self { + pub fn set_ube(&self, endianness: Endianness) -> Self { self.bf_insert(6, 1, endianness as usize) } @@ -155,10 +159,11 @@ impl Mstatus { /// Update Machine Previous Interrupt Enable /// - /// Note this updates the [`Mstatus`] value, but does not affect the mstatus - /// CSR itself. See [`set_mpie`] to directly update the CSR. + /// Note this updates a previously read [`Mstatus`] value, but does not + /// affect the mstatus CSR itself. See [`set_mpie`] to directly update the + /// CSR. #[inline] - pub fn update_mpie(&self, mpie: bool) -> Self { + pub fn set_mpie(&self, mpie: bool) -> Self { self.bf_insert(7, 1, mpie as usize) } @@ -173,10 +178,11 @@ impl Mstatus { /// Update Supervisor Previous Privilege Mode /// - /// Note this updates the [`Mstatus`] value, but does not affect the mstatus - /// CSR itself. See [`set_spp`] to directly update the CSR. + /// Note this updates a previously read [`Mstatus`] value, but does not + /// affect the mstatus CSR itself. See [`set_spp`] to directly update the + /// CSR. #[inline] - pub fn update_spp(&self, spp: SPP) -> Self { + pub fn set_spp(&self, spp: SPP) -> Self { self.bf_insert(8, 1, spp as usize) } @@ -194,17 +200,18 @@ impl Mstatus { /// Update Machine Previous Privilege Mode /// - /// Note this updates the [`Mstatus`] value, but does not affect the mstatus - /// CSR itself. See [`set_mpp`] to directly update the CSR. + /// Note this updates a previously read [`Mstatus`] value, but does not + /// affect the mstatus CSR itself. See [`set_mpp`] to directly update the + /// CSR. #[inline] - pub fn update_mpp(&self, mpp: MPP) -> Self { + pub fn set_mpp(&self, mpp: MPP) -> Self { self.bf_insert(11, 2, mpp as usize) } /// Floating-point extension state /// - /// Encodes the status of the floating-point unit, - /// including the CSR `fcsr` and floating-point data registers `f0–f31`. + /// Encodes the status of the floating-point unit, including the CSR `fcsr` + /// and floating-point data registers `f0–f31`. #[inline] pub fn fs(&self) -> FS { let fs = (self.bits >> 13) & 0x3; // bits 13-14 @@ -219,16 +226,18 @@ impl Mstatus { /// Update Floating-point extension state /// - /// Note this updates the [`Mstatus`] value, but does not affect the mstatus - /// CSR itself. See [`set_fs`] to directly update the CSR. + /// Note this updates a previously read [`Mstatus`] value, but does not + /// affect the mstatus CSR itself. See [`set_fs`] to directly update the + /// CSR. #[inline] - pub fn update_fs(&self, fs: FS) -> Self { + pub fn set_fs(&self, fs: FS) -> Self { self.bf_insert(13, 2, fs as usize) } /// Additional extension state /// - /// Encodes the status of additional user-mode extensions and associated state. + /// Encodes the status of additional user-mode extensions and associated + /// state. #[inline] pub fn xs(&self) -> XS { let xs = (self.bits >> 15) & 0x3; // bits 15-16 @@ -243,10 +252,10 @@ impl Mstatus { /// Update Additional extension state /// - /// Note this updates the [`Mstatus`] value, but does not affect the mstatus - /// CSR itself. + /// Note this updates a previously read [`Mstatus`] value, but does not + /// affect the mstatus CSR itself. #[inline] - pub fn update_xs(&self, xs: XS) -> Self { + pub fn set_xs(&self, xs: XS) -> Self { self.bf_insert(15, 2, xs as usize) } @@ -258,10 +267,11 @@ impl Mstatus { /// Update Modify Memory PRiVilege /// - /// Note this updates the [`Mstatus`] value, but does not affect the mstatus - /// CSR itself. See [`set_mprv`]/[`clear_mprv`] to directly update the CSR. + /// Note this updates a previously read [`Mstatus`] value, but does not + /// affect the mstatus CSR itself. See [`set_mprv`]/[`clear_mprv`] to + /// directly update the CSR. #[inline] - pub fn update_mprv(&self, mprv: bool) -> Self { + pub fn set_mprv(&self, mprv: bool) -> Self { self.bf_insert(17, 1, mprv as usize) } @@ -273,10 +283,11 @@ impl Mstatus { /// Update Permit Supervisor User Memory access /// - /// Note this updates the [`Mstatus`] value, but does not affect the mstatus - /// CSR itself. See [`set_sum`]/[`clear_sum`] to directly update the CSR. + /// Note this updates a previously read [`Mstatus`] value, but does not + /// affect the mstatus CSR itself. See [`set_sum`]/[`clear_sum`] to directly + /// update the CSR. #[inline] - pub fn update_sum(&self, sum: bool) -> Self { + pub fn set_sum(&self, sum: bool) -> Self { self.bf_insert(18, 1, sum as usize) } @@ -288,10 +299,11 @@ impl Mstatus { /// Update Make eXecutable Readable /// - /// Note this updates the [`Mstatus`] value, but does not affect the mstatus - /// CSR itself. See [`set_mxr`]/[`clear_mxr`] to directly update the CSR. + /// Note this updates a previously read [`Mstatus`] value, but does not affect + /// the mstatus CSR itself. See [`set_mxr`]/[`clear_mxr`] to directly update + /// the CSR. #[inline] - pub fn update_mxr(&self, mxr: bool) -> Self { + pub fn set_mxr(&self, mxr: bool) -> Self { self.bf_insert(19, 1, mxr as usize) } @@ -308,10 +320,11 @@ impl Mstatus { /// Update Trap Virtual Memory /// - /// Note this updates the [`Mstatus`] value, but does not affect the mstatus - /// CSR itself. See [`set_tvm`]/[`clear_tvm`] to directly update the CSR. + /// Note this updates a previously read [`Mstatus`] value, but does not + /// affect the mstatus CSR itself. See [`set_tvm`]/[`clear_tvm`] to directly + /// update the CSR. #[inline] - pub fn update_tvm(&self, tvm: bool) -> Self { + pub fn set_tvm(&self, tvm: bool) -> Self { self.bf_insert(20, 1, tvm as usize) } @@ -331,10 +344,11 @@ impl Mstatus { /// Update Timeout Wait /// - /// Note this updates the [`Mstatus`] value, but does not affect the mstatus - /// CSR itself. See [`set_tw`]/[`clear_tw`] to directly update the CSR. + /// Note this updates a previously read [`Mstatus`] value, but does not + /// affect the mstatus CSR itself. See [`set_tw`]/[`clear_tw`] to directly + /// update the CSR. #[inline] - pub fn update_tw(&self, tw: bool) -> Self { + pub fn set_tw(&self, tw: bool) -> Self { self.bf_insert(21, 1, tw as usize) } @@ -351,10 +365,11 @@ impl Mstatus { /// Update Trap SRET /// - /// Note this updates the [`Mstatus`] value, but does not affect the mstatus - /// CSR itself. See [`set_tsr`]/[`clear_tsr`] to directly update the CSR. + /// Note this updates a previously read [`Mstatus`] value, but does not + /// affect the mstatus CSR itself. See [`set_tsr`]/[`clear_tsr`] to directly + /// update the CSR. #[inline] - pub fn update_tsr(&self, tsr: bool) -> Self { + pub fn set_tsr(&self, tsr: bool) -> Self { self.bf_insert(22, 1, tsr as usize) } @@ -373,10 +388,10 @@ impl Mstatus { /// Update Effective xlen in U-mode (i.e., `UXLEN`). /// - /// Note this updates the [`Mstatus`] value, but does not affect the mstatus - /// CSR itself. + /// Note this updates a previously read [`Mstatus`] value, but does not + /// affect the mstatus CSR itself. #[inline] - pub fn update_uxl(&self, uxl: XLEN) -> Self { + pub fn set_uxl(&self, uxl: XLEN) -> Self { #[cfg(riscv32)] { *self @@ -400,10 +415,10 @@ impl Mstatus { /// Update Effective xlen in S-mode (i.e., `SXLEN`). /// - /// Note this updates the [`Mstatus`] value, but does not affect the mstatus - /// CSR itself. + /// Note this updates a previously read [`Mstatus`] value, but does not + /// affect the mstatus CSR itself. #[inline] - pub fn update_sxl(&self, sxl: XLEN) -> Self { + pub fn set_sxl(&self, sxl: XLEN) -> Self { #[cfg(riscv32)] { *self @@ -426,10 +441,11 @@ impl Mstatus { /// Update S-mode non-instruction-fetch memory endianness /// - /// Note this updates the [`Mstatus`] value, but does not affect the mstatus - /// CSR itself. See [`set_sbe`] to directly update the CSR. + /// Note this updates a previously read [`Mstatus`] value, but does not + /// affect the mstatus CSR itself. See [`set_sbe`] to directly update the + /// CSR. #[inline] - pub fn update_sbe(&self, endianness: Endianness) -> Self { + pub fn set_sbe(&self, endianness: Endianness) -> Self { #[cfg(riscv32)] { *self @@ -451,10 +467,11 @@ impl Mstatus { } /// Update M-mode non-instruction-fetch memory endianness /// - /// Note this updates the [`Mstatus`] value, but does not affect the mstatus - /// CSR itself. See [`set_mbe`] to directly update the CSR. + /// Note this updates a previously read [`Mstatus`] value, but does not + /// affect the mstatus CSR itself. See [`set_mbe`] to directly update the + /// CSR. #[inline] - pub fn update_mbe(&self, endianness: Endianness) -> Self { + pub fn set_mbe(&self, endianness: Endianness) -> Self { #[cfg(riscv32)] { *self @@ -472,10 +489,10 @@ impl Mstatus { /// Update whether either the FS field or XS field signals the presence of /// some dirty state /// - /// Note this updates the [`Mstatus`] value, but does not affect the mstatus - /// CSR itself. + /// Note this updates a previously read [`Mstatus`] value, but does not + /// affect the mstatus CSR itself. #[inline] - pub fn update_sd(&self, sd: bool) -> Self { + pub fn set_sd(&self, sd: bool) -> Self { self.bf_insert(usize::BITS as usize - 1, 1, sd as usize) } } @@ -601,11 +618,11 @@ mod test { #[test] fn test_mpp() { let mut mstatus = Mstatus { bits: 0 }; - mstatus = mstatus.update_mpp(MPP::User); + mstatus = mstatus.set_mpp(MPP::User); assert_eq!(mstatus.mpp(), MPP::User); - mstatus = mstatus.update_mpp(MPP::Machine); + mstatus = mstatus.set_mpp(MPP::Machine); assert_eq!(mstatus.mpp(), MPP::Machine); - mstatus = mstatus.update_mpp(MPP::Supervisor); + mstatus = mstatus.set_mpp(MPP::Supervisor); assert_eq!(mstatus.mpp(), MPP::Supervisor); } } From f968990b137cddf0c0b59a03dfd7142f1bf47eab Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 8 May 2024 12:29:47 -0700 Subject: [PATCH 7/8] Add bitfield helpers and use them in mstatus --- riscv/src/bits.rs | 17 ++++++++++++ riscv/src/lib.rs | 1 + riscv/src/register/mstatus.rs | 50 ++++++++++++++++++++--------------- 3 files changed, 46 insertions(+), 22 deletions(-) create mode 100644 riscv/src/bits.rs diff --git a/riscv/src/bits.rs b/riscv/src/bits.rs new file mode 100644 index 00000000..d58152c2 --- /dev/null +++ b/riscv/src/bits.rs @@ -0,0 +1,17 @@ +/// Insert a new value into a bitfield +/// +/// `value` is masked to `width` bits and inserted into `orig`.` +#[inline] +pub fn bf_insert(orig: usize, bit: usize, width: usize, value: usize) -> usize { + let mask = (1 << width) - 1; + orig & !(mask << bit) | ((value & mask) << bit) +} + +/// Extract a value from a bitfield +/// +/// Extracts `width` bits from bit offset `bit` and returns it shifted to bit 0.s +#[inline] +pub fn bf_extract(orig: usize, bit: usize, width: usize) -> usize { + let mask = (1 << width) - 1; + (orig >> bit) & mask +} diff --git a/riscv/src/lib.rs b/riscv/src/lib.rs index 7eacac7a..cb6f6ed8 100644 --- a/riscv/src/lib.rs +++ b/riscv/src/lib.rs @@ -36,6 +36,7 @@ #![allow(clippy::missing_safety_doc)] pub mod asm; +pub(crate) mod bits; pub mod delay; pub mod interrupt; pub mod register; diff --git a/riscv/src/register/mstatus.rs b/riscv/src/register/mstatus.rs index 15243816..bc97d493 100644 --- a/riscv/src/register/mstatus.rs +++ b/riscv/src/register/mstatus.rs @@ -1,6 +1,7 @@ //! mstatus register pub use super::misa::XLEN; +use crate::bits::{bf_extract, bf_insert}; /// mstatus register #[derive(Clone, Copy, Debug)] @@ -75,12 +76,17 @@ impl Mstatus { /// Helper to insert a bitfield into Mstatus #[inline] fn bf_insert(&self, bit: usize, width: usize, val: usize) -> Self { - let mask = (1 << width) - 1; Self { - bits: self.bits & !(mask << bit) | ((val & mask) << bit), + bits: bf_insert(self.bits, bit, width, val), } } + /// Helper to extract a bitfield from Mstatus + #[inline] + fn bf_extract(&self, bit: usize, width: usize) -> usize { + bf_extract(self.bits, bit, width) + } + /// Returns the contents of the register as raw bits #[inline] pub fn bits(&self) -> usize { @@ -90,7 +96,7 @@ impl Mstatus { /// Supervisor Interrupt Enable #[inline] pub fn sie(&self) -> bool { - self.bits & (1 << 1) != 0 + self.bf_extract(1, 1) != 0 } /// Update Supervisor Interrupt Enable @@ -106,7 +112,7 @@ impl Mstatus { /// Machine Interrupt Enable #[inline] pub fn mie(&self) -> bool { - self.bits & (1 << 3) != 0 + self.bf_extract(3, 1) != 0 } /// Update Machine Interrupt Enable @@ -122,7 +128,7 @@ impl Mstatus { /// Supervisor Previous Interrupt Enable #[inline] pub fn spie(&self) -> bool { - self.bits & (1 << 5) != 0 + self.bf_extract(5, 1) != 0 } /// Update Supervisor Previous Interrupt Enable @@ -138,7 +144,7 @@ impl Mstatus { /// U-mode non-instruction-fetch memory endianness #[inline] pub fn ube(&self) -> Endianness { - Endianness::from(self.bits & (1 << 6) != 0) + Endianness::from(self.bf_extract(6, 1) != 0) } /// Update U-mode non-instruction-fetch memory endianness @@ -154,7 +160,7 @@ impl Mstatus { /// Machine Previous Interrupt Enable #[inline] pub fn mpie(&self) -> bool { - self.bits & (1 << 7) != 0 + self.bf_extract(7, 1) != 0 } /// Update Machine Previous Interrupt Enable @@ -170,7 +176,7 @@ impl Mstatus { /// Supervisor Previous Privilege Mode #[inline] pub fn spp(&self) -> SPP { - match self.bits & (1 << 8) != 0 { + match self.bf_extract(7, 1) != 0 { true => SPP::Supervisor, false => SPP::User, } @@ -189,7 +195,7 @@ impl Mstatus { /// Machine Previous Privilege Mode #[inline] pub fn mpp(&self) -> MPP { - let mpp = (self.bits >> 11) & 0x3; // bits 11-12 + let mpp = self.bf_extract(11, 2); // bits 11-12 match mpp { 0b00 => MPP::User, 0b01 => MPP::Supervisor, @@ -214,7 +220,7 @@ impl Mstatus { /// and floating-point data registers `f0–f31`. #[inline] pub fn fs(&self) -> FS { - let fs = (self.bits >> 13) & 0x3; // bits 13-14 + let fs = self.bf_extract(13, 2); // bits 13-14 match fs { 0b00 => FS::Off, 0b01 => FS::Initial, @@ -240,7 +246,7 @@ impl Mstatus { /// state. #[inline] pub fn xs(&self) -> XS { - let xs = (self.bits >> 15) & 0x3; // bits 15-16 + let xs = self.bf_extract(15, 2); // bits 15-16 match xs { 0b00 => XS::AllOff, 0b01 => XS::NoneDirtyOrClean, @@ -262,7 +268,7 @@ impl Mstatus { /// Modify Memory PRiVilege #[inline] pub fn mprv(&self) -> bool { - self.bits & (1 << 17) != 0 + self.bf_extract(17, 1) != 0 } /// Update Modify Memory PRiVilege @@ -278,7 +284,7 @@ impl Mstatus { /// Permit Supervisor User Memory access #[inline] pub fn sum(&self) -> bool { - self.bits & (1 << 18) != 0 + self.bf_extract(18, 1) != 0 } /// Update Permit Supervisor User Memory access @@ -294,7 +300,7 @@ impl Mstatus { /// Make eXecutable Readable #[inline] pub fn mxr(&self) -> bool { - self.bits & (1 << 19) != 0 + self.bf_extract(19, 1) != 0 } /// Update Make eXecutable Readable @@ -315,7 +321,7 @@ impl Mstatus { /// TVM is hard-wired to 0 when S-mode is not supported. #[inline] pub fn tvm(&self) -> bool { - self.bits & (1 << 20) != 0 + self.bf_extract(20, 1) != 0 } /// Update Trap Virtual Memory @@ -339,7 +345,7 @@ impl Mstatus { /// TW is hard-wired to 0 when S-mode is not supported. #[inline] pub fn tw(&self) -> bool { - self.bits & (1 << 21) != 0 + self.bf_extract(21, 1) != 0 } /// Update Timeout Wait @@ -360,7 +366,7 @@ impl Mstatus { /// If S-mode is not supported, TSR bit is hard-wired to 0. #[inline] pub fn tsr(&self) -> bool { - self.bits & (1 << 22) != 0 + self.bf_extract(22, 1) != 0 } /// Update Trap SRET @@ -382,7 +388,7 @@ impl Mstatus { #[cfg(riscv32)] () => XLEN::XLEN32, #[cfg(not(riscv32))] - () => XLEN::from((self.bits >> 32) as u8 & 0x3), + () => XLEN::from(self.bf_extract(32, 2) as u8), } } @@ -409,7 +415,7 @@ impl Mstatus { #[cfg(riscv32)] () => XLEN::XLEN32, #[cfg(not(riscv32))] - () => XLEN::from((self.bits >> 34) as u8 & 0x3), + () => XLEN::from(self.bf_extract(34, 2) as u8), } } @@ -435,7 +441,7 @@ impl Mstatus { #[cfg(riscv32)] () => super::mstatush::read().sbe(), #[cfg(not(riscv32))] - () => Endianness::from(self.bits & (1 << 36) != 0), + () => Endianness::from(self.bf_extract(36, 1) != 0), } } @@ -462,7 +468,7 @@ impl Mstatus { #[cfg(riscv32)] () => super::mstatush::read().mbe(), #[cfg(not(riscv32))] - () => Endianness::from(self.bits & (1 << 37) != 0), + () => Endianness::from(self.bf_extract(37, 1) != 0), } } /// Update M-mode non-instruction-fetch memory endianness @@ -483,7 +489,7 @@ impl Mstatus { /// Whether either the FS field or XS field signals the presence of some dirty state #[inline] pub fn sd(&self) -> bool { - self.bits & (1 << (usize::BITS as usize - 1)) != 0 + self.bf_extract(usize::BITS as usize - 1, 1) != 0 } /// Update whether either the FS field or XS field signals the presence of From a2a988817419b4617a5cb4dbefdf4f0fded0ac49 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 9 May 2024 09:41:01 -0700 Subject: [PATCH 8/8] Make set_* take &mut self Also remove local bf_* helpers --- riscv/src/register/mstatus.rs | 150 +++++++++++++++------------------- 1 file changed, 64 insertions(+), 86 deletions(-) diff --git a/riscv/src/register/mstatus.rs b/riscv/src/register/mstatus.rs index bc97d493..e01388a9 100644 --- a/riscv/src/register/mstatus.rs +++ b/riscv/src/register/mstatus.rs @@ -73,20 +73,6 @@ impl From for Endianness { } impl Mstatus { - /// Helper to insert a bitfield into Mstatus - #[inline] - fn bf_insert(&self, bit: usize, width: usize, val: usize) -> Self { - Self { - bits: bf_insert(self.bits, bit, width, val), - } - } - - /// Helper to extract a bitfield from Mstatus - #[inline] - fn bf_extract(&self, bit: usize, width: usize) -> usize { - bf_extract(self.bits, bit, width) - } - /// Returns the contents of the register as raw bits #[inline] pub fn bits(&self) -> usize { @@ -96,7 +82,7 @@ impl Mstatus { /// Supervisor Interrupt Enable #[inline] pub fn sie(&self) -> bool { - self.bf_extract(1, 1) != 0 + bf_extract(self.bits, 1, 1) != 0 } /// Update Supervisor Interrupt Enable @@ -105,14 +91,14 @@ impl Mstatus { /// affect the mstatus CSR itself. See [`set_sie`]/[`clear_sie`] to directly /// update the CSR. #[inline] - pub fn set_sie(&self, sie: bool) -> Self { - self.bf_insert(1, 1, sie as usize) + pub fn set_sie(&mut self, sie: bool) { + self.bits = bf_insert(self.bits, 1, 1, sie as usize); } /// Machine Interrupt Enable #[inline] pub fn mie(&self) -> bool { - self.bf_extract(3, 1) != 0 + bf_extract(self.bits, 3, 1) != 0 } /// Update Machine Interrupt Enable @@ -121,14 +107,14 @@ impl Mstatus { /// affect the mstatus CSR itself. See [`set_mie`]/[`clear_mie`] to directly /// update the CSR. #[inline] - pub fn set_mie(&self, mie: bool) -> Self { - self.bf_insert(3, 1, mie as usize) + pub fn set_mie(&mut self, mie: bool) { + self.bits = bf_insert(self.bits, 3, 1, mie as usize); } /// Supervisor Previous Interrupt Enable #[inline] pub fn spie(&self) -> bool { - self.bf_extract(5, 1) != 0 + bf_extract(self.bits, 5, 1) != 0 } /// Update Supervisor Previous Interrupt Enable @@ -137,14 +123,14 @@ impl Mstatus { /// affect the mstatus CSR itself. See [`set_spie`]` to directly update the /// CSR. #[inline] - pub fn set_spie(&self, spie: bool) -> Self { - self.bf_insert(5, 1, spie as usize) + pub fn set_spie(&mut self, spie: bool) { + self.bits = bf_insert(self.bits, 5, 1, spie as usize); } /// U-mode non-instruction-fetch memory endianness #[inline] pub fn ube(&self) -> Endianness { - Endianness::from(self.bf_extract(6, 1) != 0) + Endianness::from(bf_extract(self.bits, 6, 1) != 0) } /// Update U-mode non-instruction-fetch memory endianness @@ -153,14 +139,14 @@ impl Mstatus { /// affect the mstatus CSR itself. See [`set_ube`] to directly update the /// CSR. #[inline] - pub fn set_ube(&self, endianness: Endianness) -> Self { - self.bf_insert(6, 1, endianness as usize) + pub fn set_ube(&mut self, endianness: Endianness) { + self.bits = bf_insert(self.bits, 6, 1, endianness as usize); } /// Machine Previous Interrupt Enable #[inline] pub fn mpie(&self) -> bool { - self.bf_extract(7, 1) != 0 + bf_extract(self.bits, 7, 1) != 0 } /// Update Machine Previous Interrupt Enable @@ -169,14 +155,14 @@ impl Mstatus { /// affect the mstatus CSR itself. See [`set_mpie`] to directly update the /// CSR. #[inline] - pub fn set_mpie(&self, mpie: bool) -> Self { - self.bf_insert(7, 1, mpie as usize) + pub fn set_mpie(&mut self, mpie: bool) { + self.bits = bf_insert(self.bits, 7, 1, mpie as usize); } /// Supervisor Previous Privilege Mode #[inline] pub fn spp(&self) -> SPP { - match self.bf_extract(7, 1) != 0 { + match bf_extract(self.bits, 8, 1) != 0 { true => SPP::Supervisor, false => SPP::User, } @@ -188,14 +174,14 @@ impl Mstatus { /// affect the mstatus CSR itself. See [`set_spp`] to directly update the /// CSR. #[inline] - pub fn set_spp(&self, spp: SPP) -> Self { - self.bf_insert(8, 1, spp as usize) + pub fn set_spp(&mut self, spp: SPP) { + self.bits = bf_insert(self.bits, 8, 1, spp as usize); } /// Machine Previous Privilege Mode #[inline] pub fn mpp(&self) -> MPP { - let mpp = self.bf_extract(11, 2); // bits 11-12 + let mpp = bf_extract(self.bits, 11, 2); // bits 11-12 match mpp { 0b00 => MPP::User, 0b01 => MPP::Supervisor, @@ -210,8 +196,8 @@ impl Mstatus { /// affect the mstatus CSR itself. See [`set_mpp`] to directly update the /// CSR. #[inline] - pub fn set_mpp(&self, mpp: MPP) -> Self { - self.bf_insert(11, 2, mpp as usize) + pub fn set_mpp(&mut self, mpp: MPP) { + self.bits = bf_insert(self.bits, 11, 2, mpp as usize); } /// Floating-point extension state @@ -220,7 +206,7 @@ impl Mstatus { /// and floating-point data registers `f0–f31`. #[inline] pub fn fs(&self) -> FS { - let fs = self.bf_extract(13, 2); // bits 13-14 + let fs = bf_extract(self.bits, 13, 2); // bits 13-14 match fs { 0b00 => FS::Off, 0b01 => FS::Initial, @@ -236,8 +222,8 @@ impl Mstatus { /// affect the mstatus CSR itself. See [`set_fs`] to directly update the /// CSR. #[inline] - pub fn set_fs(&self, fs: FS) -> Self { - self.bf_insert(13, 2, fs as usize) + pub fn set_fs(&mut self, fs: FS) { + self.bits = bf_insert(self.bits, 13, 2, fs as usize); } /// Additional extension state @@ -246,7 +232,7 @@ impl Mstatus { /// state. #[inline] pub fn xs(&self) -> XS { - let xs = self.bf_extract(15, 2); // bits 15-16 + let xs = bf_extract(self.bits, 15, 2); // bits 15-16 match xs { 0b00 => XS::AllOff, 0b01 => XS::NoneDirtyOrClean, @@ -261,14 +247,14 @@ impl Mstatus { /// Note this updates a previously read [`Mstatus`] value, but does not /// affect the mstatus CSR itself. #[inline] - pub fn set_xs(&self, xs: XS) -> Self { - self.bf_insert(15, 2, xs as usize) + pub fn set_xs(&mut self, xs: XS) { + self.bits = bf_insert(self.bits, 15, 2, xs as usize); } /// Modify Memory PRiVilege #[inline] pub fn mprv(&self) -> bool { - self.bf_extract(17, 1) != 0 + bf_extract(self.bits, 17, 1) != 0 } /// Update Modify Memory PRiVilege @@ -277,14 +263,14 @@ impl Mstatus { /// affect the mstatus CSR itself. See [`set_mprv`]/[`clear_mprv`] to /// directly update the CSR. #[inline] - pub fn set_mprv(&self, mprv: bool) -> Self { - self.bf_insert(17, 1, mprv as usize) + pub fn set_mprv(&mut self, mprv: bool) { + self.bits = bf_insert(self.bits, 17, 1, mprv as usize); } /// Permit Supervisor User Memory access #[inline] pub fn sum(&self) -> bool { - self.bf_extract(18, 1) != 0 + bf_extract(self.bits, 18, 1) != 0 } /// Update Permit Supervisor User Memory access @@ -293,14 +279,14 @@ impl Mstatus { /// affect the mstatus CSR itself. See [`set_sum`]/[`clear_sum`] to directly /// update the CSR. #[inline] - pub fn set_sum(&self, sum: bool) -> Self { - self.bf_insert(18, 1, sum as usize) + pub fn set_sum(&mut self, sum: bool) { + self.bits = bf_insert(self.bits, 18, 1, sum as usize); } /// Make eXecutable Readable #[inline] pub fn mxr(&self) -> bool { - self.bf_extract(19, 1) != 0 + bf_extract(self.bits, 19, 1) != 0 } /// Update Make eXecutable Readable @@ -309,8 +295,8 @@ impl Mstatus { /// the mstatus CSR itself. See [`set_mxr`]/[`clear_mxr`] to directly update /// the CSR. #[inline] - pub fn set_mxr(&self, mxr: bool) -> Self { - self.bf_insert(19, 1, mxr as usize) + pub fn set_mxr(&mut self, mxr: bool) { + self.bits = bf_insert(self.bits, 19, 1, mxr as usize); } /// Trap Virtual Memory @@ -321,7 +307,7 @@ impl Mstatus { /// TVM is hard-wired to 0 when S-mode is not supported. #[inline] pub fn tvm(&self) -> bool { - self.bf_extract(20, 1) != 0 + bf_extract(self.bits, 20, 1) != 0 } /// Update Trap Virtual Memory @@ -330,8 +316,8 @@ impl Mstatus { /// affect the mstatus CSR itself. See [`set_tvm`]/[`clear_tvm`] to directly /// update the CSR. #[inline] - pub fn set_tvm(&self, tvm: bool) -> Self { - self.bf_insert(20, 1, tvm as usize) + pub fn set_tvm(&mut self, tvm: bool) { + self.bits = bf_insert(self.bits, 20, 1, tvm as usize); } /// Timeout Wait @@ -345,7 +331,7 @@ impl Mstatus { /// TW is hard-wired to 0 when S-mode is not supported. #[inline] pub fn tw(&self) -> bool { - self.bf_extract(21, 1) != 0 + bf_extract(self.bits, 21, 1) != 0 } /// Update Timeout Wait @@ -354,8 +340,8 @@ impl Mstatus { /// affect the mstatus CSR itself. See [`set_tw`]/[`clear_tw`] to directly /// update the CSR. #[inline] - pub fn set_tw(&self, tw: bool) -> Self { - self.bf_insert(21, 1, tw as usize) + pub fn set_tw(&mut self, tw: bool) { + self.bits = bf_insert(self.bits, 21, 1, tw as usize); } /// Trap SRET @@ -366,7 +352,7 @@ impl Mstatus { /// If S-mode is not supported, TSR bit is hard-wired to 0. #[inline] pub fn tsr(&self) -> bool { - self.bf_extract(22, 1) != 0 + bf_extract(self.bits, 22, 1) != 0 } /// Update Trap SRET @@ -375,8 +361,8 @@ impl Mstatus { /// affect the mstatus CSR itself. See [`set_tsr`]/[`clear_tsr`] to directly /// update the CSR. #[inline] - pub fn set_tsr(&self, tsr: bool) -> Self { - self.bf_insert(22, 1, tsr as usize) + pub fn set_tsr(&mut self, tsr: bool) { + self.bits = bf_insert(self.bits, 22, 1, tsr as usize); } /// Effective xlen in U-mode (i.e., `UXLEN`). @@ -388,7 +374,7 @@ impl Mstatus { #[cfg(riscv32)] () => XLEN::XLEN32, #[cfg(not(riscv32))] - () => XLEN::from(self.bf_extract(32, 2) as u8), + () => XLEN::from(bf_extract(self.bits, 32, 2) as u8), } } @@ -397,13 +383,11 @@ impl Mstatus { /// Note this updates a previously read [`Mstatus`] value, but does not /// affect the mstatus CSR itself. #[inline] - pub fn set_uxl(&self, uxl: XLEN) -> Self { - #[cfg(riscv32)] + pub fn set_uxl(&mut self, uxl: XLEN) { + #[cfg(not(riscv32))] { - *self + self.bits = bf_insert(self.bits, 32, 2, uxl as usize); } - #[cfg(not(riscv32))] - self.bf_insert(32, 2, uxl as usize) } /// Effective xlen in S-mode (i.e., `SXLEN`). @@ -415,7 +399,7 @@ impl Mstatus { #[cfg(riscv32)] () => XLEN::XLEN32, #[cfg(not(riscv32))] - () => XLEN::from(self.bf_extract(34, 2) as u8), + () => XLEN::from(bf_extract(self.bits, 34, 2) as u8), } } @@ -424,13 +408,11 @@ impl Mstatus { /// Note this updates a previously read [`Mstatus`] value, but does not /// affect the mstatus CSR itself. #[inline] - pub fn set_sxl(&self, sxl: XLEN) -> Self { - #[cfg(riscv32)] + pub fn set_sxl(&mut self, sxl: XLEN) { + #[cfg(not(riscv32))] { - *self + self.bits = bf_insert(self.bits, 34, 2, sxl as usize); } - #[cfg(not(riscv32))] - self.bf_insert(34, 2, sxl as usize) } /// S-mode non-instruction-fetch memory endianness. @@ -441,7 +423,7 @@ impl Mstatus { #[cfg(riscv32)] () => super::mstatush::read().sbe(), #[cfg(not(riscv32))] - () => Endianness::from(self.bf_extract(36, 1) != 0), + () => Endianness::from(bf_extract(self.bits, 36, 1) != 0), } } @@ -451,13 +433,11 @@ impl Mstatus { /// affect the mstatus CSR itself. See [`set_sbe`] to directly update the /// CSR. #[inline] - pub fn set_sbe(&self, endianness: Endianness) -> Self { - #[cfg(riscv32)] + pub fn set_sbe(&mut self, endianness: Endianness) { + #[cfg(not(riscv32))] { - *self + self.bits = bf_insert(self.bits, 36, 1, endianness as usize); } - #[cfg(not(riscv32))] - self.bf_insert(36, 1, endianness as usize) } /// M-mode non-instruction-fetch memory endianness @@ -468,7 +448,7 @@ impl Mstatus { #[cfg(riscv32)] () => super::mstatush::read().mbe(), #[cfg(not(riscv32))] - () => Endianness::from(self.bf_extract(37, 1) != 0), + () => Endianness::from(bf_extract(self.bits, 37, 1) != 0), } } /// Update M-mode non-instruction-fetch memory endianness @@ -477,19 +457,17 @@ impl Mstatus { /// affect the mstatus CSR itself. See [`set_mbe`] to directly update the /// CSR. #[inline] - pub fn set_mbe(&self, endianness: Endianness) -> Self { - #[cfg(riscv32)] + pub fn set_mbe(&mut self, endianness: Endianness) { + #[cfg(not(riscv32))] { - *self + self.bits = bf_insert(self.bits, 37, 1, endianness as usize); } - #[cfg(not(riscv32))] - self.bf_insert(37, 1, endianness as usize) } /// Whether either the FS field or XS field signals the presence of some dirty state #[inline] pub fn sd(&self) -> bool { - self.bf_extract(usize::BITS as usize - 1, 1) != 0 + bf_extract(self.bits, usize::BITS as usize - 1, 1) != 0 } /// Update whether either the FS field or XS field signals the presence of @@ -498,8 +476,8 @@ impl Mstatus { /// Note this updates a previously read [`Mstatus`] value, but does not /// affect the mstatus CSR itself. #[inline] - pub fn set_sd(&self, sd: bool) -> Self { - self.bf_insert(usize::BITS as usize - 1, 1, sd as usize) + pub fn set_sd(&mut self, sd: bool) { + self.bits = bf_insert(self.bits, usize::BITS as usize - 1, 1, sd as usize); } }