1 /*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)crt0.c 5.5 (Berkeley) 05/21/91"; 10 #endif /* not lint */ 11 12 /* 13 * C start up routine. 14 * Robert Henry, UCB, 20 Oct 81 15 * 16 * We make the following (true) assumptions: 17 * 1) when the kernel calls start, it does a jump to location 2, 18 * and thus avoids the register save mask. We are NOT called 19 * with a calls! see sys1.c:setregs(). 20 * 2) The only register variable that we can trust is sp, 21 * which points to the base of the kernel calling frame. 22 * Do NOT believe the documentation in exec(2) regarding the 23 * values of fp and ap. 24 * 3) We can allocate as many register variables as we want, 25 * and don't have to save them for anybody. 26 * 4) Because of the ways that asm's work, we can't have 27 * any automatic variables allocated on the stack, because 28 * we must catch the value of sp before any automatics are 29 * allocated. 30 */ 31 32 char **environ = (char **)0; 33 static int fd; 34 35 extern unsigned char etext; 36 extern unsigned char eprol asm ("eprol"); 37 extern start() asm("start"); 38 39 asm(".text; orb #0,d0"); /* 32 bits of zero at location 0 */ 40 41 start() 42 { 43 struct kframe { 44 int kargc; 45 char *kargv[1]; /* size depends on kargc */ 46 char kargstr[1]; /* size varies */ 47 char kenvstr[1]; /* size varies */ 48 }; 49 /* 50 * ALL REGISTER VARIABLES!!! 51 */ 52 register struct kframe *kfp; /* r10 */ 53 register char **targv; 54 register char **argv; 55 extern int errno; 56 57 #ifdef lint 58 kfp = 0; 59 initcode = initcode = 0; 60 #else not lint 61 asm("lea a6@(4),%0" : "=r" (kfp)); /* catch it quick */ 62 #endif not lint 63 for (argv = targv = &kfp->kargv[0]; *targv++; /* void */) 64 /* void */ ; 65 if (targv >= (char **)(*argv)) 66 --targv; 67 environ = targv; 68 asm("eprol:"); 69 70 #ifdef paranoid 71 /* 72 * The standard I/O library assumes that file descriptors 0, 1, and 2 73 * are open. If one of these descriptors is closed prior to the start 74 * of the process, I/O gets very confused. To avoid this problem, we 75 * insure that the first three file descriptors are open before calling 76 * main(). Normally this is undefined, as it adds two unnecessary 77 * system calls. 78 */ 79 do { 80 fd = open("/dev/null", 2); 81 } while (fd >= 0 && fd < 3); 82 close(fd); 83 #endif paranoid 84 85 #ifdef MCRT0 86 monstartup(&eprol, &etext); 87 #endif MCRT0 88 errno = 0; 89 exit(main(kfp->kargc, argv, environ)); 90 } 91 92 #ifdef MCRT0 93 /*ARGSUSED*/ 94 exit(code) 95 register int code; 96 { 97 _mcleanup(); 98 _cleanup(); 99 asm("movl %1,sp@-" : "=m" (*(char *)0) : "r" (code)); 100 asm("subql #4,sp"); 101 asm("movl #1,d0"); 102 asm("trap #0"); 103 } 104 #endif MCRT0 105 106 #ifdef CRT0 107 /* 108 * null mcount and moncontrol, 109 * just in case some routine is compiled for profiling 110 */ 111 moncontrol(val) 112 int val; 113 { 114 115 } 116 asm(".globl mcount"); 117 asm("mcount: rts"); 118 #endif CRT0 119