aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/register/fpscr.rs343
-rw-r--r--src/register/mod.rs7
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;