118334Speter! crt1.s for Solaris 2, x86
218334Speter
350397Sobrien!   Copyright (C) 1993, 1998 Free Software Foundation, Inc.
418334Speter!   Written By Fred Fish, Nov 1992
518334Speter! 
618334Speter! This file is free software; you can redistribute it and/or modify it
718334Speter! under the terms of the GNU General Public License as published by the
818334Speter! Free Software Foundation; either version 2, or (at your option) any
918334Speter! later version.
1018334Speter! 
1118334Speter! In addition to the permissions in the GNU General Public License, the
1218334Speter! Free Software Foundation gives you unlimited permission to link the
1318334Speter! compiled version of this file with other programs, and to distribute
1418334Speter! those programs without any restriction coming from the use of this
1518334Speter! file.  (The General Public License restrictions do apply in other
1618334Speter! respects; for example, they cover modification of the file, and
1718334Speter! distribution when not linked into another program.)
1818334Speter! 
1918334Speter! This file is distributed in the hope that it will be useful, but
2018334Speter! WITHOUT ANY WARRANTY; without even the implied warranty of
2118334Speter! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2218334Speter! General Public License for more details.
2318334Speter! 
2418334Speter! You should have received a copy of the GNU General Public License
2518334Speter! along with this program; see the file COPYING.  If not, write to
26169689Skan! the Free Software Foundation, 51 Franklin Street, Fifth Floor,
27169689Skan! Boston, MA 02110-1301, USA.
2818334Speter! 
2918334Speter!    As a special exception, if you link this library with files
3018334Speter!    compiled with GCC to produce an executable, this does not cause
3118334Speter!    the resulting executable to be covered by the GNU General Public License.
3218334Speter!    This exception does not however invalidate any other reasons why
3318334Speter!    the executable file might be covered by the GNU General Public License.
3418334Speter! 
3518334Speter
3618334Speter! This file takes control of the process from the kernel, as specified
3718334Speter! in section 3 of the System V Application Binary Interface, Intel386
3818334Speter! Processor Supplement.  It has been constructed from information obtained
3918334Speter! from the ABI, information obtained from single stepping existing
4018334Speter! Solaris executables through their startup code with gdb, and from
4118334Speter! information obtained by single stepping executables on other i386 SVR4
4218334Speter! implementations.  This file is the first thing linked into any executable.
4318334Speter
4418334Speter	.file	"crt1.s"
4518334Speter	.ident	"GNU C crt1.s"
4618334Speter	.weak	_cleanup
4718334Speter	.weak	_DYNAMIC
4818334Speter	.text
4918334Speter
5018334Speter! Start creating the initial frame by pushing a NULL value for the return
5118334Speter! address of the initial frame, and mark the end of the stack frame chain
5218334Speter! (the innermost stack frame) with a NULL value, per page 3-32 of the ABI.
5318334Speter! Initialize the first stack frame pointer in %ebp (the contents of which
5418334Speter! are unspecified at process initialization).
5518334Speter
5618334Speter	.globl	_start
5718334Speter_start:
5818334Speter	pushl	$0x0
5918334Speter	pushl	$0x0
6018334Speter	movl	%esp,%ebp
6118334Speter
6218334Speter! As specified per page 3-32 of the ABI, %edx contains a function 
6318334Speter! pointer that should be registered with atexit(), for proper
6418334Speter! shared object termination.  Just push it onto the stack for now
6518334Speter! to preserve it.  We want to register _cleanup() first.
6618334Speter
6718334Speter	pushl	%edx
6818334Speter
6918334Speter! Check to see if there is an _cleanup() function linked in, and if
7018334Speter! so, register it with atexit() as the last thing to be run by
7118334Speter! atexit().
7218334Speter
7318334Speter	movl	$_cleanup,%eax
7418334Speter	testl	%eax,%eax
7518334Speter	je	.L1
7618334Speter	pushl	$_cleanup
7718334Speter	call	atexit
7818334Speter	addl	$0x4,%esp
7918334Speter.L1:
8018334Speter
8118334Speter! Now check to see if we have an _DYNAMIC table, and if so then
8218334Speter! we need to register the function pointer previously in %edx, but
8318334Speter! now conveniently saved on the stack as the argument to pass to
8418334Speter! atexit().
8518334Speter
8618334Speter	movl	$_DYNAMIC,%eax
8718334Speter	testl	%eax,%eax
8818334Speter	je	.L2
8918334Speter	call	atexit
9018334Speter.L2:
9118334Speter
9218334Speter! Register _fini() with atexit().  We will take care of calling _init()
9318334Speter! directly.
9418334Speter
9518334Speter	pushl	$_fini
9618334Speter	call	atexit
9718334Speter
9818334Speter! Compute the address of the environment vector on the stack and load
9918334Speter! it into the global variable _environ.  Currently argc is at 8 off
10018334Speter! the frame pointer.  Fetch the argument count into %eax, scale by the
10118334Speter! size of each arg (4 bytes) and compute the address of the environment
10218334Speter! vector which is 16 bytes (the two zero words we pushed, plus argc,
10318334Speter! plus the null word terminating the arg vector) further up the stack,
10418334Speter! off the frame pointer (whew!).
10518334Speter
10618334Speter	movl	8(%ebp),%eax
10718334Speter	leal	16(%ebp,%eax,4),%edx
10818334Speter	movl	%edx,_environ
10918334Speter
11018334Speter! Push the environment vector pointer, the argument vector pointer,
11118334Speter! and the argument count on to the stack to set up the arguments
11218334Speter! for _init(), _fpstart(), and main().  Note that the environment
11318334Speter! vector pointer and the arg count were previously loaded into
11418334Speter! %edx and %eax respectively.  The only new value we need to compute
11518334Speter! is the argument vector pointer, which is at a fixed address off
11618334Speter! the initial frame pointer.
11718334Speter
11890075Sobrien!
11990075Sobrien! Make sure the stack is properly aligned.
12090075Sobrien!
12190075Sobrien	andl $0xfffffff0,%esp
12290075Sobrien	subl $4,%esp
12390075Sobrien	
12418334Speter	pushl	%edx
12518334Speter	leal	12(%ebp),%edx
12618334Speter	pushl	%edx
12718334Speter	pushl	%eax
12818334Speter
12918334Speter! Call _init(argc, argv, environ), _fpstart(argc, argv, environ), and
13018334Speter! main(argc, argv, environ).
13118334Speter
13218334Speter	call	_init
13318334Speter	call	__fpstart
13418334Speter	call	main
13518334Speter
13618334Speter! Pop the argc, argv, and environ arguments off the stack, push the
13718334Speter! value returned from main(), and call exit().
13818334Speter
13918334Speter	addl	$12,%esp
14018334Speter	pushl	%eax
14118334Speter	call	exit
14218334Speter
14318334Speter! An inline equivalent of _exit, as specified in Figure 3-26 of the ABI.
14418334Speter
14518334Speter	pushl	$0x0
14618334Speter	movl	$0x1,%eax
14718334Speter	lcall	$7,$0
14818334Speter
14918334Speter! If all else fails, just try a halt!
15018334Speter
15118334Speter	hlt
15218334Speter	.type	_start,@function
15318334Speter	.size	_start,.-_start
15418334Speter
15518334Speter! A dummy profiling support routine for non-profiling executables,
15618334Speter! in case we link in some objects that have been compiled for profiling.
15718334Speter
15850397Sobrien	.weak	_mcount
15918334Speter_mcount:
16018334Speter	ret
16118334Speter	.type	_mcount,@function
16218334Speter	.size	_mcount,.-_mcount
163