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