xref: /csrg-svn/lib/csu/hp300/crt0.c (revision 47882)
1*47882Sbostic /*-
2*47882Sbostic  * Copyright (c) 1990 The Regents of the University of California.
3*47882Sbostic  * All rights reserved.
4*47882Sbostic  *
5*47882Sbostic  * %sccs.include.proprietary.c%
644279Sbostic  */
744279Sbostic 
844279Sbostic #if defined(LIBC_SCCS) && !defined(lint)
9*47882Sbostic static char sccsid[] = "@(#)crt0.c	5.2 (Berkeley) 04/12/91";
10*47882Sbostic #endif /* LIBC_SCCS and not lint */
1144279Sbostic 
1244279Sbostic /*
1344279Sbostic  *	C start up routine.
1444279Sbostic  *	Robert Henry, UCB, 20 Oct 81
1544279Sbostic  *
1644279Sbostic  *	We make the following (true) assumptions:
1744279Sbostic  *	1) when the kernel calls start, it does a jump to location 2,
1844279Sbostic  *	and thus avoids the register save mask.  We are NOT called
1944279Sbostic  *	with a calls!  see sys1.c:setregs().
2044279Sbostic  *	2) The only register variable that we can trust is sp,
2144279Sbostic  *	which points to the base of the kernel calling frame.
2244279Sbostic  *	Do NOT believe the documentation in exec(2) regarding the
2344279Sbostic  *	values of fp and ap.
2444279Sbostic  *	3) We can allocate as many register variables as we want,
2544279Sbostic  *	and don't have to save them for anybody.
2644279Sbostic  *	4) Because of the ways that asm's work, we can't have
2744279Sbostic  *	any automatic variables allocated on the stack, because
2844279Sbostic  *	we must catch the value of sp before any automatics are
2944279Sbostic  *	allocated.
3044279Sbostic  */
3144279Sbostic 
3244279Sbostic char **environ = (char **)0;
3344279Sbostic static int fd;
3444279Sbostic 
3544279Sbostic asm("#define _start start");
3644279Sbostic asm("#define _eprol eprol");
3744279Sbostic 
3844279Sbostic #ifdef hp300
3944279Sbostic asm("#define link .long 0; linkw");	/* Yuk!! */
4044279Sbostic #endif
4144279Sbostic 
4244279Sbostic extern	unsigned char	etext;
4344279Sbostic extern	unsigned char	eprol;
4444279Sbostic start()
4544279Sbostic {
4644279Sbostic 	struct kframe {
4744279Sbostic 		int	kargc;
4844279Sbostic 		char	*kargv[1];	/* size depends on kargc */
4944279Sbostic 		char	kargstr[1];	/* size varies */
5044279Sbostic 		char	kenvstr[1];	/* size varies */
5144279Sbostic 	};
5244279Sbostic 	/*
5344279Sbostic 	 *	ALL REGISTER VARIABLES!!!
5444279Sbostic 	 */
5544279Sbostic 	register int d7;		/* needed for init (this will be
5644279Sbostic 					   a problem with GCC) */
5744279Sbostic 	register struct kframe *kfp;	/* PCC a5 */
5844279Sbostic 	register char **targv;
5944279Sbostic 	register char **argv;
6044279Sbostic 	extern int errno;
6144279Sbostic 
6244279Sbostic #ifdef lint
6344279Sbostic 	kfp = 0;
6444279Sbostic 	initcode = initcode = 0;
6544279Sbostic #else not lint
6644279Sbostic #ifdef __GNUC__
6744279Sbostic 	asm("lea a6@(4),%0" : "=r" (kfp));	/* catch it quick */
6844279Sbostic #else
6944279Sbostic 	asm("	lea	a6@(4),a5");	/* catch it quick */
7044279Sbostic #endif
7144279Sbostic #endif not lint
7244279Sbostic 	for (argv = targv = &kfp->kargv[0]; *targv++; /* void */)
7344279Sbostic 		/* void */ ;
7444279Sbostic 	if (targv >= (char **)(*argv))
7544279Sbostic 		--targv;
7644279Sbostic 	environ = targv;
7744279Sbostic asm("eprol:");
7844279Sbostic 
7944279Sbostic #ifdef paranoid
8044279Sbostic 	/*
8144279Sbostic 	 * The standard I/O library assumes that file descriptors 0, 1, and 2
8244279Sbostic 	 * are open. If one of these descriptors is closed prior to the start
8344279Sbostic 	 * of the process, I/O gets very confused. To avoid this problem, we
8444279Sbostic 	 * insure that the first three file descriptors are open before calling
8544279Sbostic 	 * main(). Normally this is undefined, as it adds two unnecessary
8644279Sbostic 	 * system calls.
8744279Sbostic 	 */
8844279Sbostic 	do	{
8944279Sbostic 		fd = open("/dev/null", 2);
9044279Sbostic 	} while (fd >= 0 && fd < 3);
9144279Sbostic 	close(fd);
9244279Sbostic #endif paranoid
9344279Sbostic 
9444279Sbostic #ifdef MCRT0
9544279Sbostic 	monstartup(&eprol, &etext);
9644279Sbostic #endif MCRT0
9744279Sbostic 	errno = 0;
9844279Sbostic 	exit(main(kfp->kargc, argv, environ));
9944279Sbostic }
10044279Sbostic asm("#undef link");
10144279Sbostic asm("#undef _start");
10244279Sbostic asm("#undef _eprol");
10344279Sbostic 
10444279Sbostic #ifdef MCRT0
10544279Sbostic /*ARGSUSED*/
10644279Sbostic exit(code)
10744279Sbostic 	register int code;	/* PCC d7 */
10844279Sbostic {
10944279Sbostic 	monitor(0);
11044279Sbostic 	_cleanup();
11144279Sbostic #ifdef __GNUC__
11244279Sbostic 	asm("movl %1,sp@-" : "=m" (*(char *)0) : "r" (code));
11344279Sbostic #else
11444279Sbostic 	asm("	movl d7,sp@-");
11544279Sbostic #endif
11644279Sbostic 	asm("	subql #4,sp");
11744279Sbostic 	asm("	movl #1,d0");
11844279Sbostic 	asm("	trap #0");
11944279Sbostic }
12044279Sbostic #endif MCRT0
12144279Sbostic 
12244279Sbostic #ifdef CRT0
12344279Sbostic /*
12444279Sbostic  * null mcount and moncontrol,
12544279Sbostic  * just in case some routine is compiled for profiling
12644279Sbostic  */
12744279Sbostic moncontrol(val)
12844279Sbostic 	int val;
12944279Sbostic {
13044279Sbostic 
13144279Sbostic }
13244279Sbostic asm("	.globl	mcount");
13344279Sbostic asm("mcount:	rts");
13444279Sbostic #endif CRT0
135