52 строки
1.1 KiB
ArmAsm
52 строки
1.1 KiB
ArmAsm
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* arch/arm/lib/call_with_stack.S
|
|
*
|
|
* Copyright (C) 2011 ARM Ltd.
|
|
* Written by Will Deacon <will.deacon@arm.com>
|
|
*/
|
|
|
|
#include <linux/linkage.h>
|
|
#include <asm/assembler.h>
|
|
#include <asm/unwind.h>
|
|
|
|
/*
|
|
* void call_with_stack(void (*fn)(void *), void *arg, void *sp)
|
|
*
|
|
* Change the stack to that pointed at by sp, then invoke fn(arg) with
|
|
* the new stack.
|
|
*
|
|
* The sequence below follows the APCS frame convention for frame pointer
|
|
* unwinding, and implements the unwinder annotations needed by the EABI
|
|
* unwinder.
|
|
*/
|
|
|
|
ENTRY(call_with_stack)
|
|
#if defined(CONFIG_UNWINDER_FRAME_POINTER) && defined(CONFIG_CC_IS_GCC)
|
|
mov ip, sp
|
|
push {fp, ip, lr, pc}
|
|
sub fp, ip, #4
|
|
#else
|
|
UNWIND( .fnstart )
|
|
UNWIND( .save {fpreg, lr} )
|
|
push {fpreg, lr}
|
|
UNWIND( .setfp fpreg, sp )
|
|
mov fpreg, sp
|
|
#endif
|
|
mov sp, r2
|
|
mov r2, r0
|
|
mov r0, r1
|
|
|
|
bl_r r2
|
|
|
|
#if defined(CONFIG_UNWINDER_FRAME_POINTER) && defined(CONFIG_CC_IS_GCC)
|
|
ldmdb fp, {fp, sp, pc}
|
|
#else
|
|
mov sp, fpreg
|
|
pop {fpreg, pc}
|
|
UNWIND( .fnend )
|
|
#endif
|
|
.globl call_with_stack_end
|
|
call_with_stack_end:
|
|
ENDPROC(call_with_stack)
|