sol2-gc1.asm revision 169689
1178739Sgonzo! gcrt1.s for Solaris 2, x86
2178739Sgonzo
3178739Sgonzo!   Copyright (C) 1993 Free Software Foundation, Inc.
4178739Sgonzo!   Written By Fred Fish, Nov 1992
5178739Sgonzo! 
6178739Sgonzo! This file is free software; you can redistribute it and/or modify it
7178739Sgonzo! under the terms of the GNU General Public License as published by the
8178739Sgonzo! Free Software Foundation; either version 2, or (at your option) any
9178739Sgonzo! later version.
10178739Sgonzo! 
11178739Sgonzo! In addition to the permissions in the GNU General Public License, the
12178739Sgonzo! Free Software Foundation gives you unlimited permission to link the
13178739Sgonzo! compiled version of this file with other programs, and to distribute
14178739Sgonzo! those programs without any restriction coming from the use of this
15178739Sgonzo! file.  (The General Public License restrictions do apply in other
16178739Sgonzo! respects; for example, they cover modification of the file, and
17178739Sgonzo! distribution when not linked into another program.)
18178739Sgonzo! 
19178739Sgonzo! This file is distributed in the hope that it will be useful, but
20178739Sgonzo! WITHOUT ANY WARRANTY; without even the implied warranty of
21178739Sgonzo! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22178739Sgonzo! General Public License for more details.
23178739Sgonzo! 
24178739Sgonzo! You should have received a copy of the GNU General Public License
25178739Sgonzo! along with this program; see the file COPYING.  If not, write to
26178739Sgonzo! the Free Software Foundation, 51 Franklin Street, Fifth Floor,
27178739Sgonzo! Boston, MA 02110-1301, USA.
28178739Sgonzo! 
29178739Sgonzo!    As a special exception, if you link this library with files
30178739Sgonzo!    compiled with GCC to produce an executable, this does not cause
31178739Sgonzo!    the resulting executable to be covered by the GNU General Public License.
32178739Sgonzo!    This exception does not however invalidate any other reasons why
33178739Sgonzo!    the executable file might be covered by the GNU General Public License.
34178739Sgonzo! 
35178739Sgonzo
36178739Sgonzo! This file takes control of the process from the kernel, as specified
37178739Sgonzo! in section 3 of the System V Application Binary Interface, Intel386
38178739Sgonzo! Processor Supplement.  It has been constructed from information obtained
39178739Sgonzo! from the ABI, information obtained from single stepping existing
40178739Sgonzo! Solaris executables through their startup code with gdb, and from
41178739Sgonzo! information obtained by single stepping executables on other i386 SVR4
42178739Sgonzo! implementations.  This file is the first thing linked into any executable.
43178739Sgonzo
44178739Sgonzo! This is a modified crt1.s by J.W.Hawtin <oolon@ankh.org> 15/8/96, 
45178739Sgonzo! to allow program profiling, by calling monstartup on entry and _mcleanup 
46232832Skib! on exit
47178739Sgonzo
48178739Sgonzo	.file	"gcrt1.s"
49178739Sgonzo	.ident	"GNU C gcrt1.s"
50178739Sgonzo	.weak	_DYNAMIC
51178739Sgonzo	.text
52178739Sgonzo
53178739Sgonzo! Start creating the initial frame by pushing a NULL value for the return
54178739Sgonzo! address of the initial frame, and mark the end of the stack frame chain
55178739Sgonzo! (the innermost stack frame) with a NULL value, per page 3-32 of the ABI.
56178739Sgonzo! Initialize the first stack frame pointer in %ebp (the contents of which
57178739Sgonzo! are unspecified at process initialization).
58204756Suqs
59204756Suqs	.globl	_start
60178739Sgonzo_start:
61178739Sgonzo	pushl	$0x0
62178739Sgonzo	pushl	$0x0
63178739Sgonzo	movl	%esp,%ebp
64204757Suqs
65204757Suqs! As specified per page 3-32 of the ABI, %edx contains a function 
66178739Sgonzo! pointer that should be registered with atexit(), for proper
67178739Sgonzo! shared object termination.  Just push it onto the stack for now
68178739Sgonzo! to preserve it.  We want to register _cleanup() first.
69178739Sgonzo
70178739Sgonzo	pushl	%edx
71178739Sgonzo
72178739Sgonzo! Check to see if there is an _cleanup() function linked in, and if
73178739Sgonzo! so, register it with atexit() as the last thing to be run by
74245133Skib! atexit().
75178739Sgonzo
76178739Sgonzo	movl	$_mcleanup,%eax
77178739Sgonzo	testl	%eax,%eax
78232580Sgonzo	je	.L1
79232580Sgonzo	pushl	$_mcleanup
80232580Sgonzo	call	atexit
81178739Sgonzo	addl	$0x4,%esp
82178739Sgonzo.L1:
83178739Sgonzo
84178739Sgonzo! Now check to see if we have an _DYNAMIC table, and if so then
85232832Skib! we need to register the function pointer previously in %edx, but
86232832Skib! now conveniently saved on the stack as the argument to pass to
87232832Skib! atexit().
88178739Sgonzo
89178739Sgonzo	movl	$_DYNAMIC,%eax
90178739Sgonzo	testl	%eax,%eax
91178739Sgonzo	je	.L2
92178739Sgonzo	call	atexit
93178739Sgonzo.L2:
94178739Sgonzo
95! Register _fini() with atexit().  We will take care of calling _init()
96! directly.
97
98	pushl	$_fini
99	call	atexit
100
101! Start profiling
102
103        pushl %ebp
104        movl %esp,%ebp
105        pushl $_etext
106        pushl $_start
107        call monstartup
108        addl $8,%esp
109	popl %ebp
110
111! Compute the address of the environment vector on the stack and load
112! it into the global variable _environ.  Currently argc is at 8 off
113! the frame pointer.  Fetch the argument count into %eax, scale by the
114! size of each arg (4 bytes) and compute the address of the environment
115! vector which is 16 bytes (the two zero words we pushed, plus argc,
116! plus the null word terminating the arg vector) further up the stack,
117! off the frame pointer (whew!).
118
119	movl	8(%ebp),%eax
120	leal	16(%ebp,%eax,4),%edx
121	movl	%edx,_environ
122
123! Push the environment vector pointer, the argument vector pointer,
124! and the argument count on to the stack to set up the arguments
125! for _init(), _fpstart(), and main().  Note that the environment
126! vector pointer and the arg count were previously loaded into
127! %edx and %eax respectively.  The only new value we need to compute
128! is the argument vector pointer, which is at a fixed address off
129! the initial frame pointer.
130
131!
132! Make sure the stack is properly aligned.
133!
134	andl $0xfffffff0,%esp
135	subl $4,%esp
136
137	pushl	%edx
138	leal	12(%ebp),%edx
139	pushl	%edx
140	pushl	%eax
141
142! Call _init(argc, argv, environ), _fpstart(argc, argv, environ), and
143! main(argc, argv, environ).
144
145	call	_init
146	call	__fpstart
147	call	main
148
149! Pop the argc, argv, and environ arguments off the stack, push the
150! value returned from main(), and call exit().
151
152	addl	$12,%esp
153	pushl	%eax
154	call	exit
155
156! An inline equivalent of _exit, as specified in Figure 3-26 of the ABI.
157
158	pushl	$0x0
159	movl	$0x1,%eax
160	lcall	$7,$0
161
162! If all else fails, just try a halt!
163
164	hlt
165	.type	_start,@function
166	.size	_start,.-_start
167