diff --git a/riscv/CHANGELOG.md b/riscv/CHANGELOG.md index 2a56518a..f40a3202 100644 --- a/riscv/CHANGELOG.md +++ b/riscv/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Export `riscv::register::macros` module macros for external use - Add `riscv::register::mcountinhibit` module for `mcountinhibit` CSR - Add `Mcounteren` in-memory update functions +- Add `Mstatus` vector extension support ### Fixed diff --git a/riscv/src/register/mstatus.rs b/riscv/src/register/mstatus.rs index 5aadc33a..32986d34 100644 --- a/riscv/src/register/mstatus.rs +++ b/riscv/src/register/mstatus.rs @@ -41,6 +41,15 @@ pub enum FS { Dirty = 3, } +/// Vector extension state +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum VS { + Off = 0, + Initial = 1, + Clean = 2, + Dirty = 3, +} + /// Machine Previous Privilege Mode #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum MPP { @@ -216,6 +225,19 @@ impl Mstatus { } } + /// Vector extension state + #[inline] + pub fn vs(&self) -> VS { + let fs = bf_extract(self.bits, 9, 2); // bits 9-10 + match fs { + 0b00 => VS::Off, + 0b01 => VS::Initial, + 0b10 => VS::Clean, + 0b11 => VS::Dirty, + _ => unreachable!(), + } + } + /// Update Floating-point extension state /// /// Note this updates a previously read [`Mstatus`] value, but does not @@ -226,6 +248,16 @@ impl Mstatus { self.bits = bf_insert(self.bits, 13, 2, fs as usize); } + /// Update vector extension state + /// + /// Note this updates a previously read [`Mstatus`] value, but does not + /// affect the mstatus CSR itself. See [`set_vs`] to directly update the + /// CSR. + #[inline] + pub fn set_vs(&mut self, vs: VS) { + self.bits = bf_insert(self.bits, 9, 2, vs as usize); + } + /// Additional extension state /// /// Encodes the status of additional user-mode extensions and associated @@ -559,6 +591,15 @@ pub unsafe fn set_fs(fs: FS) { _write(value); } +/// Vector extension state +#[inline] +pub unsafe fn set_vs(vs: VS) { + let mut value = _read(); + value &= !(0x3 << 9); // clear previous value + value |= (vs as usize) << 9; + _write(value); +} + /// Set S-mode non-instruction-fetch memory endianness /// /// # Note