about summary refs log tree commit diff
path: root/sysdeps/alpha/_mcount.S
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/alpha/_mcount.S')
-rw-r--r--sysdeps/alpha/_mcount.S112
1 files changed, 112 insertions, 0 deletions
diff --git a/sysdeps/alpha/_mcount.S b/sysdeps/alpha/_mcount.S
new file mode 100644
index 0000000000..2d6e2ed532
--- /dev/null
+++ b/sysdeps/alpha/_mcount.S
@@ -0,0 +1,112 @@
+/* Machine-specific calling sequence for `mcount' profiling function.  alpha
+Copyright (C) 1995 Free Software Foundation, Inc.
+Contributed by David Mosberger (davidm@cs.arizona.edu).
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+/* Assembly stub to invoke _mcount().  Compiler generated code calls
+this stub after executing a function's prologue and without saving any
+registers.  It is therefore necessary to preserve a0..a5 as they may
+contain function arguments.  To work correctly with frame- less
+functions, it is also necessary to preserve ra.  Finally, division
+routines are invoked with a special calling convention and the
+compiler treats those calls as if they were instructions.  In
+particular, it doesn't save any of the temporary registers (caller
+saved registers).  It is therefore necessary to preserve all
+caller-saved registers as well
+ 
+Upon entering _mcount, register $at holds the return address and ra
+holds the return address of the function's caller (selfpc and frompc,
+respectively in gmon.c language...). */
+
+#include <sysdep.h>
+#ifdef __linux__
+# include <alpha/regdef.h>
+#else
+# include <regdef.h>
+#endif
+
+#undef ret	/* discard `ret' as defined in sysdep.h */
+
+	.set	noat
+	.set	noreorder
+
+ENTRY(_mcount)
+	subq	 sp, 0xb0, sp
+	stq	 a0, 0x00(sp)
+	mov	 ra, a0		# a0 = caller-pc
+	stq	 a1, 0x08(sp)
+	mov	$at, a1		# a1 = self-pc
+	stq	$at, 0x10(sp)
+
+	stq	 a2, 0x18(sp)
+	stq	 a3, 0x20(sp)
+	stq	 a4, 0x28(sp)
+	stq	 a5, 0x30(sp)
+	stq	 ra, 0x38(sp)
+	stq	 gp, 0x40(sp)
+
+	br	gp, 1f
+1:	ldgp	gp, 0(gp)
+
+	stq	 t0, 0x48(sp)
+	stq	 t1, 0x50(sp)
+	stq	 t2, 0x58(sp)
+	stq	 t3, 0x60(sp)
+	stq	 t4, 0x68(sp)
+	stq	 t5, 0x70(sp)
+	stq	 t6, 0x78(sp)
+
+	lda	 pv, __mcount
+
+	stq	 t7, 0x80(sp)
+	stq	 t8, 0x88(sp)
+	stq	 t9, 0x90(sp)
+	stq	t10, 0x98(sp)
+	stq	t11, 0xa0(sp)
+	stq	 v0, 0xa8(sp)
+
+	jsr	ra, (pv), __mcount
+
+	ldq	 a0, 0x00(sp)
+	ldq	 a1, 0x08(sp)
+	ldq	$at, 0x10(sp)	# restore self-pc
+	ldq	 a2, 0x18(sp)
+	ldq	 a3, 0x20(sp)
+	ldq	 a4, 0x28(sp)
+	ldq	 a5, 0x30(sp)
+	ldq	 ra, 0x38(sp)
+	ldq	 gp, 0x40(sp)
+	mov	$at, pv		# make pv point to return address
+	ldq	 t0, 0x48(sp)	# this is important under OSF/1 to
+	ldq	 t1, 0x50(sp)	# ensure that the code that we return
+	ldq	 t2, 0x58(sp)	# can correctly compute its gp
+	ldq	 t3, 0x60(sp)
+	ldq	 t4, 0x68(sp)
+	ldq	 t5, 0x70(sp)
+	ldq	 t6, 0x78(sp)
+	ldq	 t7, 0x80(sp)
+	ldq	 t8, 0x88(sp)
+	ldq	 t9, 0x90(sp)
+	ldq	t10, 0x98(sp)
+	ldq	t11, 0xa0(sp)
+	ldq	 v0, 0xa8(sp)
+
+	addq	sp, 0xb0, sp
+	ret	zero,($at),1
+
+	.end _mcount