summaryrefslogtreecommitdiffstats
path: root/sys/amd64/include/profile.h
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2004-05-18 22:52:32 +0000
committerpeter <peter@FreeBSD.org>2004-05-18 22:52:32 +0000
commit18fd75c1c371953001b5be8d1fd8595ecb338926 (patch)
treea32a388f531785ccea2973444a903c1e481bfa7b /sys/amd64/include/profile.h
parent0c866f61b2570835ad15e1e36239b7c9f6e2ba16 (diff)
downloadFreeBSD-src-18fd75c1c371953001b5be8d1fd8595ecb338926.zip
FreeBSD-src-18fd75c1c371953001b5be8d1fd8595ecb338926.tar.gz
The 'call mcount' hooks that gcc inserts when profiling are in a place that
cannot handle the scratch registers being trashed. So we have to preserve them ourselves.
Diffstat (limited to 'sys/amd64/include/profile.h')
-rw-r--r--sys/amd64/include/profile.h39
1 files changed, 37 insertions, 2 deletions
diff --git a/sys/amd64/include/profile.h b/sys/amd64/include/profile.h
index 7085547..6e2ffb9 100644
--- a/sys/amd64/include/profile.h
+++ b/sys/amd64/include/profile.h
@@ -76,9 +76,43 @@ extern int mcount_lock;
#define FUNCTION_ALIGNMENT 4
-#define _MCOUNT_DECL static __inline void _mcount
+#define _MCOUNT_DECL \
+static void _mcount(uintfptr_t frompc, uintfptr_t selfpc) __unused; \
+static void _mcount
#ifdef __GNUC__
+#define MCOUNT __asm (" \n\
+ .globl .mcount \n\
+ .type .mcount @function \n\
+.mcount: \n\
+ pushq %rbp \n\
+ movq %rsp, %rbp \n\
+ pushq %rdi \n\
+ pushq %rsi \n\
+ pushq %rdx \n\
+ pushq %rcx \n\
+ pushq %r8 \n\
+ pushq %r9 \n\
+ movq 8(%rbp),%rsi \n\
+ movq (%rbp),%rdi \n\
+ movq 8(%rdi),%rdi \n\
+ call _mcount \n\
+ popq %r9 \n\
+ popq %r8 \n\
+ popq %rcx \n\
+ popq %rdx \n\
+ popq %rsi \n\
+ popq %rdi \n\
+ leave \n\
+ ret \n\
+ .size .mcount, . - .mcount");
+#if 0
+/*
+ * We could use this, except it doesn't preserve the registers that were
+ * being passed with arguments to the function that we were inserted
+ * into. I've left it here as documentation of what the code above is
+ * supposed to do.
+ */
#define MCOUNT \
void \
mcount() \
@@ -97,10 +131,11 @@ mcount() \
* the caller's frame pointer. The caller's raddr is in the \
* caller's frame following the caller's caller's frame pointer.\
*/ \
- __asm("movq (%%rbp),%0" : "=r" (frompc)); \
+ __asm("movq (%%rbp),%0" : "=r" (frompc)); \
frompc = ((uintfptr_t *)frompc)[1]; \
_mcount(frompc, selfpc); \
}
+#endif
#else /* __GNUC__ */
#define MCOUNT \
void \
OpenPOWER on IntegriCloud