148982Sdonn /*- 248982Sdonn * Copyright (c) 1991 The Regents of the University of California. 348982Sdonn * All rights reserved. 448982Sdonn * 549277Sbostic * %sccs.include.redist.c% 648982Sdonn */ 748982Sdonn 848982Sdonn #ifndef lint 9*57962Sbostic static char sccsid[] = "@(#)crt0.c 5.5 (Berkeley) 02/12/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 24*57962Sbostic #include <stddef.h> 25*57962Sbostic #include <stdlib.h> 26*57962Sbostic #include <string.h> 27*57962Sbostic 2848982Sdonn char **environ = (char **)0; 29*57962Sbostic static char empty[1]; 30*57962Sbostic 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 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); 72*57962Sbostic #endif 7348982Sdonn errno = 0; 74*57962Sbostic if (argv[0]) 75*57962Sbostic if ((__progname = strrchr(argv[0], '/')) == NULL) 76*57962Sbostic __progname = argv[0]; 77*57962Sbostic else 78*57962Sbostic ++__progname; 7948982Sdonn exit(main(kfp->kargc, argv, environ)); 8048982Sdonn } 8148982Sdonn 8248982Sdonn #ifdef MCRT0 8348982Sdonn /*ARGSUSED*/ 8448982Sdonn exit(code) 8548982Sdonn register int code; 8648982Sdonn { 8749851Smckusick _mcleanup(); 8848982Sdonn _cleanup(); 8948982Sdonn _exit(code); 9048982Sdonn } 91*57962Sbostic #endif 9248982Sdonn 9348982Sdonn #ifdef CRT0 9448982Sdonn /* 9555304Smckusick * null moncontrol, just in case some routine is compiled for profiling 9648982Sdonn */ 9748982Sdonn moncontrol(val) 9848982Sdonn int val; 9948982Sdonn { 10048982Sdonn 10148982Sdonn } 102*57962Sbostic #endif 103