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]
@@ -10,14 +13,85 @@ pub trait Sized {}
1013pub trait Copy { }
1114
1215// CHECK-LABEL: __acle_se_entry_point
13- // CHECK: bxns
16+ // CHECK: 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 r12, control
25+ // hard: tst.w r12, #8
26+ // hard: beq .LBB0_2
27+ //
28+ // * If touched clear all float registers (d0..=d7)
29+ // hard: vmov d0, lr, lr
30+ // hard: vmov d1, lr, lr
31+ // hard: vmov d2, lr, lr
32+ // hard: vmov d3, lr, lr
33+ // hard: vmov d4, lr, lr
34+ // hard: vmov d5, lr, lr
35+ // hard: vmov d6, lr, lr
36+ // hard: vmov d7, lr, lr
37+ //
38+ // * If touched clear FPU status register
39+ // hard: vmrs r12, fpscr
40+ // hard: bic r12, r12, #159
41+ // hard: bic r12, r12, #4026531840
42+ // hard: vmsr fpscr, r12
43+ // hard: .LBB0_2:
44+ //
45+ // Clear all other registers that might have been used
46+ // CHECK: mov r2, lr
47+ // CHECK: mov r3, lr
48+ // CHECK: mov r12, lr
49+ //
50+ // Clear the flags
51+ // CHECK: msr apsr_nzcvq, lr
52+ //
53+ // Branch back to non-secure side
54+ // CHECK: bxns lr
1455#[ no_mangle]
1556pub 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+ // All arguments are written to (writes r0..=r3 and r12)
71+ // CHECK: mov r12, r0
72+ // CHECK: movs r0, #0
73+ // CHECK: movs r1, #1
74+ // CHECK: movs r2, #2
75+ // CHECK: movs r3, #3
76+ //
77+ // Lowest bit gets cleared on callee address
78+ // CHECK: bic r12, r12, #1
79+ //
80+ // Ununsed registers get cleared (r4..=r11)
81+ // CHECK: mov r4, r12
82+ // CHECK: mov r5, r12
83+ // CHECK: mov r6, r12
84+ // CHECK: mov r7, r12
85+ // CHECK: mov r8, r12
86+ // CHECK: mov r9, r12
87+ // CHECK: mov r10, r12
88+ // CHECK: mov r11, r12
89+ //
90+ // Flags get cleared
91+ // CHECK: msr apsr_nzcvq, r12
92+ //
93+ // Call to non-secure
94+ // CHECK: blxns r12
2195#[ no_mangle]
2296pub fn call_nonsecure (
2397 f : unsafe extern "C-cmse-nonsecure-call" fn ( u32 , u32 , u32 , u32 ) -> u64 ,
0 commit comments