Skip to content

Commit

Permalink
Rollup merge of rust-lang#130752 - tdittr:cmse-assembly-tests, r=jiey…
Browse files Browse the repository at this point in the history
…ouxu

Improve assembly test for CMSE ABIs

Tracking issues: rust-lang#75835 rust-lang#81391

This ensures the code-gen for these ABIs does not change silently. There is a small chance that this code-gen might change, however even GCC (https://godbolt.org/z/16arxab5x and https://godbolt.org/z/16arxab5x) generates almost the same assembly for these ABIs. I hope the notes in the comments should help fix the tests if it ever breaks.
  • Loading branch information
tgross35 authored Sep 24, 2024
2 parents 75296fc + 3d168c2 commit 1f52c07
Showing 1 changed file with 81 additions and 5 deletions.
86 changes: 81 additions & 5 deletions tests/assembly/cmse.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
//@ revisions: hard soft
//@ assembly-output: emit-asm
//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -Copt-level=1
//@ needs-llvm-components: arm
//@ [hard] compile-flags: --target thumbv8m.main-none-eabihf --crate-type lib -Copt-level=1
//@ [soft] compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -Copt-level=1
//@ [hard] needs-llvm-components: arm
//@ [soft] needs-llvm-components: arm
#![crate_type = "lib"]
#![feature(abi_c_cmse_nonsecure_call, cmse_nonsecure_entry, no_core, lang_items)]
#![no_core]
Expand All @@ -9,15 +12,88 @@ pub trait Sized {}
#[lang = "copy"]
pub trait Copy {}

// CHECK-LABEL: __acle_se_entry_point
// CHECK: bxns
// CHECK-LABEL: __acle_se_entry_point:
// CHECK-NEXT: entry_point:
//
// Write return argument (two registers since 64bit integer)
// CHECK: movs r0, #0
// CHECK: movs r1, #0
//
// If we are using hard-float:
// * Check if the float registers were touched (bit 3 in CONTROL)
// hard: mrs [[REG:r[0-9]+]], control
// hard: tst.w [[REG]], #8
// hard: beq [[LABEL:[\.a-zA-Z0-9_]+]]
//
// * If touched clear all float registers (d0..=d7)
// hard: vmov d0,
// hard: vmov d1,
// hard: vmov d2,
// hard: vmov d3,
// hard: vmov d4,
// hard: vmov d5,
// hard: vmov d6,
// hard: vmov d7,
//
// * If touched clear FPU status register
// hard: vmrs [[REG:r[0-9]+]], fpscr
// hard: bic [[REG]], [[REG]], #159
// hard: bic [[REG]], [[REG]], #4026531840
// hard: vmsr fpscr, [[REG]]
// hard: [[LABEL]]:
//
// Clear all other registers that might have been used
// CHECK: mov r2,
// CHECK: mov r3,
// CHECK: mov r12,
//
// Clear the flags
// CHECK: msr apsr_nzcvq,
//
// Branch back to non-secure side
// CHECK: bxns lr
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn entry_point() -> i64 {
0
}

// NOTE for future codegen changes:
// The specific register assignment is not important, however:
// * all registers must be cleared before `blxns` is executed
// (either by writing arguments or any other value)
// * the lowest bit on the address of the callee must be cleared
// * the flags need to be overwritten
// * `blxns` needs to be called with the callee address
// (with the lowest bit cleared)
//
// CHECK-LABEL: call_nonsecure
// CHECK: blxns
// Save callee pointer
// CHECK: mov r12, r0
//
// All arguments are written to (writes r0..=r3)
// CHECK: movs r0, #0
// CHECK: movs r1, #1
// CHECK: movs r2, #2
// CHECK: movs r3, #3
//
// Lowest bit gets cleared on callee address
// CHECK: bic r12, r12, #1
//
// Ununsed registers get cleared (r4..=r11)
// CHECK: mov r4,
// CHECK: mov r5,
// CHECK: mov r6,
// CHECK: mov r7,
// CHECK: mov r8,
// CHECK: mov r9,
// CHECK: mov r10,
// CHECK: mov r11,
//
// Flags get cleared
// CHECK: msr apsr_nzcvq,
//
// Call to non-secure
// CHECK: blxns r12
#[no_mangle]
pub fn call_nonsecure(
f: unsafe extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u64,
Expand Down

0 comments on commit 1f52c07

Please sign in to comment.