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