diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/register/fpscr.rs | 343 | ||||
-rw-r--r-- | src/register/mod.rs | 7 |
2 files changed, 350 insertions, 0 deletions
diff --git a/src/register/fpscr.rs b/src/register/fpscr.rs new file mode 100644 index 0000000..569d3a7 --- /dev/null +++ b/src/register/fpscr.rs @@ -0,0 +1,343 @@ +//! Floating-point Status Control Register + +/// Floating-point Status Control Register +#[allow(clippy::missing_inline_in_public_items)] +#[derive(Clone, Copy, Debug)] +pub struct Fpscr { + bits: u32, +} + +impl Fpscr { + /// Creates a `Fspcr` value from raw bits. + #[inline] + pub fn from_bits(bits: u32) -> Self { + Self { bits } + } + + /// Returns the contents of the register as raw bits + #[inline] + pub fn bits(self) -> u32 { + self.bits + } + + /// Read the Negative condition code flag + #[inline] + pub fn n(self) -> bool { + self.bits & (1 << 31) != 0 + } + + /// Sets the Negative condition code flag + #[inline] + pub fn set_n(&mut self, n: bool) { + let mask = 1 << 31; + match n { + true => self.bits |= mask, + false => self.bits &= !mask, + } + } + + /// Read the Zero condition code flag + #[inline] + pub fn z(self) -> bool { + self.bits & (1 << 30) != 0 + } + + /// Sets the Zero condition code flag + #[inline] + pub fn set_z(&mut self, z: bool) { + let mask = 1 << 30; + match z { + true => self.bits |= mask, + false => self.bits &= !mask, + } + } + + /// Read the Carry condition code flag + #[inline] + pub fn c(self) -> bool { + self.bits & (1 << 29) != 0 + } + + /// Sets the Carry condition code flag + #[inline] + pub fn set_c(&mut self, c: bool) { + let mask = 1 << 29; + match c { + true => self.bits |= mask, + false => self.bits &= !mask, + } + } + + /// Read the Overflow condition code flag + #[inline] + pub fn v(self) -> bool { + self.bits & (1 << 28) != 0 + } + + /// Sets the Zero condition code flag + #[inline] + pub fn set_v(&mut self, v: bool) { + let mask = 1 << 28; + match v { + true => self.bits |= mask, + false => self.bits &= !mask, + } + } + + /// Read the Alternative Half Precision bit + #[inline] + pub fn ahp(self) -> bool { + self.bits & (1 << 26) != 0 + } + + /// Sets the Alternative Half Precision bit + #[inline] + pub fn set_ahp(&mut self, ahp: bool) { + let mask = 1 << 26; + match ahp { + true => self.bits |= mask, + false => self.bits &= !mask, + } + } + + /// Read the Default NaN mode bit + #[inline] + pub fn dn(self) -> bool { + self.bits & (1 << 25) != 0 + } + + /// Sets the Default NaN mode bit + #[inline] + pub fn set_dn(&mut self, dn: bool) { + let mask = 1 << 25; + match dn { + true => self.bits |= mask, + false => self.bits &= !mask, + } + } + + /// Read the Flush to Zero mode bit + #[inline] + pub fn fz(self) -> bool { + self.bits & (1 << 24) != 0 + } + + /// Sets the Flush to Zero mode bit + #[inline] + pub fn set_fz(&mut self, fz: bool) { + let mask = 1 << 24; + match fz { + true => self.bits |= mask, + false => self.bits &= !mask, + } + } + + /// Read the Rounding Mode control field + #[inline] + pub fn rmode(self) -> RMode { + match (self.bits & (3 << 22)) >> 22 { + 0 => RMode::Nearest, + 1 => RMode::PlusInfinity, + 2 => RMode::MinusInfinity, + _ => RMode::Zero, + } + } + + /// Sets the Rounding Mode control field + #[inline] + pub fn set_rmode(&mut self, rmode: RMode) { + let mask = 3 << 22; + match rmode { + RMode::Nearest => self.bits = self.bits & !mask, + RMode::PlusInfinity => self.bits = (self.bits & !mask) | (1 << 22), + RMode::MinusInfinity => self.bits = (self.bits & !mask) | (2 << 22), + RMode::Zero => self.bits = self.bits | mask, + } + } + + /// Read the Input Denormal cumulative exception bit + #[inline] + pub fn idc(self) -> bool { + self.bits & (1 << 7) != 0 + } + + /// Sets the Input Denormal cumulative exception bit + #[inline] + pub fn set_idc(&mut self, idc: bool) { + let mask = 1 << 7; + match idc { + true => self.bits |= mask, + false => self.bits &= !mask, + } + } + + /// Read the Inexact cumulative exception bit + #[inline] + pub fn ixc(self) -> bool { + self.bits & (1 << 4) != 0 + } + + /// Sets the Inexact cumulative exception bit + #[inline] + pub fn set_ixc(&mut self, ixc: bool) { + let mask = 1 << 4; + match ixc { + true => self.bits |= mask, + false => self.bits &= !mask, + } + } + + /// Read the Underflow cumulative exception bit + #[inline] + pub fn ufc(self) -> bool { + self.bits & (1 << 3) != 0 + } + + /// Sets the Underflow cumulative exception bit + #[inline] + pub fn set_ufc(&mut self, ufc: bool) { + let mask = 1 << 3; + match ufc { + true => self.bits |= mask, + false => self.bits &= !mask, + } + } + + /// Read the Overflow cumulative exception bit + #[inline] + pub fn ofc(self) -> bool { + self.bits & (1 << 2) != 0 + } + + /// Sets the Overflow cumulative exception bit + #[inline] + pub fn set_ofc(&mut self, ofc: bool) { + let mask = 1 << 2; + match ofc { + true => self.bits |= mask, + false => self.bits &= !mask, + } + } + + /// Read the Division by Zero cumulative exception bit + #[inline] + pub fn dzc(self) -> bool { + self.bits & (1 << 1) != 0 + } + + /// Sets the Division by Zero cumulative exception bit + #[inline] + pub fn set_dzc(&mut self, dzc: bool) { + let mask = 1 << 1; + match dzc { + true => self.bits |= mask, + false => self.bits &= !mask, + } + } + + /// Read the Invalid Operation cumulative exception bit + #[inline] + pub fn ioc(self) -> bool { + self.bits & (1 << 0) != 0 + } + + /// Sets the Invalid Operation cumulative exception bit + #[inline] + pub fn set_ioc(&mut self, ioc: bool) { + let mask = 1 << 0; + match ioc { + true => self.bits |= mask, + false => self.bits &= !mask, + } + } +} + +/// Rounding mode +#[allow(clippy::missing_inline_in_public_items)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum RMode { + /// Round to Nearest (RN) mode. This is the reset value. + Nearest, + /// Round towards Plus Infinity (RP) mode. + PlusInfinity, + /// Round towards Minus Infinity (RM) mode. + MinusInfinity, + /// Round towards Zero (RZ) mode. + Zero, +} + +impl RMode { + /// Is Nearest the current rounding mode? + #[inline] + pub fn is_nearest(self) -> bool { + self == RMode::Nearest + } + + /// Is Plus Infinity the current rounding mode? + #[inline] + pub fn is_plus_infinity(self) -> bool { + self == RMode::PlusInfinity + } + + /// Is Minus Infinity the current rounding mode? + #[inline] + pub fn is_minus_infinity(self) -> bool { + self == RMode::MinusInfinity + } + + /// Is Zero the current rounding mode? + #[inline] + pub fn is_zero(self) -> bool { + self == RMode::Zero + } +} + +/// Read the FPSCR register +#[inline] +pub fn read() -> Fpscr { + match () { + #[cfg(all(cortex_m, feature = "inline-asm"))] + () => { + let r: u32; + unsafe { + llvm_asm!("vmrs $0, fpscr" : "=r"(r) ::: "volatile"); + } + Fpscr::from_bits(r) + } + + #[cfg(all(cortex_m, not(feature = "inline-asm")))] + () => unsafe { + extern "C" { + fn __get_FPSCR() -> u32; + } + Fpscr::from_bits(__get_FPSCR()) + }, + + #[cfg(not(cortex_m))] + () => unimplemented!(), + } +} + +/// Set the value of the FPSCR register +#[inline] +pub unsafe fn write(_fspcr: Fpscr) { + match () { + #[cfg(all(cortex_m, feature = "inline-asm"))] + () => { + let bits = _fspcr.bits(); + llvm_asm!("vmsr fpscr, $0" :: "r"(bits) :: "volatile"); + } + + #[cfg(all(cortex_m, not(feature = "inline-asm")))] + () => { + extern "C" { + fn __set_FPSCR(bits: u32); + } + + __set_FPSCR(_fspcr.bits()); + } + + #[cfg(not(cortex_m))] + () => unimplemented!(), + } +} diff --git a/src/register/mod.rs b/src/register/mod.rs index d69c1a5..efbe6ef 100644 --- a/src/register/mod.rs +++ b/src/register/mod.rs @@ -22,6 +22,10 @@ //! - BASEPRI //! - FAULTMASK //! +//! The following registers are only available for devices with an FPU: +//! +//! - FPSCR +//! //! # References //! //! - Cortex-M* Devices Generic User Guide - Section 2.1.3 Core registers @@ -37,6 +41,9 @@ pub mod control; #[cfg(all(not(armv6m), not(armv8m_base)))] pub mod faultmask; +#[cfg(has_fpu)] +pub mod fpscr; + pub mod msp; pub mod primask; |