mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
1bc07f6217
This patch implements the final bits of CMSE code generation: * emit special linker symbols * restrict parameter passing to no use memory * emit BXNS and BLXNS instructions for returns from non-secure entry functions, and non-secure function calls, respectively * emit code to save/restore secure floating-point state around calls to non-secure functions * emit code to save/restore non-secure floating-pointy state upon entry to non-secure entry function, and return to non-secure state * emit code to clobber registers not used for arguments and returns * when switching to no-secure state Patch by Momchil Velikov, Bradley Smith, Javed Absar, David Green, possibly others. Differential Revision: https://reviews.llvm.org/D76518
173 lines
7.1 KiB
LLVM
173 lines
7.1 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc -mtriple=thumbv8.1m.main-eabi -mattr=+8msecext,+mve.fp %s -o - | FileCheck %s --check-prefix=CHECK-SOFTFP
|
|
; RUN: llc -mtriple=thumbebv8.1m.main-eabi -mattr=+8msecext,+mve.fp %s -o - | FileCheck %s --check-prefix=CHECK-SOFTFP
|
|
; RUN: llc -mtriple=thumbv8.1m.main-eabi -mattr=+8msecext,+mve.fp --float-abi=hard %s -o - | FileCheck %s --check-prefix=CHECK-HARD
|
|
; RUN: llc -mtriple=thumbebv8.1m.main-eabi -mattr=+8msecext,+mve.fp --float-abi=hard %s -o - | FileCheck %s --check-prefix=CHECK-HARD
|
|
|
|
declare <8 x i16> @g0(...) #0
|
|
declare <4 x float> @g1(...) #0
|
|
|
|
;;
|
|
;; Test clearing before return to nonsecure state
|
|
;;
|
|
|
|
define <8 x i16> @f0() #1 {
|
|
; CHECK-SOFTFP-LABEL: f0:
|
|
; CHECK-SOFTFP: @ %bb.0: @ %entry
|
|
; CHECK-SOFTFP-NEXT: vstr fpcxtns, [sp, #-4]!
|
|
; CHECK-SOFTFP-NEXT: .save {r7, lr}
|
|
; CHECK-SOFTFP-NEXT: push {r7, lr}
|
|
; CHECK-SOFTFP-NEXT: .pad #4
|
|
; CHECK-SOFTFP-NEXT: sub sp, #4
|
|
; CHECK-SOFTFP-NEXT: bl g0
|
|
; CHECK-SOFTFP-NEXT: add sp, #4
|
|
; CHECK-SOFTFP-NEXT: pop.w {r7, lr}
|
|
; CHECK-SOFTFP-NEXT: vscclrm {s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, vpr}
|
|
; CHECK-SOFTFP-NEXT: vldr fpcxtns, [sp], #4
|
|
; CHECK-SOFTFP-NEXT: clrm {r12, apsr}
|
|
; CHECK-SOFTFP-NEXT: bxns lr
|
|
;
|
|
; CHECK-HARD-LABEL: f0:
|
|
; CHECK-HARD: @ %bb.0: @ %entry
|
|
; CHECK-HARD-NEXT: vstr fpcxtns, [sp, #-4]!
|
|
; CHECK-HARD-NEXT: .save {r7, lr}
|
|
; CHECK-HARD-NEXT: push {r7, lr}
|
|
; CHECK-HARD-NEXT: .pad #4
|
|
; CHECK-HARD-NEXT: sub sp, #4
|
|
; CHECK-HARD-NEXT: bl g0
|
|
; CHECK-HARD-NEXT: add sp, #4
|
|
; CHECK-HARD-NEXT: pop.w {r7, lr}
|
|
; CHECK-HARD-NEXT: vscclrm {s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, vpr}
|
|
; CHECK-HARD-NEXT: vldr fpcxtns, [sp], #4
|
|
; CHECK-HARD-NEXT: clrm {r0, r1, r2, r3, r12, apsr}
|
|
; CHECK-HARD-NEXT: bxns lr
|
|
entry:
|
|
%call = call <8 x i16> bitcast (<8 x i16> (...)* @g0 to <8 x i16> ()*)() #0
|
|
ret <8 x i16> %call
|
|
}
|
|
|
|
define <4 x float> @f1() #1 {
|
|
; CHECK-SOFTFP-LABEL: f1:
|
|
; CHECK-SOFTFP: @ %bb.0: @ %entry
|
|
; CHECK-SOFTFP-NEXT: vstr fpcxtns, [sp, #-4]!
|
|
; CHECK-SOFTFP-NEXT: .save {r7, lr}
|
|
; CHECK-SOFTFP-NEXT: push {r7, lr}
|
|
; CHECK-SOFTFP-NEXT: .pad #4
|
|
; CHECK-SOFTFP-NEXT: sub sp, #4
|
|
; CHECK-SOFTFP-NEXT: bl g1
|
|
; CHECK-SOFTFP-NEXT: add sp, #4
|
|
; CHECK-SOFTFP-NEXT: pop.w {r7, lr}
|
|
; CHECK-SOFTFP-NEXT: vscclrm {s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, vpr}
|
|
; CHECK-SOFTFP-NEXT: vldr fpcxtns, [sp], #4
|
|
; CHECK-SOFTFP-NEXT: clrm {r12, apsr}
|
|
; CHECK-SOFTFP-NEXT: bxns lr
|
|
;
|
|
; CHECK-HARD-LABEL: f1:
|
|
; CHECK-HARD: @ %bb.0: @ %entry
|
|
; CHECK-HARD-NEXT: vstr fpcxtns, [sp, #-4]!
|
|
; CHECK-HARD-NEXT: .save {r7, lr}
|
|
; CHECK-HARD-NEXT: push {r7, lr}
|
|
; CHECK-HARD-NEXT: .pad #4
|
|
; CHECK-HARD-NEXT: sub sp, #4
|
|
; CHECK-HARD-NEXT: bl g1
|
|
; CHECK-HARD-NEXT: add sp, #4
|
|
; CHECK-HARD-NEXT: pop.w {r7, lr}
|
|
; CHECK-HARD-NEXT: vscclrm {s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, vpr}
|
|
; CHECK-HARD-NEXT: vldr fpcxtns, [sp], #4
|
|
; CHECK-HARD-NEXT: clrm {r0, r1, r2, r3, r12, apsr}
|
|
; CHECK-HARD-NEXT: bxns lr
|
|
entry:
|
|
%call = call nnan ninf nsz <4 x float> bitcast (<4 x float> (...)* @g1 to <4 x float> ()*)() #0
|
|
ret <4 x float> %call
|
|
}
|
|
|
|
;;
|
|
;; Test clearing around nonsecure calls
|
|
;;
|
|
|
|
define void @f2(void (<8 x i16>)* nocapture %cb) #0 {
|
|
; CHECK-SOFTFP-LABEL: f2:
|
|
; CHECK-SOFTFP: @ %bb.0: @ %entry
|
|
; CHECK-SOFTFP-NEXT: .save {r4, lr}
|
|
; CHECK-SOFTFP-NEXT: push {r4, lr}
|
|
; CHECK-SOFTFP-NEXT: mov r4, r0
|
|
; CHECK-SOFTFP-NEXT: bl g0
|
|
; CHECK-SOFTFP-NEXT: push.w {r4, r5, r6, r7, r8, r9, r10, r11}
|
|
; CHECK-SOFTFP-NEXT: bic r4, r4, #1
|
|
; CHECK-SOFTFP-NEXT: sub sp, #136
|
|
; CHECK-SOFTFP-NEXT: vlstm sp
|
|
; CHECK-SOFTFP-NEXT: clrm {r5, r6, r7, r8, r9, r10, r11, r12, apsr}
|
|
; CHECK-SOFTFP-NEXT: blxns r4
|
|
; CHECK-SOFTFP-NEXT: vlldm sp
|
|
; CHECK-SOFTFP-NEXT: add sp, #136
|
|
; CHECK-SOFTFP-NEXT: pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
|
|
; CHECK-SOFTFP-NEXT: pop {r4, pc}
|
|
;
|
|
; CHECK-HARD-LABEL: f2:
|
|
; CHECK-HARD: @ %bb.0: @ %entry
|
|
; CHECK-HARD-NEXT: .save {r4, lr}
|
|
; CHECK-HARD-NEXT: push {r4, lr}
|
|
; CHECK-HARD-NEXT: mov r4, r0
|
|
; CHECK-HARD-NEXT: bl g0
|
|
; CHECK-HARD-NEXT: push.w {r4, r5, r6, r7, r8, r9, r10, r11}
|
|
; CHECK-HARD-NEXT: bic r4, r4, #1
|
|
; CHECK-HARD-NEXT: vpush {s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}
|
|
; CHECK-HARD-NEXT: vscclrm {s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31, vpr}
|
|
; CHECK-HARD-NEXT: vstr fpcxts, [sp, #-8]!
|
|
; CHECK-HARD-NEXT: clrm {r0, r1, r2, r3, r5, r6, r7, r8, r9, r10, r11, r12, apsr}
|
|
; CHECK-HARD-NEXT: blxns r4
|
|
; CHECK-HARD-NEXT: vldr fpcxts, [sp], #8
|
|
; CHECK-HARD-NEXT: vpop {s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}
|
|
; CHECK-HARD-NEXT: pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
|
|
; CHECK-HARD-NEXT: pop {r4, pc}
|
|
entry:
|
|
%call = tail call <8 x i16> bitcast (<8 x i16> (...)* @g0 to <8 x i16> ()*)() #0
|
|
tail call void %cb(<8 x i16> %call) #2
|
|
ret void
|
|
}
|
|
|
|
define void @f3(void (<4 x float>)* nocapture %cb) #0 {
|
|
; CHECK-SOFTFP-LABEL: f3:
|
|
; CHECK-SOFTFP: @ %bb.0: @ %entry
|
|
; CHECK-SOFTFP-NEXT: .save {r4, lr}
|
|
; CHECK-SOFTFP-NEXT: push {r4, lr}
|
|
; CHECK-SOFTFP-NEXT: mov r4, r0
|
|
; CHECK-SOFTFP-NEXT: bl g1
|
|
; CHECK-SOFTFP-NEXT: push.w {r4, r5, r6, r7, r8, r9, r10, r11}
|
|
; CHECK-SOFTFP-NEXT: bic r4, r4, #1
|
|
; CHECK-SOFTFP-NEXT: sub sp, #136
|
|
; CHECK-SOFTFP-NEXT: vlstm sp
|
|
; CHECK-SOFTFP-NEXT: clrm {r5, r6, r7, r8, r9, r10, r11, r12, apsr}
|
|
; CHECK-SOFTFP-NEXT: blxns r4
|
|
; CHECK-SOFTFP-NEXT: vlldm sp
|
|
; CHECK-SOFTFP-NEXT: add sp, #136
|
|
; CHECK-SOFTFP-NEXT: pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
|
|
; CHECK-SOFTFP-NEXT: pop {r4, pc}
|
|
;
|
|
; CHECK-HARD-LABEL: f3:
|
|
; CHECK-HARD: @ %bb.0: @ %entry
|
|
; CHECK-HARD-NEXT: .save {r4, lr}
|
|
; CHECK-HARD-NEXT: push {r4, lr}
|
|
; CHECK-HARD-NEXT: mov r4, r0
|
|
; CHECK-HARD-NEXT: bl g1
|
|
; CHECK-HARD-NEXT: push.w {r4, r5, r6, r7, r8, r9, r10, r11}
|
|
; CHECK-HARD-NEXT: bic r4, r4, #1
|
|
; CHECK-HARD-NEXT: vpush {s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}
|
|
; CHECK-HARD-NEXT: vscclrm {s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31, vpr}
|
|
; CHECK-HARD-NEXT: vstr fpcxts, [sp, #-8]!
|
|
; CHECK-HARD-NEXT: clrm {r0, r1, r2, r3, r5, r6, r7, r8, r9, r10, r11, r12, apsr}
|
|
; CHECK-HARD-NEXT: blxns r4
|
|
; CHECK-HARD-NEXT: vldr fpcxts, [sp], #8
|
|
; CHECK-HARD-NEXT: vpop {s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}
|
|
; CHECK-HARD-NEXT: pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
|
|
; CHECK-HARD-NEXT: pop {r4, pc}
|
|
entry:
|
|
%call = tail call nnan ninf nsz <4 x float> bitcast (<4 x float> (...)* @g1 to <4 x float> ()*)() #0
|
|
tail call void %cb(<4 x float> %call) #2
|
|
ret void
|
|
}
|
|
|
|
attributes #0 = { nounwind }
|
|
attributes #1 = { nounwind "cmse_nonsecure_entry" }
|
|
attributes #2 = { nounwind "cmse_nonsecure_call" }
|