148982Sdonn /*-
2*60983Sbostic * Copyright (c) 1991, 1993
3*60983Sbostic * The Regents of the University of California. All rights reserved.
448982Sdonn *
549277Sbostic * %sccs.include.redist.c%
648982Sdonn */
748982Sdonn
848982Sdonn #ifndef lint
9*60983Sbostic static char sccsid[] = "@(#)crt0.c 8.1 (Berkeley) 06/01/93";
1048982Sdonn #endif /* not lint */
1148982Sdonn
1248982Sdonn /*
1348982Sdonn * C start up routine.
1448982Sdonn * Robert Henry, UCB, 20 Oct 81
1548982Sdonn *
1648982Sdonn * We make the following (true) assumptions:
1748982Sdonn * 1) When the kernel calls start, it does a jump to location 2,
1848982Sdonn * and thus avoids the register save mask. We are NOT called
1948982Sdonn * with a calls!
2048982Sdonn * 2) The only register variable that we can trust is sp,
2148982Sdonn * which points to the base of the kernel calling frame.
2248982Sdonn */
2348982Sdonn
2457962Sbostic #include <stddef.h>
2557962Sbostic #include <stdlib.h>
2657962Sbostic #include <string.h>
2757962Sbostic
2848982Sdonn char **environ = (char **)0;
2957962Sbostic static char empty[1];
3057962Sbostic char *__progname = empty;
3148982Sdonn static int fd;
3248982Sdonn
3348982Sdonn extern unsigned char etext;
3448982Sdonn extern unsigned char eprol asm ("eprol");
3548982Sdonn extern start() asm("start");
3648982Sdonn
3748982Sdonn /*
3848982Sdonn * Some kluges: store sp at entry in environ, and
3948982Sdonn * install 16 bits of 0 at location 0 (a zero register save mask).
4048982Sdonn * These two hacks remove limits on the use of local
4148982Sdonn * and register variables in start().
4248982Sdonn * The reason for using 'moval (sp),...' is that 'movl sp,...' generates
4348982Sdonn * a privileged instruction trap (argh).
4448982Sdonn * XXX 'addl3 $start,$2,r0; jmp (r0)' should be replaced with
4548982Sdonn * XXX 'jbr start+2' when we convert over to gas.
4648982Sdonn */
4748982Sdonn asm(".text; .word 0; moval (sp),_environ; addl3 $start,$2,r0; jmp (r0)");
4848982Sdonn
start()4948982Sdonn start()
5048982Sdonn {
5148982Sdonn struct kframe {
5248982Sdonn int kargc;
5348982Sdonn char *kargv[1]; /* size depends on kargc */
5448982Sdonn char kargstr[1]; /* size varies */
5548982Sdonn char kenvstr[1]; /* size varies */
5648982Sdonn };
5748982Sdonn register struct kframe *kfp;
5848982Sdonn register char **targv;
5948982Sdonn register char **argv;
6048982Sdonn extern int errno;
6148982Sdonn
6248982Sdonn kfp = (struct kframe *) environ;
6348982Sdonn for (argv = targv = &kfp->kargv[0]; *targv++; /* void */)
6448982Sdonn /* void */ ;
6548982Sdonn if (targv >= (char **)(*argv))
6648982Sdonn --targv;
6748982Sdonn environ = targv;
6848982Sdonn asm("eprol:");
6948982Sdonn
7048982Sdonn #ifdef MCRT0
7148982Sdonn monstartup(&eprol, &etext);
7257962Sbostic #endif
7348982Sdonn errno = 0;
7457962Sbostic if (argv[0])
7557962Sbostic if ((__progname = strrchr(argv[0], '/')) == NULL)
7657962Sbostic __progname = argv[0];
7757962Sbostic else
7857962Sbostic ++__progname;
7948982Sdonn exit(main(kfp->kargc, argv, environ));
8048982Sdonn }
8148982Sdonn
8248982Sdonn #ifdef MCRT0
8348982Sdonn /*ARGSUSED*/
exit(code)8448982Sdonn exit(code)
8548982Sdonn register int code;
8648982Sdonn {
8749851Smckusick _mcleanup();
8848982Sdonn _cleanup();
8948982Sdonn _exit(code);
9048982Sdonn }
9157962Sbostic #endif
9248982Sdonn
9348982Sdonn #ifdef CRT0
9448982Sdonn /*
9555304Smckusick * null moncontrol, just in case some routine is compiled for profiling
9648982Sdonn */
moncontrol(val)9748982Sdonn moncontrol(val)
9848982Sdonn int val;
9948982Sdonn {
10048982Sdonn
10148982Sdonn }
10257962Sbostic #endif
103