about summary refs log tree commit diff
path: root/sysdeps/unix/sysv/linux/sparc/sparc32/init-first.h
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux/sparc/sparc32/init-first.h')
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc32/init-first.h98
1 files changed, 71 insertions, 27 deletions
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/init-first.h b/sysdeps/unix/sysv/linux/sparc/sparc32/init-first.h
index 39822fc595..9bbe6bcdab 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/init-first.h
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/init-first.h
@@ -21,32 +21,76 @@
    This is done in one of two ways: either in the stack context
    of program start, or having dlopen pass them in.  */
 
-#define SYSDEP_CALL_INIT(NAME, INIT)					      \
-void NAME (void *arg)							      \
-{									      \
-  int argc;								      \
-  char **argv, **envp;							      \
-  /* The next variable is only here to work around a bug in gcc <= 2.7.2.2.   \
-     If the address would be taken inside the expression the optimizer	      \
-     would try to be too smart and throws it away.  Grrr.  */		      \
-  int *dummy_addr = &_dl_starting_up;					      \
-									      \
-  __libc_multiple_libcs = dummy_addr && !_dl_starting_up;		      \
-									      \
-  if (!__libc_multiple_libcs)						      \
-    {									      \
-      argc = *(int *) arg;						      \
-      argv = (char **) (arg + 4);					      \
-      envp = &argv[argc+1];						      \
-    }									      \
-  else									      \
-    {									      \
-      argc = (int) arg;							      \
-      argv = ((char ***) &arg)[1];					      \
-      envp = ((char ***) &arg)[2];					      \
-    }									      \
-									      \
-  INIT (argc, argv, envp);						      \
-}
+#include <sysdep.h>
 
+#define __S1(x) #x
+#define __S(x) __S1(x)
 
+#ifdef PIC
+
+#define SYSDEP_CALL_INIT(NAME, INIT) asm("\
+	.weak _dl_starting_up
+	.global " #NAME "
+	.type " #NAME ",@function
+" #NAME ":
+	save	%sp, -64, %sp
+1:	call	11f
+	sethi	%hi(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7
+11:	or	%l7, %lo(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7
+	add	%l7, %o7, %l7
+	/* Are we a dynamic libc being loaded into a static program?  */
+	sethi	%hi(_dl_starting_up), %l2
+	or	%l2, %lo(_dl_starting_up), %l2
+	ld	[%l7+%l2], %l2
+	cmp	%l2, 0
+	beq	3f
+	 sethi	%hi(__libc_multiple_libcs), %l3
+	ld	[%l2], %l2
+	subcc	%g0, %l2, %g0
+	subx	%g0, -1, %l2
+3:	or	%l3, %lo(__libc_multiple_libcs), %l3
+	ld	[%l7+%l3], %l3
+	cmp	%l2, 0
+	st	%l2, [%l3]
+	/* If so, argc et al are in %o0-%o2 already.  Otherwise, load them.  */
+	bnz	" #INIT "
+	 restore
+	ld	[%sp+22*4], %o0
+	add	%sp, 23*4, %o1
+	sll	%o0, 2, %o2
+	add	%o2, %o1, %o2
+	ba	" #INIT "
+	 add	%o2, 4, %o2
+	.size "#NAME ", .-" #NAME);
+
+#else
+
+#define SYSDEP_CALL_INIT(NAME, INIT) asm("\
+	.weak _dl_starting_up
+	.global " #NAME "
+	.type " #NAME ",@function
+" #NAME ":
+	/* Are we a dynamic libc being loaded into a static program?  */
+	sethi	%hi(_dl_starting_up), %g2
+	or	%g2, %lo(_dl_starting_up), %g2
+	cmp	%g2, 0
+	beq	3f
+	 sethi	%hi(__libc_multiple_libcs), %g3
+	ld	[%g4+%g2], %g2
+	subcc	%g0, %g2, %g0
+	subx	%g0, -1, %g2
+3:	or	%g3, %lo(__libc_multiple_libcs), %g3
+	cmp	%g2, 0
+	st	%g2, [%g3+%g4]
+	/* If so, argc et al are in %o0-%o2 already.  Otherwise, load them.  */
+	bnz	" #INIT "
+	 nop
+	ld	[%sp+22*4], %o0
+	add	%sp, 23*4, %o1
+	sll	%o0, 2, %o2
+	add	%o2, %o1, %o2
+	ba	" #INIT "
+	 add	%o2, 4, %o2
+	.size "#NAME ", .-" #NAME);
+
+#endif