xref: /csrg-svn/lib/csu/vax/crt0.c (revision 25247)
121414Sdist /*
221414Sdist  * Copyright (c) 1980 Regents of the University of California.
321414Sdist  * All rights reserved.  The Berkeley software License Agreement
421414Sdist  * specifies the terms and conditions for redistribution.
521414Sdist  */
65102Smckusick 
721414Sdist #ifndef lint
8*25247Smckusick static char sccsid[] = "@(#)crt0.c	5.2 (Berkeley) 10/21/85";
921414Sdist #endif not lint
1021414Sdist 
115102Smckusick /*
125102Smckusick  *	C start up routine.
135102Smckusick  *	Robert Henry, UCB, 20 Oct 81
145102Smckusick  *
155102Smckusick  *	We make the following (true) assumptions:
165102Smckusick  *	1) when the kernel calls start, it does a jump to location 2,
175102Smckusick  *	and thus avoids the register save mask.  We are NOT called
185102Smckusick  *	with a calls!  see sys1.c:setregs().
195102Smckusick  *	2) The only register variable that we can trust is sp,
205102Smckusick  *	which points to the base of the kernel calling frame.
215102Smckusick  *	Do NOT believe the documentation in exec(2) regarding the
225102Smckusick  *	values of fp and ap.
235102Smckusick  *	3) We can allocate as many register variables as we want,
245102Smckusick  *	and don't have to save them for anybody.
255102Smckusick  *	4) Because of the ways that asm's work, we can't have
265102Smckusick  *	any automatic variables allocated on the stack, because
275102Smckusick  *	we must catch the value of sp before any automatics are
285102Smckusick  *	allocated.
295102Smckusick  */
305102Smckusick 
319438Smckusick char **environ = (char **)0;
32*25247Smckusick static int fd;
335102Smckusick 
345332Smckusic asm("#define _start start");
359438Smckusick asm("#define _eprol eprol");
369438Smckusick extern	unsigned char	etext;
379438Smckusick extern	unsigned char	eprol;
385102Smckusick start()
395102Smckusick {
405102Smckusick 	struct kframe {
415102Smckusick 		int	kargc;
425102Smckusick 		char	*kargv[1];	/* size depends on kargc */
435102Smckusick 		char	kargstr[1];	/* size varies */
445102Smckusick 		char	kenvstr[1];	/* size varies */
455102Smckusick 	};
465102Smckusick 	/*
475102Smckusick 	 *	ALL REGISTER VARIABLES!!!
485102Smckusick 	 */
496852Srrh 	register int r11;		/* needed for init */
506852Srrh 	register struct kframe *kfp;	/* r10 */
515102Smckusick 	register char **targv;
525102Smckusick 	register char **argv;
53*25247Smckusick 	extern int errno;
545102Smckusick 
555102Smckusick #ifdef lint
565102Smckusick 	kfp = 0;
579438Smckusick 	initcode = initcode = 0;
585102Smckusick #else not lint
596852Srrh 	asm("	movl	sp,r10");	/* catch it quick */
605102Smckusick #endif not lint
615102Smckusick 	for (argv = targv = &kfp->kargv[0]; *targv++; /* void */)
625102Smckusick 		/* void */ ;
635102Smckusick 	if (targv >= (char **)(*argv))
645102Smckusick 		--targv;
655102Smckusick 	environ = targv;
669438Smckusick asm("eprol:");
67*25247Smckusick 
68*25247Smckusick #ifdef paranoid
69*25247Smckusick 	/*
70*25247Smckusick 	 * The standard I/O library assumes that file descriptors 0, 1, and 2
71*25247Smckusick 	 * are open. If one of these descriptors is closed prior to the start
72*25247Smckusick 	 * of the process, I/O gets very confused. To avoid this problem, we
73*25247Smckusick 	 * insure that the first three file descriptors are open before calling
74*25247Smckusick 	 * main(). Normally this is undefined, as it adds two unnecessary
75*25247Smckusick 	 * system calls.
76*25247Smckusick 	 */
77*25247Smckusick 	do	{
78*25247Smckusick 		fd = open("/dev/null", 2);
79*25247Smckusick 	} while (fd >= 0 && fd < 3);
80*25247Smckusick 	close(fd);
81*25247Smckusick #endif paranoid
82*25247Smckusick 
839438Smckusick #ifdef MCRT0
849438Smckusick 	monstartup(&eprol, &etext);
859438Smckusick #endif MCRT0
86*25247Smckusick 	errno = 0;
875102Smckusick 	exit(main(kfp->kargc, argv, environ));
885102Smckusick }
899438Smckusick asm("#undef _start");
909438Smckusick asm("#undef _eprol");
915102Smckusick 
929438Smckusick #ifdef MCRT0
939438Smckusick /*ARGSUSED*/
949438Smckusick exit(code)
959438Smckusick 	register int code;	/* r11 */
969438Smckusick {
979438Smckusick 	monitor(0);
989438Smckusick 	_cleanup();
999438Smckusick 	asm("	movl r11,r0");
1009438Smckusick 	asm("	chmk $1");
1019438Smckusick }
1029438Smckusick #endif MCRT0
1039438Smckusick 
1049438Smckusick #ifdef CRT0
1055102Smckusick /*
10611795Speter  * null mcount and moncontrol,
10711795Speter  * just in case some routine is compiled for profiling
1085102Smckusick  */
10911795Speter moncontrol(val)
11011795Speter 	int val;
11111795Speter {
11211795Speter 
11311795Speter }
1145397Smckusic asm("	.globl	mcount");
1155332Smckusic asm("mcount:	rsb");
1169438Smckusick #endif CRT0
117