1*48982Sdonn /*- 2*48982Sdonn * Copyright (c) 1991 The Regents of the University of California. 3*48982Sdonn * All rights reserved. 4*48982Sdonn * 5*48982Sdonn * %sccs.include.proprietary.c% 6*48982Sdonn */ 7*48982Sdonn 8*48982Sdonn #ifndef lint 9*48982Sdonn static char sccsid[] = "@(#)crt0.c 5.1 (Berkeley) 05/03/91"; 10*48982Sdonn #endif /* not lint */ 11*48982Sdonn 12*48982Sdonn /* 13*48982Sdonn * C start up routine. 14*48982Sdonn * Robert Henry, UCB, 20 Oct 81 15*48982Sdonn * 16*48982Sdonn * We make the following (true) assumptions: 17*48982Sdonn * 1) When the kernel calls start, it does a jump to location 2, 18*48982Sdonn * and thus avoids the register save mask. We are NOT called 19*48982Sdonn * with a calls! 20*48982Sdonn * 2) The only register variable that we can trust is sp, 21*48982Sdonn * which points to the base of the kernel calling frame. 22*48982Sdonn */ 23*48982Sdonn 24*48982Sdonn char **environ = (char **)0; 25*48982Sdonn static int fd; 26*48982Sdonn 27*48982Sdonn extern unsigned char etext; 28*48982Sdonn extern unsigned char eprol asm ("eprol"); 29*48982Sdonn extern start() asm("start"); 30*48982Sdonn 31*48982Sdonn /* 32*48982Sdonn * Some kluges: store sp at entry in environ, and 33*48982Sdonn * install 16 bits of 0 at location 0 (a zero register save mask). 34*48982Sdonn * These two hacks remove limits on the use of local 35*48982Sdonn * and register variables in start(). 36*48982Sdonn * The reason for using 'moval (sp),...' is that 'movl sp,...' generates 37*48982Sdonn * a privileged instruction trap (argh). 38*48982Sdonn * XXX 'addl3 $start,$2,r0; jmp (r0)' should be replaced with 39*48982Sdonn * XXX 'jbr start+2' when we convert over to gas. 40*48982Sdonn */ 41*48982Sdonn asm(".text; .word 0; moval (sp),_environ; addl3 $start,$2,r0; jmp (r0)"); 42*48982Sdonn 43*48982Sdonn start() 44*48982Sdonn { 45*48982Sdonn struct kframe { 46*48982Sdonn int kargc; 47*48982Sdonn char *kargv[1]; /* size depends on kargc */ 48*48982Sdonn char kargstr[1]; /* size varies */ 49*48982Sdonn char kenvstr[1]; /* size varies */ 50*48982Sdonn }; 51*48982Sdonn register struct kframe *kfp; 52*48982Sdonn register char **targv; 53*48982Sdonn register char **argv; 54*48982Sdonn extern int errno; 55*48982Sdonn 56*48982Sdonn kfp = (struct kframe *) environ; 57*48982Sdonn for (argv = targv = &kfp->kargv[0]; *targv++; /* void */) 58*48982Sdonn /* void */ ; 59*48982Sdonn if (targv >= (char **)(*argv)) 60*48982Sdonn --targv; 61*48982Sdonn environ = targv; 62*48982Sdonn asm("eprol:"); 63*48982Sdonn 64*48982Sdonn #ifdef MCRT0 65*48982Sdonn monstartup(&eprol, &etext); 66*48982Sdonn #endif MCRT0 67*48982Sdonn errno = 0; 68*48982Sdonn exit(main(kfp->kargc, argv, environ)); 69*48982Sdonn } 70*48982Sdonn 71*48982Sdonn #ifdef MCRT0 72*48982Sdonn /*ARGSUSED*/ 73*48982Sdonn exit(code) 74*48982Sdonn register int code; 75*48982Sdonn { 76*48982Sdonn monitor(0); 77*48982Sdonn _cleanup(); 78*48982Sdonn _exit(code); 79*48982Sdonn } 80*48982Sdonn #endif MCRT0 81*48982Sdonn 82*48982Sdonn #ifdef CRT0 83*48982Sdonn /* 84*48982Sdonn * null mcount and moncontrol, 85*48982Sdonn * just in case some routine is compiled for profiling 86*48982Sdonn */ 87*48982Sdonn moncontrol(val) 88*48982Sdonn int val; 89*48982Sdonn { 90*48982Sdonn 91*48982Sdonn } 92*48982Sdonn 93*48982Sdonn mcount() 94*48982Sdonn { 95*48982Sdonn 96*48982Sdonn } 97*48982Sdonn #endif CRT0 98