147882Sbostic /*- 2*48802Sdonn * Copyright (c) 1991 The Regents of the University of California. 347882Sbostic * All rights reserved. 447882Sbostic * 547882Sbostic * %sccs.include.proprietary.c% 644279Sbostic */ 744279Sbostic 8*48802Sdonn #ifndef lint 9*48802Sdonn static char sccsid[] = "@(#)crt0.c 5.3 (Berkeley) 04/28/91"; 10*48802Sdonn #endif /* not lint */ 1144279Sbostic 1244279Sbostic /* 1344279Sbostic * C start up routine. 1444279Sbostic * Robert Henry, UCB, 20 Oct 81 1544279Sbostic * 1644279Sbostic * We make the following (true) assumptions: 1744279Sbostic * 1) when the kernel calls start, it does a jump to location 2, 1844279Sbostic * and thus avoids the register save mask. We are NOT called 1944279Sbostic * with a calls! see sys1.c:setregs(). 2044279Sbostic * 2) The only register variable that we can trust is sp, 2144279Sbostic * which points to the base of the kernel calling frame. 2244279Sbostic * Do NOT believe the documentation in exec(2) regarding the 2344279Sbostic * values of fp and ap. 2444279Sbostic * 3) We can allocate as many register variables as we want, 2544279Sbostic * and don't have to save them for anybody. 2644279Sbostic * 4) Because of the ways that asm's work, we can't have 2744279Sbostic * any automatic variables allocated on the stack, because 2844279Sbostic * we must catch the value of sp before any automatics are 2944279Sbostic * allocated. 3044279Sbostic */ 3144279Sbostic 3244279Sbostic char **environ = (char **)0; 3344279Sbostic static int fd; 3444279Sbostic 35*48802Sdonn extern unsigned char etext; 36*48802Sdonn extern unsigned char eprol asm ("eprol"); 37*48802Sdonn extern start() asm("start"); 3844279Sbostic 39*48802Sdonn asm(".text; orb #0,d0"); /* 32 bits of zero at location 0 */ 4044279Sbostic 4144279Sbostic start() 4244279Sbostic { 4344279Sbostic struct kframe { 4444279Sbostic int kargc; 4544279Sbostic char *kargv[1]; /* size depends on kargc */ 4644279Sbostic char kargstr[1]; /* size varies */ 4744279Sbostic char kenvstr[1]; /* size varies */ 4844279Sbostic }; 4944279Sbostic /* 5044279Sbostic * ALL REGISTER VARIABLES!!! 5144279Sbostic */ 52*48802Sdonn register struct kframe *kfp; /* r10 */ 5344279Sbostic register char **targv; 5444279Sbostic register char **argv; 5544279Sbostic extern int errno; 5644279Sbostic 5744279Sbostic #ifdef lint 5844279Sbostic kfp = 0; 5944279Sbostic initcode = initcode = 0; 6044279Sbostic #else not lint 6144279Sbostic asm("lea a6@(4),%0" : "=r" (kfp)); /* catch it quick */ 6244279Sbostic #endif not lint 6344279Sbostic for (argv = targv = &kfp->kargv[0]; *targv++; /* void */) 6444279Sbostic /* void */ ; 6544279Sbostic if (targv >= (char **)(*argv)) 6644279Sbostic --targv; 6744279Sbostic environ = targv; 6844279Sbostic asm("eprol:"); 6944279Sbostic 7044279Sbostic #ifdef paranoid 7144279Sbostic /* 7244279Sbostic * The standard I/O library assumes that file descriptors 0, 1, and 2 7344279Sbostic * are open. If one of these descriptors is closed prior to the start 7444279Sbostic * of the process, I/O gets very confused. To avoid this problem, we 7544279Sbostic * insure that the first three file descriptors are open before calling 7644279Sbostic * main(). Normally this is undefined, as it adds two unnecessary 7744279Sbostic * system calls. 7844279Sbostic */ 7944279Sbostic do { 8044279Sbostic fd = open("/dev/null", 2); 8144279Sbostic } while (fd >= 0 && fd < 3); 8244279Sbostic close(fd); 8344279Sbostic #endif paranoid 8444279Sbostic 8544279Sbostic #ifdef MCRT0 8644279Sbostic monstartup(&eprol, &etext); 8744279Sbostic #endif MCRT0 8844279Sbostic errno = 0; 8944279Sbostic exit(main(kfp->kargc, argv, environ)); 9044279Sbostic } 9144279Sbostic 9244279Sbostic #ifdef MCRT0 9344279Sbostic /*ARGSUSED*/ 9444279Sbostic exit(code) 95*48802Sdonn register int code; 9644279Sbostic { 9744279Sbostic monitor(0); 9844279Sbostic _cleanup(); 9944279Sbostic asm("movl %1,sp@-" : "=m" (*(char *)0) : "r" (code)); 100*48802Sdonn asm("subql #4,sp"); 101*48802Sdonn asm("movl #1,d0"); 102*48802Sdonn asm("trap #0"); 10344279Sbostic } 10444279Sbostic #endif MCRT0 10544279Sbostic 10644279Sbostic #ifdef CRT0 10744279Sbostic /* 10844279Sbostic * null mcount and moncontrol, 10944279Sbostic * just in case some routine is compiled for profiling 11044279Sbostic */ 11144279Sbostic moncontrol(val) 11244279Sbostic int val; 11344279Sbostic { 11444279Sbostic 11544279Sbostic } 116*48802Sdonn asm(".globl mcount"); 117*48802Sdonn asm("mcount: rts"); 11844279Sbostic #endif CRT0 119