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