xref: /optee_os/lib/libutils/ext/arch/arm/mcount_a32.S (revision 099918f6744c37ce693c38562f11466b19d573c9)
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
8*099918f6SSumit 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, :
28e3dddf72SSumit Garg	stmdb		sp!, {r0-r3, lr}
295b1384a0SSumit Garg#if defined(CFG_TA_GPROF_SUPPORT) && !defined(__KERNEL__)
30e3dddf72SSumit Garg	ldr		r0, [sp, #20]		/* lr of instrumented func */
31e3dddf72SSumit Garg	mcount_adj_pc	r0, r0
32e3dddf72SSumit Garg	mcount_adj_pc	r1, lr			/* instrumented func */
33e3dddf72SSumit Garg	bl		__mcount_internal
34e3dddf72SSumit Garg#endif
35*099918f6SSumit Garg#ifdef CFG_FTRACE_SUPPORT
36e3dddf72SSumit Garg	/* Get instrumented function's pc value */
37e3dddf72SSumit Garg	ldr		r0, [sp, #16]
38e3dddf72SSumit Garg	mcount_adj_pc	r0, r0
39e3dddf72SSumit Garg	/* Get instrumented function's lr address pointer */
40e3dddf72SSumit Garg	sub		r1, fp, #4
41e3dddf72SSumit Garg	bl		ftrace_enter
42e3dddf72SSumit Garg#endif
43e3dddf72SSumit Garg	ldmia		sp!, {r0-r3, ip, lr}
44e3dddf72SSumit Garg	bx		ip
45e3dddf72SSumit GargEND_FUNC __gnu_mcount_nc
46e3dddf72SSumit Garg
47*099918f6SSumit Garg#ifdef CFG_FTRACE_SUPPORT
48e3dddf72SSumit GargFUNC __ftrace_return, :
49e3dddf72SSumit Garg	/* save return value regs */
50e3dddf72SSumit Garg	stmdb		sp!, {r0-r3}
51e3dddf72SSumit Garg
52e3dddf72SSumit Garg	/* get return address of parent func */
53e3dddf72SSumit Garg	bl		ftrace_return
54e3dddf72SSumit Garg	mov		lr, r0
55e3dddf72SSumit Garg
56e3dddf72SSumit Garg	/* restore return value regs */
57e3dddf72SSumit Garg	ldmia		sp!, {r0-r3}
58e3dddf72SSumit Garg	bx		lr
59e3dddf72SSumit GargEND_FUNC __ftrace_return
60e3dddf72SSumit Garg#endif
61e3dddf72SSumit Garg
62*099918f6SSumit Garg#endif /* CFG_TA_GPROF_SUPPORT || CFG_FTRACE_SUPPORT */
63