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