; 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" }