xref: /optee_os/lib/libutils/ext/arch/riscv/mcount_rv.S (revision ae9b3ff90d77e8ccce1c7404dfada381d60a6fc4)
1*ae9b3ff9SAlvin Chang/* SPDX-License-Identifier: BSD-2-Clause */
2*ae9b3ff9SAlvin Chang/*
3*ae9b3ff9SAlvin Chang * Copyright (c) 2023 Andes Technology Corporation
4*ae9b3ff9SAlvin Chang * Copyright (c) 2016, Linaro Limited
5*ae9b3ff9SAlvin Chang */
6*ae9b3ff9SAlvin Chang
7*ae9b3ff9SAlvin Chang#include <asm.S>
8*ae9b3ff9SAlvin Chang
9*ae9b3ff9SAlvin Chang#if defined(CFG_FTRACE_SUPPORT)
10*ae9b3ff9SAlvin Chang
11*ae9b3ff9SAlvin Chang/*
12*ae9b3ff9SAlvin Chang * Convert return address to call site address by subtracting the size of one
13*ae9b3ff9SAlvin Chang * instruction.
14*ae9b3ff9SAlvin Chang */
15*ae9b3ff9SAlvin Chang.macro adjust_pc rd, rn
16*ae9b3ff9SAlvin Chang	addi	\rd, \rn, -4
17*ae9b3ff9SAlvin Chang.endm
18*ae9b3ff9SAlvin Chang
19*ae9b3ff9SAlvin Chang#ifdef RV32
20*ae9b3ff9SAlvin Chang
21*ae9b3ff9SAlvin Chang/* Get instrumented function's pc value */
22*ae9b3ff9SAlvin Chang.macro get_pc reg
23*ae9b3ff9SAlvin Chang	LDR	\reg, REGOFF(3)(sp)
24*ae9b3ff9SAlvin Chang	addi	\reg, \reg, -4
25*ae9b3ff9SAlvin Chang.endm
26*ae9b3ff9SAlvin Chang
27*ae9b3ff9SAlvin Chang/* Get instrumented function's ra address pointer */
28*ae9b3ff9SAlvin Chang.macro get_ra_addr reg
29*ae9b3ff9SAlvin Chang	LDR	\reg, REGOFF(2)(sp)
30*ae9b3ff9SAlvin Chang	addi	\reg, \reg, -4
31*ae9b3ff9SAlvin Chang.endm
32*ae9b3ff9SAlvin Chang
33*ae9b3ff9SAlvin Chang#else	/* RV64 */
34*ae9b3ff9SAlvin Chang
35*ae9b3ff9SAlvin Chang/* Get instrumented function's pc value */
36*ae9b3ff9SAlvin Chang.macro get_pc reg
37*ae9b3ff9SAlvin Chang	LDR	\reg, REGOFF(1)(sp)
38*ae9b3ff9SAlvin Chang	addi	\reg, \reg, -4
39*ae9b3ff9SAlvin Chang.endm
40*ae9b3ff9SAlvin Chang
41*ae9b3ff9SAlvin Chang/* Get instrumented function's ra address pointer */
42*ae9b3ff9SAlvin Chang.macro get_ra_addr reg
43*ae9b3ff9SAlvin Chang	LDR	\reg, REGOFF(0)(sp)
44*ae9b3ff9SAlvin Chang	addi	\reg, \reg, -8
45*ae9b3ff9SAlvin Chang.endm
46*ae9b3ff9SAlvin Chang
47*ae9b3ff9SAlvin Chang#endif	/* RV32 */
48*ae9b3ff9SAlvin Chang
49*ae9b3ff9SAlvin Chang/*
50*ae9b3ff9SAlvin Chang * void _mcount(void *return_address)
51*ae9b3ff9SAlvin Chang * @return_address: return address to instrumented function
52*ae9b3ff9SAlvin Chang *
53*ae9b3ff9SAlvin Chang * With the -pg option, the compiler inserts a call to _mcount into
54*ae9b3ff9SAlvin Chang * every function prologue.
55*ae9b3ff9SAlvin Chang * a0 contains the value of ra before the call, that is the return
56*ae9b3ff9SAlvin Chang * address to the caller of the instrumented function. The callee, i.e. the
57*ae9b3ff9SAlvin Chang * instrumented function itself, is determined from the current value of ra.
58*ae9b3ff9SAlvin Chang * Then we call:
59*ae9b3ff9SAlvin Chang *   void __mcount_internal(void *frompc, void *selfpc);
60*ae9b3ff9SAlvin Chang */
61*ae9b3ff9SAlvin ChangFUNC _mcount, :
62*ae9b3ff9SAlvin Chang	addi		sp, sp, -16
63*ae9b3ff9SAlvin Chang	/* Save ra and s0(fp) onto stack */
64*ae9b3ff9SAlvin Chang#ifdef RV32
65*ae9b3ff9SAlvin Chang	STR		ra, REGOFF(3)(sp)
66*ae9b3ff9SAlvin Chang	STR		s0, REGOFF(2)(sp)
67*ae9b3ff9SAlvin Chang#else
68*ae9b3ff9SAlvin Chang	STR		ra, REGOFF(1)(sp)
69*ae9b3ff9SAlvin Chang	STR		s0, REGOFF(0)(sp)
70*ae9b3ff9SAlvin Chang#endif
71*ae9b3ff9SAlvin Chang	/* Setup frame pointer */
72*ae9b3ff9SAlvin Chang	addi		s0, sp, 16
73*ae9b3ff9SAlvin Chang#ifdef CFG_FTRACE_SUPPORT
74*ae9b3ff9SAlvin Chang	get_pc		a0
75*ae9b3ff9SAlvin Chang	get_ra_addr	a1
76*ae9b3ff9SAlvin Chang	call		ftrace_enter
77*ae9b3ff9SAlvin Chang#endif
78*ae9b3ff9SAlvin Chang	/* Restore ra and s0(fp) from stack */
79*ae9b3ff9SAlvin Chang#ifdef RV32
80*ae9b3ff9SAlvin Chang	LDR		s0, REGOFF(2)(sp)
81*ae9b3ff9SAlvin Chang	LDR		ra, REGOFF(3)(sp)
82*ae9b3ff9SAlvin Chang#else
83*ae9b3ff9SAlvin Chang	LDR		s0, REGOFF(0)(sp)
84*ae9b3ff9SAlvin Chang	LDR		ra, REGOFF(1)(sp)
85*ae9b3ff9SAlvin Chang#endif
86*ae9b3ff9SAlvin Chang	addi		sp, sp, 16
87*ae9b3ff9SAlvin Chang	ret
88*ae9b3ff9SAlvin ChangEND_FUNC _mcount
89*ae9b3ff9SAlvin Chang
90*ae9b3ff9SAlvin Chang#ifdef CFG_FTRACE_SUPPORT
91*ae9b3ff9SAlvin ChangFUNC __ftrace_return, :
92*ae9b3ff9SAlvin Chang	/* Save return value regs */
93*ae9b3ff9SAlvin Chang	addi		sp, sp, -REGOFF(8)
94*ae9b3ff9SAlvin Chang	STR		a0, REGOFF(0)(sp)
95*ae9b3ff9SAlvin Chang	STR		a1, REGOFF(1)(sp)
96*ae9b3ff9SAlvin Chang	STR		a2, REGOFF(2)(sp)
97*ae9b3ff9SAlvin Chang	STR		a3, REGOFF(3)(sp)
98*ae9b3ff9SAlvin Chang	STR		a4, REGOFF(4)(sp)
99*ae9b3ff9SAlvin Chang	STR		a5, REGOFF(5)(sp)
100*ae9b3ff9SAlvin Chang	STR		a6, REGOFF(6)(sp)
101*ae9b3ff9SAlvin Chang	STR		a7, REGOFF(7)(sp)
102*ae9b3ff9SAlvin Chang
103*ae9b3ff9SAlvin Chang	/* Get return address of parent func */
104*ae9b3ff9SAlvin Chang	call		ftrace_return
105*ae9b3ff9SAlvin Chang	mv		ra, a0
106*ae9b3ff9SAlvin Chang
107*ae9b3ff9SAlvin Chang	/* Restore return value regs */
108*ae9b3ff9SAlvin Chang	LDR		a0, REGOFF(0)(sp)
109*ae9b3ff9SAlvin Chang	LDR		a1, REGOFF(1)(sp)
110*ae9b3ff9SAlvin Chang	LDR		a2, REGOFF(2)(sp)
111*ae9b3ff9SAlvin Chang	LDR		a3, REGOFF(3)(sp)
112*ae9b3ff9SAlvin Chang	LDR		a4, REGOFF(4)(sp)
113*ae9b3ff9SAlvin Chang	LDR		a5, REGOFF(5)(sp)
114*ae9b3ff9SAlvin Chang	LDR		a6, REGOFF(6)(sp)
115*ae9b3ff9SAlvin Chang	LDR		a7, REGOFF(7)(sp)
116*ae9b3ff9SAlvin Chang	addi		sp, sp, REGOFF(8)
117*ae9b3ff9SAlvin Chang
118*ae9b3ff9SAlvin Chang	ret
119*ae9b3ff9SAlvin ChangEND_FUNC __ftrace_return
120*ae9b3ff9SAlvin Chang#endif
121*ae9b3ff9SAlvin Chang
122*ae9b3ff9SAlvin Chang#endif /* CFG_FTRACE_SUPPORT */
123