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	.section .note.GNU-stack,"",%progbits
11
12/*
13 * Convert return address to call site address by subtracting the size of the
14 * mcount call instruction (blx __gnu_mcount_nc).
15 */
16.macro mcount_adj_pc rd, rn
17	bic	\rd, \rn, #1	/* Clear thumb bit if present */
18	sub	\rd, \rd, #4
19.endm
20
21/*
22 * With the -pg option, GCC (4.4+) inserts a call to __gnu_mcount_nc into
23 * every function prologue.
24 * The caller of the instrumented function can be determined from the lr value
25 * stored on the top of the stack. The callee, i.e. the instrumented function
26 * itself, is determined from the current value of lr. Then we call:
27 *   void __mcount_internal(void *frompc, void *selfpc);
28 */
29FUNC __gnu_mcount_nc, :
30UNWIND(	.cantunwind)
31	stmdb		sp!, {r0-r3, lr}
32#if defined(CFG_TA_GPROF_SUPPORT) && !defined(__KERNEL__)
33	ldr		r0, [sp, #20]		/* lr of instrumented func */
34	mcount_adj_pc	r0, r0
35	mcount_adj_pc	r1, lr			/* instrumented func */
36	bl		__mcount_internal
37#endif
38#ifdef CFG_FTRACE_SUPPORT
39	/* Get instrumented function's pc value */
40	ldr		r0, [sp, #16]
41	mcount_adj_pc	r0, r0
42	/* Get instrumented function's lr address pointer */
43	sub		r1, fp, #4
44	bl		ftrace_enter
45#endif
46	ldmia		sp!, {r0-r3, ip, lr}
47	bx		ip
48END_FUNC __gnu_mcount_nc
49
50#ifdef CFG_FTRACE_SUPPORT
51FUNC __ftrace_return, :
52	/* save return value regs */
53	stmdb		sp!, {r0-r3}
54
55	/* get return address of parent func */
56	bl		ftrace_return
57	mov		lr, r0
58
59	/* restore return value regs */
60	ldmia		sp!, {r0-r3}
61	bx		lr
62END_FUNC __ftrace_return
63#endif
64
65#endif /* CFG_TA_GPROF_SUPPORT || CFG_FTRACE_SUPPORT */
66