sol2-c1.asm revision 302408
1185377Ssam! crt1.s for Solaris 2, x86
2187831Ssam
3185377Ssam!   Copyright (C) 1993, 1998 Free Software Foundation, Inc.
4185377Ssam!   Written By Fred Fish, Nov 1992
5185377Ssam! 
6185377Ssam! This file is free software; you can redistribute it and/or modify it
7185377Ssam! under the terms of the GNU General Public License as published by the
8185377Ssam! Free Software Foundation; either version 2, or (at your option) any
9185377Ssam! later version.
10185377Ssam! 
11185377Ssam! In addition to the permissions in the GNU General Public License, the
12185377Ssam! Free Software Foundation gives you unlimited permission to link the
13185377Ssam! compiled version of this file with other programs, and to distribute
14185377Ssam! those programs without any restriction coming from the use of this
15185377Ssam! file.  (The General Public License restrictions do apply in other
16185377Ssam! respects; for example, they cover modification of the file, and
17187611Ssam! distribution when not linked into another program.)
18185377Ssam! 
19185377Ssam! This file is distributed in the hope that it will be useful, but
20185377Ssam! WITHOUT ANY WARRANTY; without even the implied warranty of
21185377Ssam! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22185377Ssam! General Public License for more details.
23185377Ssam! 
24185377Ssam! You should have received a copy of the GNU General Public License
25185377Ssam! along with this program; see the file COPYING.  If not, write to
26185377Ssam! the Free Software Foundation, 51 Franklin Street, Fifth Floor,
27185377Ssam! Boston, MA 02110-1301, USA.
28185377Ssam! 
29185377Ssam!    As a special exception, if you link this library with files
30185377Ssam!    compiled with GCC to produce an executable, this does not cause
31185377Ssam!    the resulting executable to be covered by the GNU General Public License.
32185377Ssam!    This exception does not however invalidate any other reasons why
33185377Ssam!    the executable file might be covered by the GNU General Public License.
34185377Ssam! 
35185377Ssam
36185377Ssam! This file takes control of the process from the kernel, as specified
37185377Ssam! in section 3 of the System V Application Binary Interface, Intel386
38185377Ssam! Processor Supplement.  It has been constructed from information obtained
39185377Ssam! from the ABI, information obtained from single stepping existing
40185377Ssam! Solaris executables through their startup code with gdb, and from
41185377Ssam! information obtained by single stepping executables on other i386 SVR4
42185377Ssam! implementations.  This file is the first thing linked into any executable.
43185377Ssam
44185377Ssam	.file	"crt1.s"
45185377Ssam	.ident	"GNU C crt1.s"
46185377Ssam	.weak	_cleanup
47185377Ssam	.weak	_DYNAMIC
48185377Ssam	.text
49208644Srpaulo
50185377Ssam! Start creating the initial frame by pushing a NULL value for the return
51185377Ssam! address of the initial frame, and mark the end of the stack frame chain
52185377Ssam! (the innermost stack frame) with a NULL value, per page 3-32 of the ABI.
53185377Ssam! Initialize the first stack frame pointer in %ebp (the contents of which
54185377Ssam! are unspecified at process initialization).
55185377Ssam
56185377Ssam	.globl	_start
57185377Ssam_start:
58185377Ssam	pushl	$0x0
59185377Ssam	pushl	$0x0
60185377Ssam	movl	%esp,%ebp
61185377Ssam
62185377Ssam! As specified per page 3-32 of the ABI, %edx contains a function 
63185377Ssam! pointer that should be registered with atexit(), for proper
64185377Ssam! shared object termination.  Just push it onto the stack for now
65185377Ssam! to preserve it.  We want to register _cleanup() first.
66185377Ssam
67185377Ssam	pushl	%edx
68185377Ssam
69185377Ssam! Check to see if there is an _cleanup() function linked in, and if
70185377Ssam! so, register it with atexit() as the last thing to be run by
71185377Ssam! atexit().
72185377Ssam
73185377Ssam	movl	$_cleanup,%eax
74185377Ssam	testl	%eax,%eax
75185377Ssam	je	.L1
76185377Ssam	pushl	$_cleanup
77185377Ssam	call	atexit
78185377Ssam	addl	$0x4,%esp
79185377Ssam.L1:
80185377Ssam
81185377Ssam! Now check to see if we have an _DYNAMIC table, and if so then
82185377Ssam! we need to register the function pointer previously in %edx, but
83185377Ssam! now conveniently saved on the stack as the argument to pass to
84185377Ssam! atexit().
85185377Ssam
86185377Ssam	movl	$_DYNAMIC,%eax
87185377Ssam	testl	%eax,%eax
88185377Ssam	je	.L2
89185377Ssam	call	atexit
90185377Ssam.L2:
91185377Ssam
92185377Ssam! Register _fini() with atexit().  We will take care of calling _init()
93185377Ssam! directly.
94185377Ssam
95185377Ssam	pushl	$_fini
96185377Ssam	call	atexit
97185377Ssam
98185377Ssam! Compute the address of the environment vector on the stack and load
99185377Ssam! it into the global variable _environ.  Currently argc is at 8 off
100185377Ssam! the frame pointer.  Fetch the argument count into %eax, scale by the
101185377Ssam! size of each arg (4 bytes) and compute the address of the environment
102185377Ssam! vector which is 16 bytes (the two zero words we pushed, plus argc,
103185377Ssam! plus the null word terminating the arg vector) further up the stack,
104185377Ssam! off the frame pointer (whew!).
105185377Ssam
106185377Ssam	movl	8(%ebp),%eax
107185377Ssam	leal	16(%ebp,%eax,4),%edx
108187831Ssam	movl	%edx,_environ
109187831Ssam
110185377Ssam! Push the environment vector pointer, the argument vector pointer,
111185377Ssam! and the argument count on to the stack to set up the arguments
112187831Ssam! for _init(), _fpstart(), and main().  Note that the environment
113187831Ssam! vector pointer and the arg count were previously loaded into
114187831Ssam! %edx and %eax respectively.  The only new value we need to compute
115187831Ssam! is the argument vector pointer, which is at a fixed address off
116187831Ssam! the initial frame pointer.
117187831Ssam
118185377Ssam!
119185377Ssam! Make sure the stack is properly aligned.
120187831Ssam!
121187831Ssam	andl $0xfffffff0,%esp
122185377Ssam	subl $4,%esp
123185377Ssam	
124187831Ssam	pushl	%edx
125185377Ssam	leal	12(%ebp),%edx
126185377Ssam	pushl	%edx
127185377Ssam	pushl	%eax
128185377Ssam
129185377Ssam! Call _init(argc, argv, environ), _fpstart(argc, argv, environ), and
130185377Ssam! main(argc, argv, environ).
131185377Ssam
132185377Ssam	call	_init
133185377Ssam	call	__fpstart
134185377Ssam	call	main
135185377Ssam
136185377Ssam! Pop the argc, argv, and environ arguments off the stack, push the
137185377Ssam! value returned from main(), and call exit().
138185377Ssam
139201758Smbr	addl	$12,%esp
140185377Ssam	pushl	%eax
141185377Ssam	call	exit
142185377Ssam
143185377Ssam! An inline equivalent of _exit, as specified in Figure 3-26 of the ABI.
144185377Ssam
145185377Ssam	pushl	$0x0
146185377Ssam	movl	$0x1,%eax
147185377Ssam	lcall	$7,$0
148185377Ssam
149185377Ssam! If all else fails, just try a halt!
150185377Ssam
151185377Ssam	hlt
152185377Ssam	.type	_start,@function
153185377Ssam	.size	_start,.-_start
154185377Ssam
155185377Ssam! A dummy profiling support routine for non-profiling executables,
156187831Ssam! in case we link in some objects that have been compiled for profiling.
157187831Ssam
158185377Ssam	.weak	_mcount
159185377Ssam_mcount:
160185377Ssam	ret
161185377Ssam	.type	_mcount,@function
162185377Ssam	.size	_mcount,.-_mcount
163185377Ssam