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