1
+ //@ revisions: hard soft
1
2
//@ 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
4
7
#![ crate_type = "lib" ]
5
8
#![ feature( abi_c_cmse_nonsecure_call, cmse_nonsecure_entry, no_core, lang_items) ]
6
9
#![ no_core]
@@ -9,15 +12,88 @@ pub trait Sized {}
9
12
#[ lang = "copy" ]
10
13
pub trait Copy { }
11
14
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
14
55
#[ no_mangle]
15
56
pub extern "C-cmse-nonsecure-entry" fn entry_point ( ) -> i64 {
16
57
0
17
58
}
18
59
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
+ //
19
69
// 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
21
97
#[ no_mangle]
22
98
pub fn call_nonsecure (
23
99
f : unsafe extern "C-cmse-nonsecure-call" fn ( u32 , u32 , u32 , u32 ) -> u64 ,
0 commit comments