diff options
author | grehan <grehan@FreeBSD.org> | 2005-12-29 04:07:36 +0000 |
---|---|---|
committer | grehan <grehan@FreeBSD.org> | 2005-12-29 04:07:36 +0000 |
commit | 50e5f6dc9b9bb159769fc3e1ece08c3b81acbc9f (patch) | |
tree | 57a4b9a262faa6fa7fc998edefcd9c2a3b02415b /sys/powerpc/include | |
parent | 574cde8a07bbbad7d5607e1774fe51dc682cc5b2 (diff) | |
download | FreeBSD-src-50e5f6dc9b9bb159769fc3e1ece08c3b81acbc9f.zip FreeBSD-src-50e5f6dc9b9bb159769fc3e1ece08c3b81acbc9f.tar.gz |
Add user-space profiling support. Kernel profiling still todo.
Obtained from: NetBSD
Diffstat (limited to 'sys/powerpc/include')
-rw-r--r-- | sys/powerpc/include/profile.h | 90 |
1 files changed, 82 insertions, 8 deletions
diff --git a/sys/powerpc/include/profile.h b/sys/powerpc/include/profile.h index a592bcd..96f3825 100644 --- a/sys/powerpc/include/profile.h +++ b/sys/powerpc/include/profile.h @@ -32,22 +32,96 @@ #ifndef _MACHINE_PROFILE_H_ #define _MACHINE_PROFILE_H_ -#define _MCOUNT_DECL void mcount +#define _MCOUNT_DECL void __mcount #define FUNCTION_ALIGNMENT 16 typedef u_int fptrdiff_t; +/* + * The mcount trampoline macro, expanded in libc/gmon/mcount.c + * + * For PowerPC SVR4 ABI profiling, the compiler will insert + * a data declaration and code sequence at the start of a routine of the form + * + * .function_mc: .data + * .align 2 + * .long 0 + * .text + * + * function: mflr %r0 + * addis %r11,%r0, .function_mc@ha + * stw %r0,4(%r1) + * addi %r0,%r11, .function_mc@l + * bl _mcount + * + * The link register is saved in the LR save word in the caller's + * stack frame, r0 is set up to point to the allocated longword, + * and control is transferred to _mcount. + * + * On return from _mcount, the routine should function as it would + * with no profiling so _mcount must restore register state to that upon + * entry. Any routine called by the _mcount trampoline will save + * callee-save registers, so _mcount must make sure it saves volatile + * registers that may have state after it returns i.e. parameter registers. + * + * The FreeBSD libc mcount routine ignores the r0 longword pointer, but + * instead requires as parameters the current PC and called PC. The current + * PC is obtained from the link register, as a result of "bl _mcount" in + * the stub, while the caller's PC is obtained from the LR save word. + * + * On return from libc mcount, the return is done indirectly with the + * ctr register rather than the link register, to allow the link register + * to be restored to what it was on entry to the profiled routine. + */ + +#ifdef PIC +#define _PLT "@plt" +#else +#define _PLT +#endif + #define MCOUNT \ -void \ -_mcount() \ -{ \ -} +__asm(" .globl _mcount \n" \ +" .type _mcount,@function \n" \ +"_mcount: \n" \ +" stwu %r1,-64(%r1) /* alloca for reg save space */ \n" \ +" stw %r3,16(%r1) /* save parameter registers, */ \n" \ +" stw %r4,20(%r1) /* r3-10 */ \n" \ +" stw %r5,24(%r1) \n" \ +" stw %r6,28(%r1) \n" \ +" stw %r7,32(%r1) \n" \ +" stw %r8,36(%r1) \n" \ +" stw %r9,40(%r1) \n" \ +" stw %r10,44(%r1) \n" \ +" \n" \ +" mflr %r4 /* link register is 'selfpc' */ \n" \ +" stw %r4,48(%r1) /* save since bl will scrub */ \n" \ +" lwz %r3,68(%r1) /* get 'frompc' from LR-save */ \n" \ +" bl __mcount" _PLT " /* __mcount(frompc, selfpc)*/ \n" \ +" lwz %r3,68(%r1) \n" \ +" mtlr %r3 /* restore caller's lr */ \n" \ +" lwz %r4,48(%r1) \n" \ +" mtctr %r4 /* set up ctr for call back */ \n" \ +" /* note that blr is not used!*/ \n" \ +" lwz %r3,16(%r1) /* restore r3-10 parameters */ \n" \ +" lwz %r4,20(%r1) \n" \ +" lwz %r5,24(%r1) \n" \ +" lwz %r6,28(%r1) \n" \ +" lwz %r7,32(%r1) \n" \ +" lwz %r8,36(%r1) \n" \ +" lwz %r9,40(%r1) \n" \ +" lwz %r10,44(%r1) \n" \ +" addi %r1,%r1,64 /* blow away alloca save area */ \n" \ +" bctr /* return with indirect call */ \n" \ +"_mcount_end: \n" \ +" .size _mcount,_mcount_end-_mcount"); + #ifdef _KERNEL -#define MCOUNT_ENTER(s) -#define MCOUNT_EXIT(s) -#define MCOUNT_DECL(s) +#define MCOUNT_ENTER(s) s = intr_disable(); +#define MCOUNT_EXIT(s) intr_restore(s); +#define MCOUNT_DECL(s) register_t s void bintr(void); void btrap(void); |