1*47882Sbostic /*- 2*47882Sbostic * Copyright (c) 1990 The Regents of the University of California. 3*47882Sbostic * All rights reserved. 4*47882Sbostic * 5*47882Sbostic * %sccs.include.proprietary.c% 644279Sbostic */ 744279Sbostic 844279Sbostic #if defined(LIBC_SCCS) && !defined(lint) 9*47882Sbostic static char sccsid[] = "@(#)crt0.c 5.2 (Berkeley) 04/12/91"; 10*47882Sbostic #endif /* LIBC_SCCS and 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 3544279Sbostic asm("#define _start start"); 3644279Sbostic asm("#define _eprol eprol"); 3744279Sbostic 3844279Sbostic #ifdef hp300 3944279Sbostic asm("#define link .long 0; linkw"); /* Yuk!! */ 4044279Sbostic #endif 4144279Sbostic 4244279Sbostic extern unsigned char etext; 4344279Sbostic extern unsigned char eprol; 4444279Sbostic start() 4544279Sbostic { 4644279Sbostic struct kframe { 4744279Sbostic int kargc; 4844279Sbostic char *kargv[1]; /* size depends on kargc */ 4944279Sbostic char kargstr[1]; /* size varies */ 5044279Sbostic char kenvstr[1]; /* size varies */ 5144279Sbostic }; 5244279Sbostic /* 5344279Sbostic * ALL REGISTER VARIABLES!!! 5444279Sbostic */ 5544279Sbostic register int d7; /* needed for init (this will be 5644279Sbostic a problem with GCC) */ 5744279Sbostic register struct kframe *kfp; /* PCC a5 */ 5844279Sbostic register char **targv; 5944279Sbostic register char **argv; 6044279Sbostic extern int errno; 6144279Sbostic 6244279Sbostic #ifdef lint 6344279Sbostic kfp = 0; 6444279Sbostic initcode = initcode = 0; 6544279Sbostic #else not lint 6644279Sbostic #ifdef __GNUC__ 6744279Sbostic asm("lea a6@(4),%0" : "=r" (kfp)); /* catch it quick */ 6844279Sbostic #else 6944279Sbostic asm(" lea a6@(4),a5"); /* catch it quick */ 7044279Sbostic #endif 7144279Sbostic #endif not lint 7244279Sbostic for (argv = targv = &kfp->kargv[0]; *targv++; /* void */) 7344279Sbostic /* void */ ; 7444279Sbostic if (targv >= (char **)(*argv)) 7544279Sbostic --targv; 7644279Sbostic environ = targv; 7744279Sbostic asm("eprol:"); 7844279Sbostic 7944279Sbostic #ifdef paranoid 8044279Sbostic /* 8144279Sbostic * The standard I/O library assumes that file descriptors 0, 1, and 2 8244279Sbostic * are open. If one of these descriptors is closed prior to the start 8344279Sbostic * of the process, I/O gets very confused. To avoid this problem, we 8444279Sbostic * insure that the first three file descriptors are open before calling 8544279Sbostic * main(). Normally this is undefined, as it adds two unnecessary 8644279Sbostic * system calls. 8744279Sbostic */ 8844279Sbostic do { 8944279Sbostic fd = open("/dev/null", 2); 9044279Sbostic } while (fd >= 0 && fd < 3); 9144279Sbostic close(fd); 9244279Sbostic #endif paranoid 9344279Sbostic 9444279Sbostic #ifdef MCRT0 9544279Sbostic monstartup(&eprol, &etext); 9644279Sbostic #endif MCRT0 9744279Sbostic errno = 0; 9844279Sbostic exit(main(kfp->kargc, argv, environ)); 9944279Sbostic } 10044279Sbostic asm("#undef link"); 10144279Sbostic asm("#undef _start"); 10244279Sbostic asm("#undef _eprol"); 10344279Sbostic 10444279Sbostic #ifdef MCRT0 10544279Sbostic /*ARGSUSED*/ 10644279Sbostic exit(code) 10744279Sbostic register int code; /* PCC d7 */ 10844279Sbostic { 10944279Sbostic monitor(0); 11044279Sbostic _cleanup(); 11144279Sbostic #ifdef __GNUC__ 11244279Sbostic asm("movl %1,sp@-" : "=m" (*(char *)0) : "r" (code)); 11344279Sbostic #else 11444279Sbostic asm(" movl d7,sp@-"); 11544279Sbostic #endif 11644279Sbostic asm(" subql #4,sp"); 11744279Sbostic asm(" movl #1,d0"); 11844279Sbostic asm(" trap #0"); 11944279Sbostic } 12044279Sbostic #endif MCRT0 12144279Sbostic 12244279Sbostic #ifdef CRT0 12344279Sbostic /* 12444279Sbostic * null mcount and moncontrol, 12544279Sbostic * just in case some routine is compiled for profiling 12644279Sbostic */ 12744279Sbostic moncontrol(val) 12844279Sbostic int val; 12944279Sbostic { 13044279Sbostic 13144279Sbostic } 13244279Sbostic asm(" .globl mcount"); 13344279Sbostic asm("mcount: rts"); 13444279Sbostic #endif CRT0 135