1e3dddf72SSumit Garg/* SPDX-License-Identifier: BSD-2-Clause */ 2e3dddf72SSumit Garg/* 3e3dddf72SSumit Garg * Copyright (c) 2016, Linaro Limited 4e3dddf72SSumit Garg */ 5e3dddf72SSumit Garg 6e3dddf72SSumit Garg#include <asm.S> 7e3dddf72SSumit Garg 8*099918f6SSumit Garg#if defined(CFG_TA_GPROF_SUPPORT) || defined(CFG_FTRACE_SUPPORT) 9e3dddf72SSumit Garg 10e3dddf72SSumit Garg/* 11e3dddf72SSumit Garg * Convert return address to call site address by subtracting the size of the 12e3dddf72SSumit Garg * mcount call instruction (blx __gnu_mcount_nc). 13e3dddf72SSumit Garg */ 14e3dddf72SSumit Garg.macro mcount_adj_pc rd, rn 15e3dddf72SSumit Garg bic \rd, \rn, #1 /* Clear thumb bit if present */ 16e3dddf72SSumit Garg sub \rd, \rd, #4 17e3dddf72SSumit Garg.endm 18e3dddf72SSumit Garg 19e3dddf72SSumit Garg/* 20e3dddf72SSumit Garg * With the -pg option, GCC (4.4+) inserts a call to __gnu_mcount_nc into 21e3dddf72SSumit Garg * every function prologue. 22e3dddf72SSumit Garg * The caller of the instrumented function can be determined from the lr value 23e3dddf72SSumit Garg * stored on the top of the stack. The callee, i.e. the instrumented function 24e3dddf72SSumit Garg * itself, is determined from the current value of lr. Then we call: 25e3dddf72SSumit Garg * void __mcount_internal(void *frompc, void *selfpc); 26e3dddf72SSumit Garg */ 27e3dddf72SSumit GargFUNC __gnu_mcount_nc, : 28e3dddf72SSumit Garg stmdb sp!, {r0-r3, lr} 295b1384a0SSumit Garg#if defined(CFG_TA_GPROF_SUPPORT) && !defined(__KERNEL__) 30e3dddf72SSumit Garg ldr r0, [sp, #20] /* lr of instrumented func */ 31e3dddf72SSumit Garg mcount_adj_pc r0, r0 32e3dddf72SSumit Garg mcount_adj_pc r1, lr /* instrumented func */ 33e3dddf72SSumit Garg bl __mcount_internal 34e3dddf72SSumit Garg#endif 35*099918f6SSumit Garg#ifdef CFG_FTRACE_SUPPORT 36e3dddf72SSumit Garg /* Get instrumented function's pc value */ 37e3dddf72SSumit Garg ldr r0, [sp, #16] 38e3dddf72SSumit Garg mcount_adj_pc r0, r0 39e3dddf72SSumit Garg /* Get instrumented function's lr address pointer */ 40e3dddf72SSumit Garg sub r1, fp, #4 41e3dddf72SSumit Garg bl ftrace_enter 42e3dddf72SSumit Garg#endif 43e3dddf72SSumit Garg ldmia sp!, {r0-r3, ip, lr} 44e3dddf72SSumit Garg bx ip 45e3dddf72SSumit GargEND_FUNC __gnu_mcount_nc 46e3dddf72SSumit Garg 47*099918f6SSumit Garg#ifdef CFG_FTRACE_SUPPORT 48e3dddf72SSumit GargFUNC __ftrace_return, : 49e3dddf72SSumit Garg /* save return value regs */ 50e3dddf72SSumit Garg stmdb sp!, {r0-r3} 51e3dddf72SSumit Garg 52e3dddf72SSumit Garg /* get return address of parent func */ 53e3dddf72SSumit Garg bl ftrace_return 54e3dddf72SSumit Garg mov lr, r0 55e3dddf72SSumit Garg 56e3dddf72SSumit Garg /* restore return value regs */ 57e3dddf72SSumit Garg ldmia sp!, {r0-r3} 58e3dddf72SSumit Garg bx lr 59e3dddf72SSumit GargEND_FUNC __ftrace_return 60e3dddf72SSumit Garg#endif 61e3dddf72SSumit Garg 62*099918f6SSumit Garg#endif /* CFG_TA_GPROF_SUPPORT || CFG_FTRACE_SUPPORT */ 63