diff options
-rw-r--r-- | asm-fpu.s | 21 | ||||
-rwxr-xr-x | assemble.sh | 10 | ||||
-rw-r--r-- | bin/thumbv6m-none-eabi.a | bin | 5806 -> 5806 bytes | |||
-rw-r--r-- | bin/thumbv7em-none-eabi.a | bin | 10570 -> 10554 bytes | |||
-rw-r--r-- | bin/thumbv7em-none-eabihf.a | bin | 10570 -> 12620 bytes | |||
-rw-r--r-- | bin/thumbv7m-none-eabi.a | bin | 8328 -> 8320 bytes | |||
-rw-r--r-- | bin/thumbv8m.base-none-eabi.a | bin | 8254 -> 8246 bytes | |||
-rw-r--r-- | bin/thumbv8m.main-none-eabi.a | bin | 13372 -> 13356 bytes | |||
-rw-r--r-- | bin/thumbv8m.main-none-eabihf.a | bin | 13372 -> 15424 bytes | |||
-rw-r--r-- | src/register/fpscr.rs | 343 | ||||
-rw-r--r-- | src/register/mod.rs | 7 |
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 Binary files differindex 0014368..43ecf80 100644 --- a/bin/thumbv6m-none-eabi.a +++ b/bin/thumbv6m-none-eabi.a diff --git a/bin/thumbv7em-none-eabi.a b/bin/thumbv7em-none-eabi.a Binary files differindex f7dc35c..a250694 100644 --- a/bin/thumbv7em-none-eabi.a +++ b/bin/thumbv7em-none-eabi.a diff --git a/bin/thumbv7em-none-eabihf.a b/bin/thumbv7em-none-eabihf.a Binary files differindex f7dc35c..efff863 100644 --- a/bin/thumbv7em-none-eabihf.a +++ b/bin/thumbv7em-none-eabihf.a diff --git a/bin/thumbv7m-none-eabi.a b/bin/thumbv7m-none-eabi.a Binary files differindex f1f686d..e1a886b 100644 --- a/bin/thumbv7m-none-eabi.a +++ b/bin/thumbv7m-none-eabi.a diff --git a/bin/thumbv8m.base-none-eabi.a b/bin/thumbv8m.base-none-eabi.a Binary files differindex 7711268..c4db7d5 100644 --- a/bin/thumbv8m.base-none-eabi.a +++ b/bin/thumbv8m.base-none-eabi.a diff --git a/bin/thumbv8m.main-none-eabi.a b/bin/thumbv8m.main-none-eabi.a Binary files differindex ff78de2..719d1df 100644 --- a/bin/thumbv8m.main-none-eabi.a +++ b/bin/thumbv8m.main-none-eabi.a diff --git a/bin/thumbv8m.main-none-eabihf.a b/bin/thumbv8m.main-none-eabihf.a Binary files differindex ff78de2..0b665bc 100644 --- a/bin/thumbv8m.main-none-eabihf.a +++ b/bin/thumbv8m.main-none-eabihf.a 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; |