sol2-c1.asm revision 169690
1169691Skan! crt1.s for Solaris 2, x86
2169691Skan
3169691Skan!   Copyright (C) 1993, 1998 Free Software Foundation, Inc.
4169691Skan!   Written By Fred Fish, Nov 1992
5169691Skan! 
6169691Skan! This file is free software; you can redistribute it and/or modify it
7169691Skan! under the terms of the GNU General Public License as published by the
8169691Skan! Free Software Foundation; either version 2, or (at your option) any
9169691Skan! later version.
10169691Skan! 
11169691Skan! In addition to the permissions in the GNU General Public License, the
12169691Skan! Free Software Foundation gives you unlimited permission to link the
13169691Skan! compiled version of this file with other programs, and to distribute
14169691Skan! those programs without any restriction coming from the use of this
15169691Skan! file.  (The General Public License restrictions do apply in other
16169691Skan! respects; for example, they cover modification of the file, and
17169691Skan! distribution when not linked into another program.)
18169691Skan! 
19169691Skan! This file is distributed in the hope that it will be useful, but
20169691Skan! WITHOUT ANY WARRANTY; without even the implied warranty of
21169691Skan! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22169691Skan! General Public License for more details.
23169691Skan! 
24169691Skan! You should have received a copy of the GNU General Public License
25169691Skan! along with this program; see the file COPYING.  If not, write to
26169691Skan! the Free Software Foundation, 51 Franklin Street, Fifth Floor,
27169691Skan! Boston, MA 02110-1301, USA.
28169691Skan! 
29169691Skan!    As a special exception, if you link this library with files
30169691Skan!    compiled with GCC to produce an executable, this does not cause
31169691Skan!    the resulting executable to be covered by the GNU General Public License.
32169691Skan!    This exception does not however invalidate any other reasons why
33169691Skan!    the executable file might be covered by the GNU General Public License.
34169691Skan! 
35169691Skan
36169691Skan! This file takes control of the process from the kernel, as specified
37169691Skan! in section 3 of the System V Application Binary Interface, Intel386
38169691Skan! Processor Supplement.  It has been constructed from information obtained
39169691Skan! from the ABI, information obtained from single stepping existing
40169691Skan! Solaris executables through their startup code with gdb, and from
41169691Skan! information obtained by single stepping executables on other i386 SVR4
42169691Skan! implementations.  This file is the first thing linked into any executable.
43169691Skan
44169691Skan	.file	"crt1.s"
45169691Skan	.ident	"GNU C crt1.s"
46169691Skan	.weak	_cleanup
47169691Skan	.weak	_DYNAMIC
48169691Skan	.text
49169691Skan
50169691Skan! Start creating the initial frame by pushing a NULL value for the return
51169691Skan! address of the initial frame, and mark the end of the stack frame chain
52169691Skan! (the innermost stack frame) with a NULL value, per page 3-32 of the ABI.
53169691Skan! Initialize the first stack frame pointer in %ebp (the contents of which
54169691Skan! are unspecified at process initialization).
55169691Skan
56169691Skan	.globl	_start
57169691Skan_start:
58169691Skan	pushl	$0x0
59169691Skan	pushl	$0x0
60169691Skan	movl	%esp,%ebp
61169691Skan
62169691Skan! As specified per page 3-32 of the ABI, %edx contains a function 
63169691Skan! pointer that should be registered with atexit(), for proper
64169691Skan! shared object termination.  Just push it onto the stack for now
65169691Skan! to preserve it.  We want to register _cleanup() first.
66169691Skan
67169691Skan	pushl	%edx
68169691Skan
69169691Skan! Check to see if there is an _cleanup() function linked in, and if
70169691Skan! so, register it with atexit() as the last thing to be run by
71169691Skan! atexit().
72169691Skan
73169691Skan	movl	$_cleanup,%eax
74169691Skan	testl	%eax,%eax
75169691Skan	je	.L1
76169691Skan	pushl	$_cleanup
77169691Skan	call	atexit
78169691Skan	addl	$0x4,%esp
79169691Skan.L1:
80169691Skan
81169691Skan! Now check to see if we have an _DYNAMIC table, and if so then
82169691Skan! we need to register the function pointer previously in %edx, but
83169691Skan! now conveniently saved on the stack as the argument to pass to
84169691Skan! atexit().
85169691Skan
86169691Skan	movl	$_DYNAMIC,%eax
87169691Skan	testl	%eax,%eax
88169691Skan	je	.L2
89169691Skan	call	atexit
90169691Skan.L2:
91169691Skan
92169691Skan! Register _fini() with atexit().  We will take care of calling _init()
93169691Skan! directly.
94169691Skan
95169691Skan	pushl	$_fini
96169691Skan	call	atexit
97169691Skan
98169691Skan! Compute the address of the environment vector on the stack and load
99169691Skan! it into the global variable _environ.  Currently argc is at 8 off
100169691Skan! the frame pointer.  Fetch the argument count into %eax, scale by the
101169691Skan! size of each arg (4 bytes) and compute the address of the environment
102169691Skan! vector which is 16 bytes (the two zero words we pushed, plus argc,
103169691Skan! plus the null word terminating the arg vector) further up the stack,
104169691Skan! off the frame pointer (whew!).
105169691Skan
106169691Skan	movl	8(%ebp),%eax
107169691Skan	leal	16(%ebp,%eax,4),%edx
108169691Skan	movl	%edx,_environ
109169691Skan
110169691Skan! Push the environment vector pointer, the argument vector pointer,
111169691Skan! and the argument count on to the stack to set up the arguments
112169691Skan! for _init(), _fpstart(), and main().  Note that the environment
113169691Skan! vector pointer and the arg count were previously loaded into
114169691Skan! %edx and %eax respectively.  The only new value we need to compute
115169691Skan! is the argument vector pointer, which is at a fixed address off
116169691Skan! the initial frame pointer.
117169691Skan
118169691Skan!
119! Make sure the stack is properly aligned.
120!
121	andl $0xfffffff0,%esp
122	subl $4,%esp
123	
124	pushl	%edx
125	leal	12(%ebp),%edx
126	pushl	%edx
127	pushl	%eax
128
129! Call _init(argc, argv, environ), _fpstart(argc, argv, environ), and
130! main(argc, argv, environ).
131
132	call	_init
133	call	__fpstart
134	call	main
135
136! Pop the argc, argv, and environ arguments off the stack, push the
137! value returned from main(), and call exit().
138
139	addl	$12,%esp
140	pushl	%eax
141	call	exit
142
143! An inline equivalent of _exit, as specified in Figure 3-26 of the ABI.
144
145	pushl	$0x0
146	movl	$0x1,%eax
147	lcall	$7,$0
148
149! If all else fails, just try a halt!
150
151	hlt
152	.type	_start,@function
153	.size	_start,.-_start
154
155! A dummy profiling support routine for non-profiling executables,
156! in case we link in some objects that have been compiled for profiling.
157
158	.weak	_mcount
159_mcount:
160	ret
161	.type	_mcount,@function
162	.size	_mcount,.-_mcount
163