xref: /csrg-svn/lib/csu/hp300/crt0.c (revision 44279)
1*44279Sbostic /*
2*44279Sbostic  * Copyright (c) 1980 Regents of the University of California.
3*44279Sbostic  * All rights reserved.  The Berkeley software License Agreement
4*44279Sbostic  * specifies the terms and conditions for redistribution.
5*44279Sbostic  */
6*44279Sbostic 
7*44279Sbostic #if defined(LIBC_SCCS) && !defined(lint)
8*44279Sbostic static char sccsid[] = "@(#)crt0.c	5.3 (Berkeley) 3/9/86";
9*44279Sbostic #endif LIBC_SCCS and not lint
10*44279Sbostic 
11*44279Sbostic /*
12*44279Sbostic  *	C start up routine.
13*44279Sbostic  *	Robert Henry, UCB, 20 Oct 81
14*44279Sbostic  *
15*44279Sbostic  *	We make the following (true) assumptions:
16*44279Sbostic  *	1) when the kernel calls start, it does a jump to location 2,
17*44279Sbostic  *	and thus avoids the register save mask.  We are NOT called
18*44279Sbostic  *	with a calls!  see sys1.c:setregs().
19*44279Sbostic  *	2) The only register variable that we can trust is sp,
20*44279Sbostic  *	which points to the base of the kernel calling frame.
21*44279Sbostic  *	Do NOT believe the documentation in exec(2) regarding the
22*44279Sbostic  *	values of fp and ap.
23*44279Sbostic  *	3) We can allocate as many register variables as we want,
24*44279Sbostic  *	and don't have to save them for anybody.
25*44279Sbostic  *	4) Because of the ways that asm's work, we can't have
26*44279Sbostic  *	any automatic variables allocated on the stack, because
27*44279Sbostic  *	we must catch the value of sp before any automatics are
28*44279Sbostic  *	allocated.
29*44279Sbostic  */
30*44279Sbostic 
31*44279Sbostic char **environ = (char **)0;
32*44279Sbostic static int fd;
33*44279Sbostic 
34*44279Sbostic asm("#define _start start");
35*44279Sbostic asm("#define _eprol eprol");
36*44279Sbostic 
37*44279Sbostic #ifdef hp300
38*44279Sbostic asm("#define link .long 0; linkw");	/* Yuk!! */
39*44279Sbostic #endif
40*44279Sbostic 
41*44279Sbostic extern	unsigned char	etext;
42*44279Sbostic extern	unsigned char	eprol;
43*44279Sbostic start()
44*44279Sbostic {
45*44279Sbostic 	struct kframe {
46*44279Sbostic 		int	kargc;
47*44279Sbostic 		char	*kargv[1];	/* size depends on kargc */
48*44279Sbostic 		char	kargstr[1];	/* size varies */
49*44279Sbostic 		char	kenvstr[1];	/* size varies */
50*44279Sbostic 	};
51*44279Sbostic 	/*
52*44279Sbostic 	 *	ALL REGISTER VARIABLES!!!
53*44279Sbostic 	 */
54*44279Sbostic 	register int d7;		/* needed for init (this will be
55*44279Sbostic 					   a problem with GCC) */
56*44279Sbostic 	register struct kframe *kfp;	/* PCC a5 */
57*44279Sbostic 	register char **targv;
58*44279Sbostic 	register char **argv;
59*44279Sbostic 	extern int errno;
60*44279Sbostic 
61*44279Sbostic #ifdef lint
62*44279Sbostic 	kfp = 0;
63*44279Sbostic 	initcode = initcode = 0;
64*44279Sbostic #else not lint
65*44279Sbostic #ifdef __GNUC__
66*44279Sbostic 	asm("lea a6@(4),%0" : "=r" (kfp));	/* catch it quick */
67*44279Sbostic #else
68*44279Sbostic 	asm("	lea	a6@(4),a5");	/* catch it quick */
69*44279Sbostic #endif
70*44279Sbostic #endif not lint
71*44279Sbostic 	for (argv = targv = &kfp->kargv[0]; *targv++; /* void */)
72*44279Sbostic 		/* void */ ;
73*44279Sbostic 	if (targv >= (char **)(*argv))
74*44279Sbostic 		--targv;
75*44279Sbostic 	environ = targv;
76*44279Sbostic asm("eprol:");
77*44279Sbostic 
78*44279Sbostic #ifdef paranoid
79*44279Sbostic 	/*
80*44279Sbostic 	 * The standard I/O library assumes that file descriptors 0, 1, and 2
81*44279Sbostic 	 * are open. If one of these descriptors is closed prior to the start
82*44279Sbostic 	 * of the process, I/O gets very confused. To avoid this problem, we
83*44279Sbostic 	 * insure that the first three file descriptors are open before calling
84*44279Sbostic 	 * main(). Normally this is undefined, as it adds two unnecessary
85*44279Sbostic 	 * system calls.
86*44279Sbostic 	 */
87*44279Sbostic 	do	{
88*44279Sbostic 		fd = open("/dev/null", 2);
89*44279Sbostic 	} while (fd >= 0 && fd < 3);
90*44279Sbostic 	close(fd);
91*44279Sbostic #endif paranoid
92*44279Sbostic 
93*44279Sbostic #ifdef MCRT0
94*44279Sbostic 	monstartup(&eprol, &etext);
95*44279Sbostic #endif MCRT0
96*44279Sbostic 	errno = 0;
97*44279Sbostic 	exit(main(kfp->kargc, argv, environ));
98*44279Sbostic }
99*44279Sbostic asm("#undef link");
100*44279Sbostic asm("#undef _start");
101*44279Sbostic asm("#undef _eprol");
102*44279Sbostic 
103*44279Sbostic #ifdef MCRT0
104*44279Sbostic /*ARGSUSED*/
105*44279Sbostic exit(code)
106*44279Sbostic 	register int code;	/* PCC d7 */
107*44279Sbostic {
108*44279Sbostic 	monitor(0);
109*44279Sbostic 	_cleanup();
110*44279Sbostic #ifdef __GNUC__
111*44279Sbostic 	asm("movl %1,sp@-" : "=m" (*(char *)0) : "r" (code));
112*44279Sbostic #else
113*44279Sbostic 	asm("	movl d7,sp@-");
114*44279Sbostic #endif
115*44279Sbostic 	asm("	subql #4,sp");
116*44279Sbostic 	asm("	movl #1,d0");
117*44279Sbostic 	asm("	trap #0");
118*44279Sbostic }
119*44279Sbostic #endif MCRT0
120*44279Sbostic 
121*44279Sbostic #ifdef CRT0
122*44279Sbostic /*
123*44279Sbostic  * null mcount and moncontrol,
124*44279Sbostic  * just in case some routine is compiled for profiling
125*44279Sbostic  */
126*44279Sbostic moncontrol(val)
127*44279Sbostic 	int val;
128*44279Sbostic {
129*44279Sbostic 
130*44279Sbostic }
131*44279Sbostic asm("	.globl	mcount");
132*44279Sbostic asm("mcount:	rts");
133*44279Sbostic #endif CRT0
134