aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--asm-fpu.s21
-rwxr-xr-xassemble.sh10
-rw-r--r--bin/thumbv6m-none-eabi.abin5806 -> 5806 bytes
-rw-r--r--bin/thumbv7em-none-eabi.abin10570 -> 10554 bytes
-rw-r--r--bin/thumbv7em-none-eabihf.abin10570 -> 12620 bytes
-rw-r--r--bin/thumbv7m-none-eabi.abin8328 -> 8320 bytes
-rw-r--r--bin/thumbv8m.base-none-eabi.abin8254 -> 8246 bytes
-rw-r--r--bin/thumbv8m.main-none-eabi.abin13372 -> 13356 bytes
-rw-r--r--bin/thumbv8m.main-none-eabihf.abin13372 -> 15424 bytes
-rw-r--r--src/register/fpscr.rs343
-rw-r--r--src/register/mod.rs7
11 files changed, 378 insertions, 3 deletions
diff --git a/asm-fpu.s b/asm-fpu.s
new file mode 100644
index 0000000..417d199
--- /dev/null
+++ b/asm-fpu.s
@@ -0,0 +1,21 @@
+ .cfi_sections .debug_frame
+
+ .section .text.__get_FPSCR
+ .global __get_FPSCR
+ .thumb_func
+ .cfi_startproc
+__get_FPSCR:
+ vmrs r0, fpscr
+ bx lr
+ .cfi_endproc
+ .size __get_FPSCR, . - __get_FPSCR
+
+ .section .text.__set_FPSCR
+ .global __set_FPSCR
+ .thumb_func
+ .cfi_startproc
+__set_FPSCR:
+ vmsr fpscr, r0
+ bx lr
+ .cfi_endproc
+ .size __set_FPSCR, . - __set_FPSCR
diff --git a/assemble.sh b/assemble.sh
index 3e9e59e..775eccb 100755
--- a/assemble.sh
+++ b/assemble.sh
@@ -17,10 +17,11 @@ arm-none-eabi-as -g -march=armv7-m asm-v7.s -o bin/$crate-v7.o
ar crs bin/thumbv7m-none-eabi.a bin/$crate.o bin/$crate-v7.o
arm-none-eabi-as -g -march=armv7e-m asm.s -o bin/$crate.o
-arm-none-eabi-as -g -march=armv7e-m asm-v7.s -o bin/$crate-v7.o
+arm-none-eabi-as -g -march=armv7e-m asm-fpu.s -mfpu=fpv4-sp-d16 -o bin/$crate-v7-fpu.o
arm-none-eabi-as -g -march=armv7e-m asm-cm7-r0p1.s -o bin/$crate-cm7-r0p1.o
+arm-none-eabi-as -g -march=armv7e-m asm-v7.s -o bin/$crate-v7.o
ar crs bin/thumbv7em-none-eabi.a bin/$crate.o bin/$crate-v7.o bin/$crate-cm7-r0p1.o
-ar crs bin/thumbv7em-none-eabihf.a bin/$crate.o bin/$crate-v7.o bin/$crate-cm7-r0p1.o
+ar crs bin/thumbv7em-none-eabihf.a bin/$crate.o bin/$crate-v7.o bin/$crate-cm7-r0p1.o bin/$crate-v7-fpu.o
arm-none-eabi-as -g -march=armv8-m.base asm.s -o bin/$crate.o
arm-none-eabi-as -g -march=armv8-m.base asm-v8.s -o bin/$crate-v8.o
@@ -30,11 +31,14 @@ arm-none-eabi-as -g -march=armv8-m.main asm.s -o bin/$crate.o
arm-none-eabi-as -g -march=armv8-m.main asm-v7.s -o bin/$crate-v7.o
arm-none-eabi-as -g -march=armv8-m.main asm-v8.s -o bin/$crate-v8.o
arm-none-eabi-as -g -march=armv8-m.main asm-v8-main.s -o bin/$crate-v8-main.o
+arm-none-eabi-as -g -march=armv8-m.main asm-fpu.s -mfpu=fpv5-sp-d16 -o bin/$crate-v8-fpu.o
ar crs bin/thumbv8m.main-none-eabi.a bin/$crate.o bin/$crate-v7.o bin/$crate-v8.o bin/$crate-v8-main.o
-ar crs bin/thumbv8m.main-none-eabihf.a bin/$crate.o bin/$crate-v7.o bin/$crate-v8.o bin/$crate-v8-main.o
+ar crs bin/thumbv8m.main-none-eabihf.a bin/$crate.o bin/$crate-v7.o bin/$crate-v8.o bin/$crate-v8-main.o bin/$crate-v8-fpu.o
rm bin/$crate.o
rm bin/$crate-v7.o
+rm bin/$crate-v7-fpu.o
+rm bin/$crate-v8-fpu.o
rm bin/$crate-cm7-r0p1.o
rm bin/$crate-v8.o
rm bin/$crate-v8-main.o
diff --git a/bin/thumbv6m-none-eabi.a b/bin/thumbv6m-none-eabi.a
index 0014368..43ecf80 100644
--- a/bin/thumbv6m-none-eabi.a
+++ b/bin/thumbv6m-none-eabi.a
Binary files differ
diff --git a/bin/thumbv7em-none-eabi.a b/bin/thumbv7em-none-eabi.a
index f7dc35c..a250694 100644
--- a/bin/thumbv7em-none-eabi.a
+++ b/bin/thumbv7em-none-eabi.a
Binary files differ
diff --git a/bin/thumbv7em-none-eabihf.a b/bin/thumbv7em-none-eabihf.a
index f7dc35c..efff863 100644
--- a/bin/thumbv7em-none-eabihf.a
+++ b/bin/thumbv7em-none-eabihf.a
Binary files differ
diff --git a/bin/thumbv7m-none-eabi.a b/bin/thumbv7m-none-eabi.a
index f1f686d..e1a886b 100644
--- a/bin/thumbv7m-none-eabi.a
+++ b/bin/thumbv7m-none-eabi.a
Binary files differ
diff --git a/bin/thumbv8m.base-none-eabi.a b/bin/thumbv8m.base-none-eabi.a
index 7711268..c4db7d5 100644
--- a/bin/thumbv8m.base-none-eabi.a
+++ b/bin/thumbv8m.base-none-eabi.a
Binary files differ
diff --git a/bin/thumbv8m.main-none-eabi.a b/bin/thumbv8m.main-none-eabi.a
index ff78de2..719d1df 100644
--- a/bin/thumbv8m.main-none-eabi.a
+++ b/bin/thumbv8m.main-none-eabi.a
Binary files differ
diff --git a/bin/thumbv8m.main-none-eabihf.a b/bin/thumbv8m.main-none-eabihf.a
index ff78de2..0b665bc 100644
--- a/bin/thumbv8m.main-none-eabihf.a
+++ b/bin/thumbv8m.main-none-eabihf.a
Binary files differ
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;