Skip to content

Commit 1f52c07

Browse files
authored
Rollup merge of rust-lang#130752 - tdittr:cmse-assembly-tests, r=jieyouxu
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.
2 parents 75296fc + 3d168c2 commit 1f52c07

File tree

1 file changed

+81
-5
lines changed

1 file changed

+81
-5
lines changed

tests/assembly/cmse.rs

+81-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
//@ revisions: hard soft
12
//@ assembly-output: emit-asm
2-
//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -Copt-level=1
3-
//@ needs-llvm-components: arm
3+
//@ [hard] compile-flags: --target thumbv8m.main-none-eabihf --crate-type lib -Copt-level=1
4+
//@ [soft] compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -Copt-level=1
5+
//@ [hard] needs-llvm-components: arm
6+
//@ [soft] needs-llvm-components: arm
47
#![crate_type = "lib"]
58
#![feature(abi_c_cmse_nonsecure_call, cmse_nonsecure_entry, no_core, lang_items)]
69
#![no_core]
@@ -9,15 +12,88 @@ pub trait Sized {}
912
#[lang = "copy"]
1013
pub trait Copy {}
1114

12-
// CHECK-LABEL: __acle_se_entry_point
13-
// CHECK: bxns
15+
// CHECK-LABEL: __acle_se_entry_point:
16+
// CHECK-NEXT: entry_point:
17+
//
18+
// Write return argument (two registers since 64bit integer)
19+
// CHECK: movs r0, #0
20+
// CHECK: movs r1, #0
21+
//
22+
// If we are using hard-float:
23+
// * Check if the float registers were touched (bit 3 in CONTROL)
24+
// hard: mrs [[REG:r[0-9]+]], control
25+
// hard: tst.w [[REG]], #8
26+
// hard: beq [[LABEL:[\.a-zA-Z0-9_]+]]
27+
//
28+
// * If touched clear all float registers (d0..=d7)
29+
// hard: vmov d0,
30+
// hard: vmov d1,
31+
// hard: vmov d2,
32+
// hard: vmov d3,
33+
// hard: vmov d4,
34+
// hard: vmov d5,
35+
// hard: vmov d6,
36+
// hard: vmov d7,
37+
//
38+
// * If touched clear FPU status register
39+
// hard: vmrs [[REG:r[0-9]+]], fpscr
40+
// hard: bic [[REG]], [[REG]], #159
41+
// hard: bic [[REG]], [[REG]], #4026531840
42+
// hard: vmsr fpscr, [[REG]]
43+
// hard: [[LABEL]]:
44+
//
45+
// Clear all other registers that might have been used
46+
// CHECK: mov r2,
47+
// CHECK: mov r3,
48+
// CHECK: mov r12,
49+
//
50+
// Clear the flags
51+
// CHECK: msr apsr_nzcvq,
52+
//
53+
// Branch back to non-secure side
54+
// CHECK: bxns lr
1455
#[no_mangle]
1556
pub extern "C-cmse-nonsecure-entry" fn entry_point() -> i64 {
1657
0
1758
}
1859

60+
// NOTE for future codegen changes:
61+
// The specific register assignment is not important, however:
62+
// * all registers must be cleared before `blxns` is executed
63+
// (either by writing arguments or any other value)
64+
// * the lowest bit on the address of the callee must be cleared
65+
// * the flags need to be overwritten
66+
// * `blxns` needs to be called with the callee address
67+
// (with the lowest bit cleared)
68+
//
1969
// CHECK-LABEL: call_nonsecure
20-
// CHECK: blxns
70+
// Save callee pointer
71+
// CHECK: mov r12, r0
72+
//
73+
// All arguments are written to (writes r0..=r3)
74+
// CHECK: movs r0, #0
75+
// CHECK: movs r1, #1
76+
// CHECK: movs r2, #2
77+
// CHECK: movs r3, #3
78+
//
79+
// Lowest bit gets cleared on callee address
80+
// CHECK: bic r12, r12, #1
81+
//
82+
// Ununsed registers get cleared (r4..=r11)
83+
// CHECK: mov r4,
84+
// CHECK: mov r5,
85+
// CHECK: mov r6,
86+
// CHECK: mov r7,
87+
// CHECK: mov r8,
88+
// CHECK: mov r9,
89+
// CHECK: mov r10,
90+
// CHECK: mov r11,
91+
//
92+
// Flags get cleared
93+
// CHECK: msr apsr_nzcvq,
94+
//
95+
// Call to non-secure
96+
// CHECK: blxns r12
2197
#[no_mangle]
2298
pub fn call_nonsecure(
2399
f: unsafe extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u64,

0 commit comments

Comments
 (0)