Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * arch/arm/lib/call_with_stack.S
0004  *
0005  * Copyright (C) 2011 ARM Ltd.
0006  * Written by Will Deacon <will.deacon@arm.com>
0007  */
0008 
0009 #include <linux/linkage.h>
0010 #include <asm/assembler.h>
0011 #include <asm/unwind.h>
0012 
0013 /*
0014  * void call_with_stack(void (*fn)(void *), void *arg, void *sp)
0015  *
0016  * Change the stack to that pointed at by sp, then invoke fn(arg) with
0017  * the new stack.
0018  *
0019  * The sequence below follows the APCS frame convention for frame pointer
0020  * unwinding, and implements the unwinder annotations needed by the EABI
0021  * unwinder.
0022  */
0023 
0024 ENTRY(call_with_stack)
0025 #if defined(CONFIG_UNWINDER_FRAME_POINTER) && defined(CONFIG_CC_IS_GCC)
0026     mov ip, sp
0027     push    {fp, ip, lr, pc}
0028     sub fp, ip, #4
0029 #else
0030 UNWIND( .fnstart        )
0031 UNWIND( .save   {fpreg, lr} )
0032     push    {fpreg, lr}
0033 UNWIND( .setfp  fpreg, sp   )
0034     mov fpreg, sp
0035 #endif
0036     mov sp, r2
0037     mov r2, r0
0038     mov r0, r1
0039 
0040     bl_r    r2
0041 
0042 #if defined(CONFIG_UNWINDER_FRAME_POINTER) && defined(CONFIG_CC_IS_GCC)
0043     ldmdb   fp, {fp, sp, pc}
0044 #else
0045     mov sp, fpreg
0046     pop {fpreg, pc}
0047 UNWIND( .fnend          )
0048 #endif
0049 ENDPROC(call_with_stack)