summary refs log tree commit diff
path: root/sysdeps/sparc64/elf/start.S
blob: 334f85b1293ce0600bf4fcb8052838a2858663e9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/* Startup code for elf64-sparc
   Copyright (C) 1997 Free Software Foundation, Inc.
   Contributed by Richard Henderson <richard@gnu.ai.mit.edu>, 1997.

   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.  */

#include <sysdep.h>


	.section ".text"
	.align 4
	.global _start
	.type _start,#function
_start:

  /* First order of business is to load %g4 with our base address.  */
	sethi	%uhi(_start), %g4
	or	%g4, %ulo(_start), %g4
	sllx	%g4, 32, %g4

  /* Terminate the stack frame, and reserve space for functions to
     drop their arguments.  */
	mov	%g0, %fp
	sub	%sp, 6*8, %sp

  /* Save %g1.  When starting a binary via the dynamic linker, %g1
     contains the address of the shared library termination function,
     which we will register below with atexit() to be called by exit().
     If we are statically linked, this will be NULL.  */

  /* Do essential libc initialization (sp points to argc, argv, and envp)  */
	call	__libc_init_first
	 mov	%g1, %l0

  /* Now that we have the proper stack frame, register library termination
     function, if there is any:  */

	brz,pn	%l0, 1f
	 nop
	call	atexit
	 mov	%l0, %o0
1:

  /* Extract the arguments and environment as encoded on the stack.  The
     argument info starts after one register window (16 words) past the SP,
     plus the bias we added, plus the magic v9 STACK_BIAS.  */
	ldx	[%sp+STACK_BIAS+22*8], %o0
	add	%sp, STACK_BIAS+23*8, %o1
	sllx	%o0, 3, %o2
	add	%o2, %o1, %o2
	sethi	%hi(__environ), %g2
	add	%o2, 8, %o2
	add	%g2, %g4, %g2
	stx	%o2, [%g2+%lo(__environ)]

	mov	%o0, %l0		/* tuck them away */
	mov	%o1, %l1

  /* Call _init, the entry point to our own .init section.  */
	call	_init
	 mov	%o2, %l2

  /* Register our .fini section with atexit.  */
	sethi	%hi(_fini), %o0
	add	%o0, %g4, %o0
	call	atexit
	 add	%o0, %lo(_fini), %o0

  /* Call the user's main and exit with its return value.  */
	mov	%l0, %o0
	mov	%l1, %o1
	call	main
	 mov	%l2, %o2
	call	exit
	 nop

  /* Die very horribly if exit returns.  */
	illtrap	0

	.size _start,.-_start