From e9a706a4144834a8e50e8dd371bc796cb4fbc854 Mon Sep 17 00:00:00 2001
From: Eric Andersen <andersen@codepoet.org>
Date: Thu, 6 Mar 2003 13:57:31 +0000
Subject: Patch from Stefan Allius to finish off the last required bits for
 gmon profiling support for the SuperH target.

---
 libc/sysdeps/linux/sh/Makefile            |  10 ++-
 libc/sysdeps/linux/sh/bits/machine-gmon.h | 101 ++++++++++++++++++++++--------
 libc/sysdeps/linux/sh/crt0.S              |   8 ++-
 3 files changed, 90 insertions(+), 29 deletions(-)

diff --git a/libc/sysdeps/linux/sh/Makefile b/libc/sysdeps/linux/sh/Makefile
index 425335f7b..9a4560336 100644
--- a/libc/sysdeps/linux/sh/Makefile
+++ b/libc/sysdeps/linux/sh/Makefile
@@ -24,7 +24,8 @@ CFLAGS+= -I../
 SFLAGS= $(CFLAGS) -D__ASSEMBLER__
 
 CRT0_SRC = crt0.S
-CRT0_OBJ = crt0.o crt1.o
+CRT0_OBJ = crt0.o crt1.o gcrt1.o
+CRT0_DEPS=gmon-start.S
 
 SSRC=setjmp.S __longjmp.S vfork.S clone.S
 SOBJS=$(patsubst %.S,%.o, $(SSRC))
@@ -55,6 +56,13 @@ $(COBJS): %.o : %.c
 	$(CC) $(CFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
+ifeq ($(strip $(UCLIBC_PROFILING)),y)
+SAFECFLAGS := $(subst -g,,$(CFLAGS))
+gmon-start.S: ../common/gmon-start.c
+	$(CC) $(SAFECFLAGS) -c $< -S -o $*.S
+gcrt1.o: $(CRT0_DEPS)
+endif
+
 headers:
 
 clean:
diff --git a/libc/sysdeps/linux/sh/bits/machine-gmon.h b/libc/sysdeps/linux/sh/bits/machine-gmon.h
index 46c7b191a..6497859ad 100644
--- a/libc/sysdeps/linux/sh/bits/machine-gmon.h
+++ b/libc/sysdeps/linux/sh/bits/machine-gmon.h
@@ -1,32 +1,83 @@
 /* Machine-dependent definitions for profiling support.  SH version.
-   Copyright (C) 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
+ *
+ * Copyright (C) 2003 Stefan Allius <allius@atecom.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
 
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-/* We must not pollute the global namespace.  */
 #define mcount_internal __mcount_internal
 
-void mcount_internal (u_long frompc, u_long selfpc);
-
 #define _MCOUNT_DECL(frompc, selfpc) \
-void mcount_internal (u_long frompc, u_long selfpc)
-
+static void __attribute__((unused)) mcount_internal (u_long frompc, u_long selfpc)
 
-/* Define MCOUNT as empty since we have the implementation in another
-   file.  */
-#define MCOUNT
+/*
+ * This mcount implementation expect the 'frompc' return address on
+ * the stack and the 'selfpc' return address in register pr.
+ *
+ * Your compiler should include some stuff like this at each function
+ * entry:
+ *
+ *	mov.l	1f,r1
+ *	sts.l	pr,@-r15
+ *	mova	2f,r0
+ *	jmp	@r1
+ *	 lds	r0,pr
+ *	.align	2
+ * 1:	.long	mcount
+ * 2:	lds.l	@r15+,pr
+ *
+ * or for PIC:
+ *
+ *	mov.l	3f,r1
+ *	mova	3f,r0
+ *	add	r1,r0
+ *	mov.l	1f,r1
+ *	mov.l	@(r0,r1),r1
+ *	sts.l	pr,@-r15
+ *	mova	2f,r0
+ *	jmp	@r1
+ *	 lds	r0,pr
+ *	.align	2
+ * 1:	.long	mcount@GOT
+ * 3:	.long	_GLOBAL_OFFSET_TABLE_
+ * 2:	lds.l	@r15+,pr
+ *
+ *
+ * This ABI will be supported by GCC version 3.3 or newer!
+ */
+#define MCOUNT asm(\
+	".align 4\n\t" \
+	".globl _mcount\n\t" \
+	".type _mcount,@function\n" \
+        "_mcount:\n\t" \
+	"mov.l r4,  @-r15\n\t" \
+	"mov.l r5,  @-r15\n\t" \
+	"mov.l r6,  @-r15\n\t" \
+	"mov.l r7,  @-r15\n\t" \
+	"sts.l pr,  @-r15\n\t" \
+	"sts   pr, r5\n\t" \
+	"bsr __mcount_internal\n\t" \
+	" mov.l @(5*4,r15), r4\n\t" \
+	"lds.l @r15+, pr\n\t" \
+	"mov.l @r15+, r7\n\t" \
+	"mov.l @r15+, r6\n\t" \
+	"mov.l @r15+, r5\n\t" \
+	"rts\n\t" \
+	" mov.l @r15+, r4\n\t" \
+	".size _mcount,.-_mcount;\n\t" \
+	".weak mcount;\n\t" \
+	" mcount = _mcount;");
 
diff --git a/libc/sysdeps/linux/sh/crt0.S b/libc/sysdeps/linux/sh/crt0.S
index b6a7e117d..64dd3f493 100644
--- a/libc/sysdeps/linux/sh/crt0.S
+++ b/libc/sysdeps/linux/sh/crt0.S
@@ -76,7 +76,7 @@ _start_end:
 L_main:
 	.long   __uClibc_main /* in libuClibc.*.so */
 
-#else /* L_crt1 && __UCLIBC_CTOR_DTOR__ */
+#else /* (L_crt1 || L_gcrt1) && __UCLIBC_CTOR_DTOR__ */
 	/* Push the finip argument to __uClibc_start_main() onto the stack */
 	mov.l L_fini,r6
 	mov.l r6,@-r15
@@ -113,8 +113,7 @@ _init:
 	rts
 	nop
 
-.Lfe1:
-	.size   _init,.Lfe1-_init
+	.size   _init,.-_init
 	.weak   _fini
 	.set    _fini,_init
 
@@ -128,3 +127,6 @@ L_fini:
 L_abort: 
       .long   abort   
 
+#if defined L_gcrt1 && defined __UCLIBC_PROFILING__
+# include "./gmon-start.S"
+#endif
-- 
cgit v1.2.3