aboutsummaryrefslogtreecommitdiff
path: root/asm.rs
diff options
context:
space:
mode:
authorGravatar bors[bot] <26634292+bors[bot]@users.noreply.github.com> 2020-08-31 21:08:05 +0000
committerGravatar GitHub <noreply@github.com> 2020-08-31 21:08:05 +0000
commitb05a24e6b31e039e059760a4245b378df008faf8 (patch)
tree50a7ce8ead7bb9ef1f34216e8934988572d442a8 /asm.rs
parent3260e397647b5ea4984e8c82cb537f2475da0f5d (diff)
parentc27c8e5b063bd7058ba05dc3a9fa7886a1b1545c (diff)
downloadcortex-m-b05a24e6b31e039e059760a4245b378df008faf8.tar.gz
cortex-m-b05a24e6b31e039e059760a4245b378df008faf8.tar.zst
cortex-m-b05a24e6b31e039e059760a4245b378df008faf8.zip
Merge #262
262: Merge asm implementations r=therealprof a=jonas-schievink This replaces the implementation of `inline-asm` with the file I wrote in #259 (and some fixes). All functions that call assembly now do so via a `call_asm!` macro that either dispatches to a call to an `#[inline(always)]` function containing the inline `asm!`, or to the FFI shim. This makes all functions that call into asm significantly shorter. The FFI shim is now also macro-generated, which makes it very small. Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
Diffstat (limited to 'asm.rs')
-rw-r--r--asm.rs346
1 files changed, 0 insertions, 346 deletions
diff --git a/asm.rs b/asm.rs
deleted file mode 100644
index f5b0179..0000000
--- a/asm.rs
+++ /dev/null
@@ -1,346 +0,0 @@
-//! Assembly stubs for the `cortex-m` crate.
-//!
-//! We use this file to precompile some assembly stubs into the static libraries you can find in
-//! `bin`. Apps using the `cortex-m` crate then link against those static libraries and don't need
-//! to build this file themselves.
-//!
-//! Nowadays the assembly stubs are no longer actual assembly files, but actually just this Rust
-//! file `asm.rs` that uses unstable inline assembly, coupled with the `xtask` tool to invoke rustc
-//! and build the files.
-//!
-//! Precompiling this to a static lib allows users to call assembly routines from stable Rust, but
-//! also perform [linker plugin LTO] with the precompiled artifacts to completely inline the
-//! assembly routines into their code, which brings the "outline assembly" on par with "real" inline
-//! assembly.
-//!
-//! For developers and contributors to `cortex-m`, this setup means that they don't have to install
-//! any binutils, assembler, or C compiler to hack on the crate. All they need is to run `cargo
-//! xtask assemble` to rebuild the archives from this file.
-//!
-//! Cool, right?
-//!
-//! # Rust version management
-//!
-//! Since inline assembly is still unstable, and we want to ensure that the created blobs are
-//! up-to-date in CI, we have to pin the nightly version we use for this. The nightly toolchain is
-//! stored in `asm-toolchain`.
-//!
-//! The `cargo xtask` automation will automatically install the `asm-toolchain` as well as all
-//! Cortex-M targets needed to generate the blobs.
-//!
-//! [linker plugin LTO]: https://doc.rust-lang.org/stable/rustc/linker-plugin-lto.html
-
-#![feature(asm)]
-#![no_std]
-#![crate_type = "staticlib"]
-#![deny(warnings)]
-
-#[no_mangle]
-pub unsafe extern "C" fn __bkpt() {
- asm!("bkpt");
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn __control_r() -> u32 {
- let r;
- asm!("mrs {}, CONTROL", out(reg) r);
- r
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn __control_w(w: u32) {
- asm!("msr CONTROL, {}", in(reg) w);
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn __cpsid() {
- asm!("cpsid i");
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn __cpsie() {
- asm!("cpsie i");
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn __delay(cyc: u32) {
- asm!("
- 1:
- nop
- subs {}, #1
- bne 1b
- // Branch to 1 instead of __delay does not generate R_ARM_THM_JUMP8 relocation, which breaks
- // linking on the thumbv6m-none-eabi target
- ", in(reg) cyc);
-}
-
-// FIXME do we need compiler fences here or should we expect them in the caller?
-#[no_mangle]
-pub unsafe extern "C" fn __dmb() {
- asm!("dmb 0xF");
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn __dsb() {
- asm!("dsb 0xF");
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn __isb() {
- asm!("isb 0xF");
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn __msp_r() -> u32 {
- let r;
- asm!("mrs {}, MSP", out(reg) r);
- r
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn __msp_w(val: u32) {
- asm!("msr MSP, {}", in(reg) val);
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn __nop() {
- // NOTE: This is a `pure` asm block, but applying that option allows the compiler to eliminate
- // the nop entirely (or to collapse multiple subsequent ones). Since the user probably wants N
- // nops when they call `nop` N times, let's not add that option.
- asm!("nop");
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn __primask() -> u32 {
- // FIXME: rename to __primask_r
- let r;
- asm!("mrs {}, PRIMASK", out(reg) r);
- r
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn __psp_r() -> u32 {
- let r;
- asm!("mrs {}, PSP", out(reg) r);
- r
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn __psp_w(val: u32) {
- asm!("msr PSP, {}", in(reg) val);
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn __sev() {
- asm!("sev");
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn __udf() {
- asm!("udf #0");
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn __wfe() {
- asm!("wfe");
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn __wfi() {
- asm!("wfi");
-}
-
-#[cfg(armv7m)]
-pub mod v7m {
- #[no_mangle]
- pub unsafe extern "C" fn __basepri_max(val: u8) {
- asm!("msr BASEPRI_MAX, {}", in(reg) val);
- }
-
- #[no_mangle]
- pub unsafe extern "C" fn __basepri_r() -> u8 {
- let r;
- asm!("mrs {}, BASEPRI", out(reg) r);
- r
- }
-
- #[no_mangle]
- pub unsafe extern "C" fn __basepri_w(val: u8) {
- asm!("msr BASEPRI, {}", in(reg) val);
- }
-
- #[no_mangle]
- pub unsafe extern "C" fn __faultmask() -> u32 {
- let r;
- asm!("mrs {}, FAULTMASK", out(reg) r);
- r
- }
-
- // FIXME: compiler_fences necessary?
- #[no_mangle]
- pub unsafe extern "C" fn __enable_icache() {
- asm!(
- "
- ldr r0, =0xE000ED14 @ CCR
- mrs r2, PRIMASK @ save critical nesting info
- cpsid i @ mask interrupts
- ldr r1, [r0] @ read CCR
- orr.w r1, r1, #(1 << 17) @ Set bit 17, IC
- str r1, [r0] @ write it back
- dsb @ ensure store completes
- isb @ synchronize pipeline
- msr PRIMASK, r2 @ unnest critical section
- ",
- out("r0") _,
- out("r1") _,
- out("r2") _,
- );
- }
-
- #[no_mangle]
- pub unsafe extern "C" fn __enable_dcache() {
- asm!(
- "
- ldr r0, =0xE000ED14 @ CCR
- mrs r2, PRIMASK @ save critical nesting info
- cpsid i @ mask interrupts
- ldr r1, [r0] @ read CCR
- orr.w r1, r1, #(1 << 16) @ Set bit 16, DC
- str r1, [r0] @ write it back
- dsb @ ensure store completes
- isb @ synchronize pipeline
- msr PRIMASK, r2 @ unnest critical section
- ",
- out("r0") _,
- out("r1") _,
- out("r2") _,
- );
- }
-}
-
-#[cfg(armv7em)]
-mod v7em {
- #[no_mangle]
- pub unsafe extern "C" fn __basepri_max_cm7_r0p1(val: u8) {
- asm!(
- "
- mrs r1, PRIMASK
- cpsid i
- tst.w r1, #1
- msr BASEPRI_MAX, {}
- it ne
- bxne lr
- cpsie i
- ",
- in(reg) val,
- out("r1") _,
- );
- }
-
- #[no_mangle]
- pub unsafe extern "C" fn __basepri_w_cm7_r0p1(val: u8) {
- asm!(
- "
- mrs r1, PRIMASK
- cpsid i
- tst.w r1, #1
- msr BASEPRI, {}
- it ne
- bxne lr
- cpsie i
- ",
- in(reg) val,
- out("r1") _,
- );
- }
-}
-
-/// Baseline and Mainline.
-#[cfg(armv8m)]
-pub mod v8m {
- #[no_mangle]
- pub unsafe extern "C" fn __tt(mut target: u32) -> u32 {
- asm!("tt {target}, {target}", target = inout(reg) target);
- target
- }
-
- #[no_mangle]
- pub unsafe extern "C" fn __ttt(mut target: u32) -> u32 {
- asm!("ttt {target}, {target}", target = inout(reg) target);
- target
- }
-
- #[no_mangle]
- pub unsafe extern "C" fn __tta(mut target: u32) -> u32 {
- asm!("tta {target}, {target}", target = inout(reg) target);
- target
- }
-
- #[no_mangle]
- pub unsafe extern "C" fn __ttat(mut target: u32) -> u32 {
- asm!("ttat {target}, {target}", target = inout(reg) target);
- target
- }
-}
-
-/// Mainline only.
-#[cfg(armv8m_main)]
-pub mod v8m_main {
- #[no_mangle]
- pub unsafe extern "C" fn __msplim_r() -> u32 {
- let r;
- asm!("mrs {}, MSPLIM", out(reg) r);
- r
- }
-
- #[no_mangle]
- pub unsafe extern "C" fn __msplim_w(val: u32) {
- asm!("msr MSPLIM, {}", in(reg) val);
- }
-
- #[no_mangle]
- pub unsafe extern "C" fn __psplim_r() -> u32 {
- let r;
- asm!("mrs {}, PSPLIM", out(reg) r);
- r
- }
-
- #[no_mangle]
- pub unsafe extern "C" fn __psplim_w(val: u32) {
- asm!("msr PSPLIM, {}", in(reg) val);
- }
-}
-
-/// All targets with FPU.
-#[cfg(has_fpu)]
-pub mod fpu {
- #[no_mangle]
- pub unsafe extern "C" fn __get_FPSCR() -> u32 {
- let r;
- asm!("vmrs {}, fpscr", out(reg) r);
- r
- }
-
- #[no_mangle]
- pub unsafe extern "C" fn __set_FPSCR(val: u32) {
- asm!("vmsr fpscr, {}", in(reg) val);
- }
-}
-
-/// We *must* define a panic handler here, even though nothing here should ever be able to panic.
-///
-/// We prove that nothing will ever panic by calling a function that doesn't exist. If the panic
-/// handler gets linked in, this causes a linker error. We always build this file with optimizations
-/// enabled, but even without them the panic handler should never be linked in.
-#[panic_handler]
-fn panic(_: &core::panic::PanicInfo) -> ! {
- extern "C" {
- #[link_name = "cortex-m internal error: panic handler not optimized out, please file an \
- issue at https://github.com/rust-embedded/cortex-m"]
- fn __cortex_m_should_not_panic() -> !;
- }
-
- unsafe {
- __cortex_m_should_not_panic();
- }
-}