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