xref: /optee_os/lib/libutils/ext/arch/arm/mcount_a64.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 one
12*e3dddf72SSumit Garg * instruction.
13*e3dddf72SSumit Garg */
14*e3dddf72SSumit Garg.macro adjust_pc rd, rn
15*e3dddf72SSumit Garg	sub	\rd, \rn, #4
16*e3dddf72SSumit Garg.endm
17*e3dddf72SSumit Garg
18*e3dddf72SSumit Garg/* Get instrumented function's pc value */
19*e3dddf72SSumit Garg.macro get_pc reg
20*e3dddf72SSumit Garg	ldr	\reg, [x29, #8]
21*e3dddf72SSumit Garg	sub	\reg, \reg, #4
22*e3dddf72SSumit Garg.endm
23*e3dddf72SSumit Garg
24*e3dddf72SSumit Garg/* Get instrumented function's lr address pointer */
25*e3dddf72SSumit Garg.macro get_lr_addr reg
26*e3dddf72SSumit Garg	ldr	\reg, [x29]
27*e3dddf72SSumit Garg	add	\reg, \reg, #8
28*e3dddf72SSumit Garg.endm
29*e3dddf72SSumit Garg
30*e3dddf72SSumit Garg/*
31*e3dddf72SSumit Garg * void _mcount(void *return_address)
32*e3dddf72SSumit Garg * @return_address: return address to instrumented function
33*e3dddf72SSumit Garg *
34*e3dddf72SSumit Garg * With the -pg option, the compiler inserts a call to _mcount into
35*e3dddf72SSumit Garg * every function prologue.
36*e3dddf72SSumit Garg * x0 contains the value of lr (x30) before the call, that is the return
37*e3dddf72SSumit Garg * address to the caller of the instrumented function. The callee, i.e. the
38*e3dddf72SSumit Garg * instrumented function itself, is determined from the current value of x30.
39*e3dddf72SSumit Garg * Then we call:
40*e3dddf72SSumit Garg *   void __mcount_internal(void *frompc, void *selfpc);
41*e3dddf72SSumit Garg */
42*e3dddf72SSumit GargFUNC _mcount, :
43*e3dddf72SSumit Garg	stp		x29, x30, [sp, #-16]!
44*e3dddf72SSumit Garg	mov		x29, sp
45*e3dddf72SSumit Garg#ifdef CFG_TA_GPROF_SUPPORT
46*e3dddf72SSumit Garg	adjust_pc	x0, x0
47*e3dddf72SSumit Garg	adjust_pc	x1, x30
48*e3dddf72SSumit Garg	bl		__mcount_internal
49*e3dddf72SSumit Garg#endif
50*e3dddf72SSumit Garg#ifdef CFG_TA_FTRACE_SUPPORT
51*e3dddf72SSumit Garg	get_pc		x0
52*e3dddf72SSumit Garg	get_lr_addr	x1
53*e3dddf72SSumit Garg	bl		ftrace_enter
54*e3dddf72SSumit Garg#endif
55*e3dddf72SSumit Garg	ldp		x29, x30, [sp], #16
56*e3dddf72SSumit Garg	ret
57*e3dddf72SSumit GargEND_FUNC _mcount
58*e3dddf72SSumit Garg
59*e3dddf72SSumit Garg#ifdef CFG_TA_FTRACE_SUPPORT
60*e3dddf72SSumit GargFUNC __ftrace_return, :
61*e3dddf72SSumit Garg	/* Save return value regs */
62*e3dddf72SSumit Garg	sub		sp, sp, #64
63*e3dddf72SSumit Garg	stp		x0, x1, [sp]
64*e3dddf72SSumit Garg	stp		x2, x3, [sp, #16]
65*e3dddf72SSumit Garg	stp		x4, x5, [sp, #32]
66*e3dddf72SSumit Garg	stp		x6, x7, [sp, #48]
67*e3dddf72SSumit Garg
68*e3dddf72SSumit Garg	/* Get return address of parent func */
69*e3dddf72SSumit Garg	bl		ftrace_return
70*e3dddf72SSumit Garg	mov		x30, x0
71*e3dddf72SSumit Garg
72*e3dddf72SSumit Garg	/* Restore return value regs */
73*e3dddf72SSumit Garg	ldp		x0, x1, [sp]
74*e3dddf72SSumit Garg	ldp		x2, x3, [sp, #16]
75*e3dddf72SSumit Garg	ldp		x4, x5, [sp, #32]
76*e3dddf72SSumit Garg	ldp		x6, x7, [sp, #48]
77*e3dddf72SSumit Garg	add		sp, sp, #64
78*e3dddf72SSumit Garg
79*e3dddf72SSumit Garg	ret
80*e3dddf72SSumit GargEND_FUNC __ftrace_return
81*e3dddf72SSumit Garg#endif
82*e3dddf72SSumit Garg
83*e3dddf72SSumit Garg#endif /* CFG_TA_GPROF_SUPPORT || CFG_TA_FTRACE_SUPPORT */
84