diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/asm.rs | 295 | ||||
-rw-r--r-- | src/call_asm.rs | 24 | ||||
-rw-r--r-- | src/interrupt.rs | 38 | ||||
-rw-r--r-- | src/lib.rs | 9 | ||||
-rw-r--r-- | src/register/apsr.rs | 15 | ||||
-rw-r--r-- | src/register/basepri.rs | 64 | ||||
-rw-r--r-- | src/register/basepri_max.rs | 45 | ||||
-rw-r--r-- | src/register/control.rs | 55 | ||||
-rw-r--r-- | src/register/faultmask.rs | 36 | ||||
-rw-r--r-- | src/register/fpscr.rs | 46 | ||||
-rw-r--r-- | src/register/lr.rs | 22 | ||||
-rw-r--r-- | src/register/mod.rs | 6 | ||||
-rw-r--r-- | src/register/msp.rs | 40 | ||||
-rw-r--r-- | src/register/msplim.rs | 40 | ||||
-rw-r--r-- | src/register/pc.rs | 22 | ||||
-rw-r--r-- | src/register/primask.rs | 37 | ||||
-rw-r--r-- | src/register/psp.rs | 40 | ||||
-rw-r--r-- | src/register/psplim.rs | 40 |
18 files changed, 121 insertions, 753 deletions
@@ -1,27 +1,18 @@ //! Miscellaneous assembly instructions +// When inline assembly is enabled, pull in the assembly routines here. `call_asm!` will invoke +// these routines. +#[cfg(feature = "inline-asm")] +#[path = "../asm/inline.rs"] +pub(crate) mod inline; + /// Puts the processor in Debug state. Debuggers can pick this up as a "breakpoint". /// /// **NOTE** calling `bkpt` when the processor is not connected to a debugger will cause an /// exception. #[inline(always)] pub fn bkpt() { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => unsafe { llvm_asm!("bkpt" :::: "volatile") }, - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - extern "C" { - fn __bkpt(); - } - - __bkpt(); - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + call_asm!(__bkpt()); } /// Blocks the program for *at least* `n` instruction cycles @@ -29,151 +20,47 @@ pub fn bkpt() { /// This is implemented in assembly so its execution time is independent of the optimization /// level, however it is dependent on the specific architecture and core configuration. /// -/// NOTE that the delay can take much longer if interrupts are serviced during its execution +/// NOTE that the delay can take much longer if interrupts are serviced during its execution /// and the execution time may vary with other factors. This delay is mainly useful for simple /// timer-less initialization of peripherals if and only if accurate timing is not essential. In /// any other case please use a more accurate method to produce a delay. #[inline] -pub fn delay(_n: u32) { +pub fn delay(n: u32) { // NOTE(divide by 4) is easier to compute than `/ 3` because it's just a shift (`>> 2`). - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => unsafe { - llvm_asm!("1: - nop - subs $0, $$1 - bne.n 1b" - : "+r"(_n / 4 + 1) - : - : "cpsr" - : "volatile"); - }, - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - extern "C" { - fn __delay(n: u32); - } - - __delay(_n / 4 + 1); - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + let real_cyc = n / 4 + 1; + call_asm!(__delay(real_cyc: u32)); } /// A no-operation. Useful to prevent delay loops from being optimized away. #[inline] pub fn nop() { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => unsafe { llvm_asm!("nop" :::: "volatile") }, - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - extern "C" { - fn __nop(); - } - - __nop() - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + call_asm!(__nop()); } - /// Generate an Undefined Instruction exception. /// /// Can be used as a stable alternative to `core::intrinsics::abort`. #[inline] pub fn udf() -> ! { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => unsafe { - llvm_asm!("udf" :::: "volatile"); - core::hint::unreachable_unchecked(); - }, - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - extern "C" { - fn __udf(); - } - - __udf(); - - core::hint::unreachable_unchecked(); - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + call_asm!(__udf() -> !) } /// Wait For Event #[inline] pub fn wfe() { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => unsafe { llvm_asm!("wfe" :::: "volatile") }, - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - extern "C" { - fn __wfe(); - } - - __wfe() - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + call_asm!(__wfe()) } /// Wait For Interrupt #[inline] pub fn wfi() { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => unsafe { llvm_asm!("wfi" :::: "volatile") }, - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - extern "C" { - fn __wfi(); - } - - __wfi() - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + call_asm!(__wfi()) } /// Send Event #[inline] pub fn sev() { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => unsafe { llvm_asm!("sev" :::: "volatile") }, - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - extern "C" { - fn __sev(); - } - - __sev() - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + call_asm!(__sev()) } /// Instruction Synchronization Barrier @@ -182,23 +69,7 @@ pub fn sev() { /// from cache or memory, after the instruction has been completed. #[inline] pub fn isb() { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => unsafe { llvm_asm!("isb 0xF" ::: "memory" : "volatile") }, - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - extern "C" { - fn __isb(); - } - - __isb() - // XXX do we need a explicit compiler barrier here? - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + call_asm!(__isb()) } /// Data Synchronization Barrier @@ -210,23 +81,7 @@ pub fn isb() { /// * all cache and branch predictor maintenance operations before this instruction complete #[inline] pub fn dsb() { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => unsafe { llvm_asm!("dsb 0xF" ::: "memory" : "volatile") }, - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - extern "C" { - fn __dsb(); - } - - __dsb() - // XXX do we need a explicit compiler barrier here? - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + call_asm!(__dsb()) } /// Data Memory Barrier @@ -236,23 +91,7 @@ pub fn dsb() { /// after the `DMB` instruction. #[inline] pub fn dmb() { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => unsafe { llvm_asm!("dmb 0xF" ::: "memory" : "volatile") }, - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - extern "C" { - fn __dmb(); - } - - __dmb() - // XXX do we need a explicit compiler barrier here? - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + call_asm!(__dmb()) } /// Test Target @@ -265,28 +104,8 @@ pub fn dmb() { // The __tt function does not dereference the pointer received. #[allow(clippy::not_unsafe_ptr_arg_deref)] pub fn tt(addr: *mut u32) -> u32 { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => { - let tt_resp: u32; - unsafe { - llvm_asm!("tt $0, $1" : "=r"(tt_resp) : "r"(addr) :: "volatile"); - } - tt_resp - } - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - extern "C" { - fn __tt(_: *mut u32) -> u32; - } - - __tt(addr) - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + let addr = addr as u32; + call_asm!(__tt(addr: u32) -> u32) } /// Test Target Unprivileged @@ -300,28 +119,8 @@ pub fn tt(addr: *mut u32) -> u32 { // The __ttt function does not dereference the pointer received. #[allow(clippy::not_unsafe_ptr_arg_deref)] pub fn ttt(addr: *mut u32) -> u32 { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => { - let tt_resp: u32; - unsafe { - llvm_asm!("ttt $0, $1" : "=r"(tt_resp) : "r"(addr) :: "volatile"); - } - tt_resp - } - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - extern "C" { - fn __ttt(_: *mut u32) -> u32; - } - - __ttt(addr) - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + let addr = addr as u32; + call_asm!(__ttt(addr: u32) -> u32) } /// Test Target Alternate Domain @@ -336,28 +135,8 @@ pub fn ttt(addr: *mut u32) -> u32 { // The __tta function does not dereference the pointer received. #[allow(clippy::not_unsafe_ptr_arg_deref)] pub fn tta(addr: *mut u32) -> u32 { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => { - let tt_resp: u32; - unsafe { - llvm_asm!("tta $0, $1" : "=r"(tt_resp) : "r"(addr) :: "volatile"); - } - tt_resp - } - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - extern "C" { - fn __tta(_: *mut u32) -> u32; - } - - __tta(addr) - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + let addr = addr as u32; + call_asm!(__tta(addr: u32) -> u32) } /// Test Target Alternate Domain Unprivileged @@ -372,26 +151,6 @@ pub fn tta(addr: *mut u32) -> u32 { // The __ttat function does not dereference the pointer received. #[allow(clippy::not_unsafe_ptr_arg_deref)] pub fn ttat(addr: *mut u32) -> u32 { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => { - let tt_resp: u32; - unsafe { - llvm_asm!("ttat $0, $1" : "=r"(tt_resp) : "r"(addr) :: "volatile"); - } - tt_resp - } - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - extern "C" { - fn __ttat(_: *mut u32) -> u32; - } - - __ttat(addr) - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + let addr = addr as u32; + call_asm!(__ttat(addr: u32) -> u32) } diff --git a/src/call_asm.rs b/src/call_asm.rs new file mode 100644 index 0000000..295277f --- /dev/null +++ b/src/call_asm.rs @@ -0,0 +1,24 @@ +/// An internal macro to invoke an assembly routine. +/// +/// Depending on whether the unstable `inline-asm` feature is enabled, this will either call into +/// the inline assembly implementation directly, or through the FFI shim (see `asm/lib.rs`). +macro_rules! call_asm { + ( $func:ident ( $($args:ident: $tys:ty),* ) $(-> $ret:ty)? ) => {{ + #[allow(unused_unsafe)] + unsafe { + match () { + #[cfg(feature = "inline-asm")] + () => crate::asm::inline::$func($($args),*), + + #[cfg(not(feature = "inline-asm"))] + () => { + extern "C" { + fn $func($($args: $tys),*) $(-> $ret)?; + } + + $func($($args),*) + }, + } + } + }}; +} diff --git a/src/interrupt.rs b/src/interrupt.rs index c5da48d..68719ec 100644 --- a/src/interrupt.rs +++ b/src/interrupt.rs @@ -26,25 +26,7 @@ pub unsafe trait InterruptNumber: Copy { /// Disables all interrupts #[inline] pub fn disable() { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => unsafe { - llvm_asm!("cpsid i" ::: "memory" : "volatile"); - }, - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - extern "C" { - fn __cpsid(); - } - - // XXX do we need a explicit compiler barrier here? - __cpsid(); - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + call_asm!(__cpsid()); } /// Enables all the interrupts @@ -54,23 +36,7 @@ pub fn disable() { /// - Do not call this function inside an `interrupt::free` critical section #[inline] pub unsafe fn enable() { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => llvm_asm!("cpsie i" ::: "memory" : "volatile"), - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => { - extern "C" { - fn __cpsie(); - } - - // XXX do we need a explicit compiler barrier here? - __cpsie(); - } - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + call_asm!(__cpsie()); } /// Execute closure `f` in an interrupt-free context. @@ -12,7 +12,7 @@ //! ## `inline-asm` //! //! When this feature is enabled the implementation of all the functions inside the `asm` and -//! `register` modules use inline assembly (`llvm_asm!`) instead of external assembly (FFI into separate +//! `register` modules use inline assembly (`asm!`) instead of external assembly (FFI into separate //! assembly files pre-compiled using `arm-none-eabi-gcc`). The advantages of enabling `inline-asm` //! are: //! @@ -52,17 +52,16 @@ //! //! # Minimum Supported Rust Version (MSRV) //! -//! This crate is guaranteed to compile on stable Rust 1.31 and up. It *might* +//! This crate is guaranteed to compile on stable Rust 1.38 and up. It *might* //! compile with older versions but that may change in any new patch release. -#![cfg_attr(feature = "inline-asm", feature(llvm_asm))] +#![cfg_attr(feature = "inline-asm", feature(asm))] #![deny(missing_docs)] #![no_std] #![allow(clippy::identity_op)] #![allow(clippy::missing_safety_doc)] // Prevent clippy from complaining about empty match expression that are used for cfg gating. #![allow(clippy::match_single_binding)] - // This makes clippy warn about public functions which are not #[inline]. // // Almost all functions in this crate result in trivial or even no assembly. @@ -82,6 +81,8 @@ extern crate bare_metal; extern crate volatile_register; #[macro_use] +mod call_asm; +#[macro_use] mod macros; pub mod asm; diff --git a/src/register/apsr.rs b/src/register/apsr.rs index 3db8aeb..b81d892 100644 --- a/src/register/apsr.rs +++ b/src/register/apsr.rs @@ -50,17 +50,6 @@ impl Apsr { /// **NOTE** This function is available if `cortex-m` is built with the `"inline-asm"` feature. #[inline] pub fn read() -> Apsr { - match () { - #[cfg(cortex_m)] - () => { - let r: u32; - unsafe { - llvm_asm!("mrs $0, APSR" : "=r"(r) ::: "volatile"); - } - Apsr { bits: r } - } - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + let bits: u32 = call_asm!(__apsr_r() -> u32); + Apsr { bits } } diff --git a/src/register/basepri.rs b/src/register/basepri.rs index 6caf938..07084cd 100644 --- a/src/register/basepri.rs +++ b/src/register/basepri.rs @@ -3,28 +3,7 @@ /// Reads the CPU register #[inline] pub fn read() -> u8 { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => { - let r: u32; - unsafe { - llvm_asm!("mrs $0, BASEPRI" : "=r"(r) ::: "volatile"); - } - r as u8 - } - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - extern "C" { - fn __basepri_r() -> u8; - } - - __basepri_r() - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + call_asm!(__basepri_r() -> u8) } /// Writes to the CPU register @@ -32,39 +11,14 @@ pub fn read() -> u8 { /// **IMPORTANT** If you are using a Cortex-M7 device with revision r0p1 you MUST enable the /// `cm7-r0p1` Cargo feature or this function WILL misbehave. #[inline] -pub unsafe fn write(_basepri: u8) { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => match () { - #[cfg(not(feature = "cm7-r0p1"))] - () => llvm_asm!("msr BASEPRI, $0" :: "r"(_basepri) : "memory" : "volatile"), - #[cfg(feature = "cm7-r0p1")] - () => crate::interrupt::free( - |_| llvm_asm!("msr BASEPRI, $0" :: "r"(_basepri) : "memory" : "volatile"), - ), - }, - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => match () { - #[cfg(not(feature = "cm7-r0p1"))] - () => { - extern "C" { - fn __basepri_w(_: u8); - } - - __basepri_w(_basepri); - } - #[cfg(feature = "cm7-r0p1")] - () => { - extern "C" { - fn __basepri_w_cm7_r0p1(_: u8); - } - - __basepri_w_cm7_r0p1(_basepri); - } - }, +pub unsafe fn write(basepri: u8) { + #[cfg(feature = "cm7-r0p1")] + { + call_asm!(__basepri_w_cm7_r0p1(basepri: u8)); + } - #[cfg(not(cortex_m))] - () => unimplemented!(), + #[cfg(not(feature = "cm7-r0p1"))] + { + call_asm!(__basepri_w(basepri: u8)); } } diff --git a/src/register/basepri_max.rs b/src/register/basepri_max.rs index 0e66f69..cea3838 100644 --- a/src/register/basepri_max.rs +++ b/src/register/basepri_max.rs @@ -8,43 +8,14 @@ /// **IMPORTANT** If you are using a Cortex-M7 device with revision r0p1 you MUST enable the /// `cm7-r0p1` Cargo feature or this function WILL misbehave. #[inline] -pub fn write(_basepri: u8) { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => unsafe { - match () { - #[cfg(not(feature = "cm7-r0p1"))] - () => llvm_asm!("msr BASEPRI_MAX, $0" :: "r"(_basepri) : "memory" : "volatile"), - #[cfg(feature = "cm7-r0p1")] - () => crate::interrupt::free( - |_| llvm_asm!("msr BASEPRI_MAX, $0" :: "r"(_basepri) : "memory" : "volatile"), - ), - } - }, - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - match () { - #[cfg(not(feature = "cm7-r0p1"))] - () => { - extern "C" { - fn __basepri_max(_: u8); - } - - __basepri_max(_basepri) - } - #[cfg(feature = "cm7-r0p1")] - () => { - extern "C" { - fn __basepri_max_cm7_r0p1(_: u8); - } - - __basepri_max_cm7_r0p1(_basepri) - } - } - }, +pub fn write(basepri: u8) { + #[cfg(feature = "cm7-r0p1")] + { + call_asm!(__basepri_max_cm7_r0p1(basepri: u8)); + } - #[cfg(not(cortex_m))] - () => unimplemented!(), + #[cfg(not(feature = "cm7-r0p1"))] + { + call_asm!(__basepri_max(basepri: u8)); } } diff --git a/src/register/control.rs b/src/register/control.rs index 211b532..938b10f 100644 --- a/src/register/control.rs +++ b/src/register/control.rs @@ -156,58 +156,13 @@ impl Fpca { /// Reads the CPU register #[inline] pub fn read() -> Control { - match () { - #[cfg(cortex_m)] - () => { - let r = match () { - #[cfg(feature = "inline-asm")] - () => { - let r: u32; - unsafe { llvm_asm!("mrs $0, CONTROL" : "=r"(r) ::: "volatile") } - r - } - - #[cfg(not(feature = "inline-asm"))] - () => unsafe { - extern "C" { - fn __control_r() -> u32; - } - - __control_r() - }, - }; - - Control { bits: r } - } - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + let bits: u32 = call_asm!(__control_r() -> u32); + Control { bits } } /// Writes to the CPU register. #[inline] -pub unsafe fn write(_control: Control) { - match () { - #[cfg(cortex_m)] - () => match () { - #[cfg(feature = "inline-asm")] - () => { - let control = _control.bits(); - llvm_asm!("msr CONTROL, $0" :: "r"(control) : "memory" : "volatile"); - } - - #[cfg(not(feature = "inline-asm"))] - () => { - extern "C" { - fn __control_w(bits: u32); - } - - __control_w(_control.bits()); - } - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } +pub unsafe fn write(control: Control) { + let control = control.bits(); + call_asm!(__control_w(control: u32)); } diff --git a/src/register/faultmask.rs b/src/register/faultmask.rs index 06f60fe..1f19d97 100644 --- a/src/register/faultmask.rs +++ b/src/register/faultmask.rs @@ -27,36 +27,10 @@ impl Faultmask { /// Reads the CPU register #[inline] pub fn read() -> Faultmask { - match () { - #[cfg(cortex_m)] - () => { - let r = match () { - #[cfg(feature = "inline-asm")] - () => { - let r: u32; - unsafe { llvm_asm!("mrs $0, FAULTMASK" : "=r"(r) ::: "volatile") } - r - } - - #[cfg(not(feature = "inline-asm"))] - () => unsafe { - extern "C" { - fn __faultmask() -> u32; - - } - - __faultmask() - }, - }; - - if r & (1 << 0) == (1 << 0) { - Faultmask::Inactive - } else { - Faultmask::Active - } - } - - #[cfg(not(cortex_m))] - () => unimplemented!(), + let r: u32 = call_asm!(__faultmask_r() -> u32); + if r & (1 << 0) == (1 << 0) { + Faultmask::Inactive + } else { + Faultmask::Active } } diff --git a/src/register/fpscr.rs b/src/register/fpscr.rs index 2ca00e1..dd538e9 100644 --- a/src/register/fpscr.rs +++ b/src/register/fpscr.rs @@ -295,49 +295,13 @@ impl RMode { /// 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!(), - } + let r: u32 = call_asm!(__fpscr_r() -> u32); + Fpscr::from_bits(r) } /// 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!(), - } +pub unsafe fn write(fpscr: Fpscr) { + let fpscr = fpscr.bits(); + call_asm!(__fpscr_w(fpscr: u32)); } diff --git a/src/register/lr.rs b/src/register/lr.rs index 6919e10..1aa546c 100644 --- a/src/register/lr.rs +++ b/src/register/lr.rs @@ -5,29 +5,13 @@ /// **NOTE** This function is available if `cortex-m` is built with the `"inline-asm"` feature. #[inline] pub fn read() -> u32 { - match () { - #[cfg(cortex_m)] - () => { - let r: u32; - unsafe { llvm_asm!("mov $0,R14" : "=r"(r) ::: "volatile") } - r - } - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + call_asm!(__lr_r() -> u32) } /// Writes `bits` to the CPU register /// /// **NOTE** This function is available if `cortex-m` is built with the `"inline-asm"` feature. #[inline] -pub unsafe fn write(_bits: u32) { - match () { - #[cfg(cortex_m)] - () => llvm_asm!("mov R14,$0" :: "r"(_bits) :: "volatile"), - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } +pub unsafe fn write(bits: u32) { + call_asm!(__lr_w(bits: u32)); } diff --git a/src/register/mod.rs b/src/register/mod.rs index efbe6ef..48d157a 100644 --- a/src/register/mod.rs +++ b/src/register/mod.rs @@ -58,11 +58,11 @@ pub mod psplim; // Accessing these registers requires inline assembly because their contents are tied to the current // stack frame -#[cfg(any(feature = "inline-asm", target_arch = "x86_64"))] +#[cfg(feature = "inline-asm")] pub mod apsr; -#[cfg(any(feature = "inline-asm", target_arch = "x86_64"))] +#[cfg(feature = "inline-asm")] pub mod lr; -#[cfg(any(feature = "inline-asm", target_arch = "x86_64"))] +#[cfg(feature = "inline-asm")] pub mod pc; diff --git a/src/register/msp.rs b/src/register/msp.rs index b5460ed..275023d 100644 --- a/src/register/msp.rs +++ b/src/register/msp.rs @@ -3,45 +3,11 @@ /// Reads the CPU register #[inline] pub fn read() -> u32 { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => { - let r; - unsafe { llvm_asm!("mrs $0,MSP" : "=r"(r) ::: "volatile") } - r - } - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - extern "C" { - fn __msp_r() -> u32; - } - - __msp_r() - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + call_asm!(__msp_r() -> u32) } /// Writes `bits` to the CPU register #[inline] -pub unsafe fn write(_bits: u32) { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => llvm_asm!("msr MSP,$0" :: "r"(_bits) :: "volatile"), - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => { - extern "C" { - fn __msp_w(_: u32); - } - - __msp_w(_bits); - } - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } +pub unsafe fn write(bits: u32) { + call_asm!(__msp_w(bits: u32)); } diff --git a/src/register/msplim.rs b/src/register/msplim.rs index 68915c4..ac6f9ed 100644 --- a/src/register/msplim.rs +++ b/src/register/msplim.rs @@ -3,45 +3,11 @@ /// Reads the CPU register #[inline] pub fn read() -> u32 { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => { - let r; - unsafe { llvm_asm!("mrs $0,MSPLIM" : "=r"(r) ::: "volatile") } - r - } - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - extern "C" { - fn __msplim_r() -> u32; - } - - __msplim_r() - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + call_asm!(__msplim_r() -> u32) } /// Writes `bits` to the CPU register #[inline] -pub unsafe fn write(_bits: u32) { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => llvm_asm!("msr MSPLIM,$0" :: "r"(_bits) :: "volatile"), - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => { - extern "C" { - fn __msplim_w(_: u32); - } - - __msplim_w(_bits); - } - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } +pub unsafe fn write(bits: u32) { + call_asm!(__msplim_w(bits: u32)) } diff --git a/src/register/pc.rs b/src/register/pc.rs index f4486c4..0b33629 100644 --- a/src/register/pc.rs +++ b/src/register/pc.rs @@ -5,29 +5,13 @@ /// **NOTE** This function is available if `cortex-m` is built with the `"inline-asm"` feature. #[inline] pub fn read() -> u32 { - match () { - #[cfg(cortex_m)] - () => { - let r; - unsafe { llvm_asm!("mov $0,R15" : "=r"(r) ::: "volatile") } - r - } - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + call_asm!(__pc_r() -> u32) } /// Writes `bits` to the CPU register /// /// **NOTE** This function is available if `cortex-m` is built with the `"inline-asm"` feature. #[inline] -pub unsafe fn write(_bits: u32) { - match () { - #[cfg(cortex_m)] - () => llvm_asm!("mov R15,$0" :: "r"(_bits) :: "volatile"), - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } +pub unsafe fn write(bits: u32) { + call_asm!(__pc_w(bits: u32)); } diff --git a/src/register/primask.rs b/src/register/primask.rs index 4b6df3c..20692a2 100644 --- a/src/register/primask.rs +++ b/src/register/primask.rs @@ -27,35 +27,14 @@ impl Primask { /// Reads the CPU register #[inline] pub fn read() -> Primask { - match () { - #[cfg(cortex_m)] - () => { - let r = match () { - #[cfg(feature = "inline-asm")] - () => { - let r: u32; - unsafe { llvm_asm!("mrs $0, PRIMASK" : "=r"(r) ::: "volatile") } - r - } - - #[cfg(not(feature = "inline-asm"))] - () => { - extern "C" { - fn __primask() -> u32; - } - - unsafe { __primask() } - } - }; - - if r & (1 << 0) == (1 << 0) { - Primask::Inactive - } else { - Primask::Active - } - } + fn read_raw() -> u32 { + call_asm!(__primask_r() -> u32) + } - #[cfg(not(cortex_m))] - () => unimplemented!(), + let r = read_raw(); + if r & (1 << 0) == (1 << 0) { + Primask::Inactive + } else { + Primask::Active } } diff --git a/src/register/psp.rs b/src/register/psp.rs index c020e4f..0bca22c 100644 --- a/src/register/psp.rs +++ b/src/register/psp.rs @@ -3,45 +3,11 @@ /// Reads the CPU register #[inline] pub fn read() -> u32 { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => { - let r; - unsafe { llvm_asm!("mrs $0,PSP" : "=r"(r) ::: "volatile") } - r - } - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - extern "C" { - fn __psp_r() -> u32; - } - - __psp_r() - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + call_asm!(__psp_r() -> u32) } /// Writes `bits` to the CPU register #[inline] -pub unsafe fn write(_bits: u32) { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => llvm_asm!("msr PSP,$0" :: "r"(_bits) :: "volatile"), - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => { - extern "C" { - fn __psp_w(_: u32); - } - - __psp_w(_bits); - } - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } +pub unsafe fn write(bits: u32) { + call_asm!(__psp_w(bits: u32)) } diff --git a/src/register/psplim.rs b/src/register/psplim.rs index 8cb8f1c..8ee1e94 100644 --- a/src/register/psplim.rs +++ b/src/register/psplim.rs @@ -3,45 +3,11 @@ /// Reads the CPU register #[inline] pub fn read() -> u32 { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => { - let r; - unsafe { llvm_asm!("mrs $0,PSPLIM" : "=r"(r) ::: "volatile") } - r - } - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => unsafe { - extern "C" { - fn __psplim_r() -> u32; - } - - __psplim_r() - }, - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } + call_asm!(__psplim_r() -> u32) } /// Writes `bits` to the CPU register #[inline] -pub unsafe fn write(_bits: u32) { - match () { - #[cfg(all(cortex_m, feature = "inline-asm"))] - () => llvm_asm!("msr PSPLIM,$0" :: "r"(_bits) :: "volatile"), - - #[cfg(all(cortex_m, not(feature = "inline-asm")))] - () => { - extern "C" { - fn __psplim_w(_: u32); - } - - __psplim_w(_bits); - } - - #[cfg(not(cortex_m))] - () => unimplemented!(), - } +pub unsafe fn write(bits: u32) { + call_asm!(__psplim_w(bits: u32)) } |