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