162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * arch/arm/lib/call_with_stack.S 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2011 ARM Ltd. 662306a36Sopenharmony_ci * Written by Will Deacon <will.deacon@arm.com> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/linkage.h> 1062306a36Sopenharmony_ci#include <asm/assembler.h> 1162306a36Sopenharmony_ci#include <asm/unwind.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci/* 1462306a36Sopenharmony_ci * void call_with_stack(void (*fn)(void *), void *arg, void *sp) 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * Change the stack to that pointed at by sp, then invoke fn(arg) with 1762306a36Sopenharmony_ci * the new stack. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * The sequence below follows the APCS frame convention for frame pointer 2062306a36Sopenharmony_ci * unwinding, and implements the unwinder annotations needed by the EABI 2162306a36Sopenharmony_ci * unwinder. 2262306a36Sopenharmony_ci */ 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ciENTRY(call_with_stack) 2562306a36Sopenharmony_ci#if defined(CONFIG_UNWINDER_FRAME_POINTER) && defined(CONFIG_CC_IS_GCC) 2662306a36Sopenharmony_ci mov ip, sp 2762306a36Sopenharmony_ci push {fp, ip, lr, pc} 2862306a36Sopenharmony_ci sub fp, ip, #4 2962306a36Sopenharmony_ci#else 3062306a36Sopenharmony_ciUNWIND( .fnstart ) 3162306a36Sopenharmony_ciUNWIND( .save {fpreg, lr} ) 3262306a36Sopenharmony_ci push {fpreg, lr} 3362306a36Sopenharmony_ciUNWIND( .setfp fpreg, sp ) 3462306a36Sopenharmony_ci mov fpreg, sp 3562306a36Sopenharmony_ci#endif 3662306a36Sopenharmony_ci mov sp, r2 3762306a36Sopenharmony_ci mov r2, r0 3862306a36Sopenharmony_ci mov r0, r1 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci bl_r r2 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#if defined(CONFIG_UNWINDER_FRAME_POINTER) && defined(CONFIG_CC_IS_GCC) 4362306a36Sopenharmony_ci ldmdb fp, {fp, sp, pc} 4462306a36Sopenharmony_ci#else 4562306a36Sopenharmony_ci mov sp, fpreg 4662306a36Sopenharmony_ci pop {fpreg, pc} 4762306a36Sopenharmony_ciUNWIND( .fnend ) 4862306a36Sopenharmony_ci#endif 4962306a36Sopenharmony_ci .globl call_with_stack_end 5062306a36Sopenharmony_cicall_with_stack_end: 5162306a36Sopenharmony_ciENDPROC(call_with_stack) 52