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*55304Smckusick static char sccsid[] = "@(#)crt0.c 5.4 (Berkeley) 07/16/92"; 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 2448982Sdonn char **environ = (char **)0; 2548982Sdonn static int fd; 2648982Sdonn 2748982Sdonn extern unsigned char etext; 2848982Sdonn extern unsigned char eprol asm ("eprol"); 2948982Sdonn extern start() asm("start"); 3048982Sdonn 3148982Sdonn /* 3248982Sdonn * Some kluges: store sp at entry in environ, and 3348982Sdonn * install 16 bits of 0 at location 0 (a zero register save mask). 3448982Sdonn * These two hacks remove limits on the use of local 3548982Sdonn * and register variables in start(). 3648982Sdonn * The reason for using 'moval (sp),...' is that 'movl sp,...' generates 3748982Sdonn * a privileged instruction trap (argh). 3848982Sdonn * XXX 'addl3 $start,$2,r0; jmp (r0)' should be replaced with 3948982Sdonn * XXX 'jbr start+2' when we convert over to gas. 4048982Sdonn */ 4148982Sdonn asm(".text; .word 0; moval (sp),_environ; addl3 $start,$2,r0; jmp (r0)"); 4248982Sdonn 4348982Sdonn start() 4448982Sdonn { 4548982Sdonn struct kframe { 4648982Sdonn int kargc; 4748982Sdonn char *kargv[1]; /* size depends on kargc */ 4848982Sdonn char kargstr[1]; /* size varies */ 4948982Sdonn char kenvstr[1]; /* size varies */ 5048982Sdonn }; 5148982Sdonn register struct kframe *kfp; 5248982Sdonn register char **targv; 5348982Sdonn register char **argv; 5448982Sdonn extern int errno; 5548982Sdonn 5648982Sdonn kfp = (struct kframe *) environ; 5748982Sdonn for (argv = targv = &kfp->kargv[0]; *targv++; /* void */) 5848982Sdonn /* void */ ; 5948982Sdonn if (targv >= (char **)(*argv)) 6048982Sdonn --targv; 6148982Sdonn environ = targv; 6248982Sdonn asm("eprol:"); 6348982Sdonn 6448982Sdonn #ifdef MCRT0 6548982Sdonn monstartup(&eprol, &etext); 6648982Sdonn #endif MCRT0 6748982Sdonn errno = 0; 6848982Sdonn exit(main(kfp->kargc, argv, environ)); 6948982Sdonn } 7048982Sdonn 7148982Sdonn #ifdef MCRT0 7248982Sdonn /*ARGSUSED*/ 7348982Sdonn exit(code) 7448982Sdonn register int code; 7548982Sdonn { 7649851Smckusick _mcleanup(); 7748982Sdonn _cleanup(); 7848982Sdonn _exit(code); 7948982Sdonn } 8048982Sdonn #endif MCRT0 8148982Sdonn 8248982Sdonn #ifdef CRT0 8348982Sdonn /* 84*55304Smckusick * null moncontrol, just in case some routine is compiled for profiling 8548982Sdonn */ 8648982Sdonn moncontrol(val) 8748982Sdonn int val; 8848982Sdonn { 8948982Sdonn 9048982Sdonn } 9148982Sdonn #endif CRT0 92