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