xref: /optee_os/lib/libutils/ext/arch/arm/mcount_a32.S (revision d658309647eb2ea592263a956999db54bd517fc5)
1e3dddf72SSumit Garg/* SPDX-License-Identifier: BSD-2-Clause */
2e3dddf72SSumit Garg/*
3e3dddf72SSumit Garg * Copyright (c) 2016, Linaro Limited
4e3dddf72SSumit Garg */
5e3dddf72SSumit Garg
6e3dddf72SSumit Garg#include <asm.S>
7e3dddf72SSumit Garg
8099918f6SSumit Garg#if defined(CFG_TA_GPROF_SUPPORT) || defined(CFG_FTRACE_SUPPORT)
9e3dddf72SSumit Garg
10e3dddf72SSumit Garg/*
11e3dddf72SSumit Garg * Convert return address to call site address by subtracting the size of the
12e3dddf72SSumit Garg * mcount call instruction (blx __gnu_mcount_nc).
13e3dddf72SSumit Garg */
14e3dddf72SSumit Garg.macro mcount_adj_pc rd, rn
15e3dddf72SSumit Garg	bic	\rd, \rn, #1	/* Clear thumb bit if present */
16e3dddf72SSumit Garg	sub	\rd, \rd, #4
17e3dddf72SSumit Garg.endm
18e3dddf72SSumit Garg
19e3dddf72SSumit Garg/*
20e3dddf72SSumit Garg * With the -pg option, GCC (4.4+) inserts a call to __gnu_mcount_nc into
21e3dddf72SSumit Garg * every function prologue.
22e3dddf72SSumit Garg * The caller of the instrumented function can be determined from the lr value
23e3dddf72SSumit Garg * stored on the top of the stack. The callee, i.e. the instrumented function
24e3dddf72SSumit Garg * itself, is determined from the current value of lr. Then we call:
25e3dddf72SSumit Garg *   void __mcount_internal(void *frompc, void *selfpc);
26e3dddf72SSumit Garg */
27e3dddf72SSumit GargFUNC __gnu_mcount_nc, :
28*d6583096SJerome ForissierUNWIND(	.cantunwind)
29e3dddf72SSumit Garg	stmdb		sp!, {r0-r3, lr}
305b1384a0SSumit Garg#if defined(CFG_TA_GPROF_SUPPORT) && !defined(__KERNEL__)
31e3dddf72SSumit Garg	ldr		r0, [sp, #20]		/* lr of instrumented func */
32e3dddf72SSumit Garg	mcount_adj_pc	r0, r0
33e3dddf72SSumit Garg	mcount_adj_pc	r1, lr			/* instrumented func */
34e3dddf72SSumit Garg	bl		__mcount_internal
35e3dddf72SSumit Garg#endif
36099918f6SSumit Garg#ifdef CFG_FTRACE_SUPPORT
37e3dddf72SSumit Garg	/* Get instrumented function's pc value */
38e3dddf72SSumit Garg	ldr		r0, [sp, #16]
39e3dddf72SSumit Garg	mcount_adj_pc	r0, r0
40e3dddf72SSumit Garg	/* Get instrumented function's lr address pointer */
41e3dddf72SSumit Garg	sub		r1, fp, #4
42e3dddf72SSumit Garg	bl		ftrace_enter
43e3dddf72SSumit Garg#endif
44e3dddf72SSumit Garg	ldmia		sp!, {r0-r3, ip, lr}
45e3dddf72SSumit Garg	bx		ip
46e3dddf72SSumit GargEND_FUNC __gnu_mcount_nc
47e3dddf72SSumit Garg
48099918f6SSumit Garg#ifdef CFG_FTRACE_SUPPORT
49e3dddf72SSumit GargFUNC __ftrace_return, :
50e3dddf72SSumit Garg	/* save return value regs */
51e3dddf72SSumit Garg	stmdb		sp!, {r0-r3}
52e3dddf72SSumit Garg
53e3dddf72SSumit Garg	/* get return address of parent func */
54e3dddf72SSumit Garg	bl		ftrace_return
55e3dddf72SSumit Garg	mov		lr, r0
56e3dddf72SSumit Garg
57e3dddf72SSumit Garg	/* restore return value regs */
58e3dddf72SSumit Garg	ldmia		sp!, {r0-r3}
59e3dddf72SSumit Garg	bx		lr
60e3dddf72SSumit GargEND_FUNC __ftrace_return
61e3dddf72SSumit Garg#endif
62e3dddf72SSumit Garg
63099918f6SSumit Garg#endif /* CFG_TA_GPROF_SUPPORT || CFG_FTRACE_SUPPORT */
64