1*47884Sbostic /*- 2*47884Sbostic * Copyright (c) 1982 The Regents of the University of California. 3*47884Sbostic * All rights reserved. 4*47884Sbostic * 5*47884Sbostic * %sccs.include.proprietary.c% 621414Sdist */ 75102Smckusick 826668Sdonn #if defined(LIBC_SCCS) && !defined(lint) 9*47884Sbostic static char sccsid[] = "@(#)crt0.c 5.5 (Berkeley) 04/12/91"; 10*47884Sbostic #endif /* LIBC_SCCS and not lint */ 1121414Sdist 125102Smckusick /* 135102Smckusick * C start up routine. 145102Smckusick * Robert Henry, UCB, 20 Oct 81 155102Smckusick * 165102Smckusick * We make the following (true) assumptions: 175102Smckusick * 1) when the kernel calls start, it does a jump to location 2, 185102Smckusick * and thus avoids the register save mask. We are NOT called 195102Smckusick * with a calls! see sys1.c:setregs(). 205102Smckusick * 2) The only register variable that we can trust is sp, 215102Smckusick * which points to the base of the kernel calling frame. 225102Smckusick * Do NOT believe the documentation in exec(2) regarding the 235102Smckusick * values of fp and ap. 245102Smckusick * 3) We can allocate as many register variables as we want, 255102Smckusick * and don't have to save them for anybody. 265102Smckusick * 4) Because of the ways that asm's work, we can't have 275102Smckusick * any automatic variables allocated on the stack, because 285102Smckusick * we must catch the value of sp before any automatics are 295102Smckusick * allocated. 305102Smckusick */ 315102Smckusick 329438Smckusick char **environ = (char **)0; 3325247Smckusick static int fd; 345102Smckusick 355332Smckusic asm("#define _start start"); 369438Smckusick asm("#define _eprol eprol"); 379438Smckusick extern unsigned char etext; 389438Smckusick extern unsigned char eprol; 395102Smckusick start() 405102Smckusick { 415102Smckusick struct kframe { 425102Smckusick int kargc; 435102Smckusick char *kargv[1]; /* size depends on kargc */ 445102Smckusick char kargstr[1]; /* size varies */ 455102Smckusick char kenvstr[1]; /* size varies */ 465102Smckusick }; 475102Smckusick /* 485102Smckusick * ALL REGISTER VARIABLES!!! 495102Smckusick */ 506852Srrh register int r11; /* needed for init */ 516852Srrh register struct kframe *kfp; /* r10 */ 525102Smckusick register char **targv; 535102Smckusick register char **argv; 5425247Smckusick extern int errno; 555102Smckusick 565102Smckusick #ifdef lint 575102Smckusick kfp = 0; 589438Smckusick initcode = initcode = 0; 595102Smckusick #else not lint 606852Srrh asm(" movl sp,r10"); /* catch it quick */ 615102Smckusick #endif not lint 625102Smckusick for (argv = targv = &kfp->kargv[0]; *targv++; /* void */) 635102Smckusick /* void */ ; 645102Smckusick if (targv >= (char **)(*argv)) 655102Smckusick --targv; 665102Smckusick environ = targv; 679438Smckusick asm("eprol:"); 6825247Smckusick 6925247Smckusick #ifdef paranoid 7025247Smckusick /* 7125247Smckusick * The standard I/O library assumes that file descriptors 0, 1, and 2 7225247Smckusick * are open. If one of these descriptors is closed prior to the start 7325247Smckusick * of the process, I/O gets very confused. To avoid this problem, we 7425247Smckusick * insure that the first three file descriptors are open before calling 7525247Smckusick * main(). Normally this is undefined, as it adds two unnecessary 7625247Smckusick * system calls. 7725247Smckusick */ 7825247Smckusick do { 7925247Smckusick fd = open("/dev/null", 2); 8025247Smckusick } while (fd >= 0 && fd < 3); 8125247Smckusick close(fd); 8225247Smckusick #endif paranoid 8325247Smckusick 849438Smckusick #ifdef MCRT0 859438Smckusick monstartup(&eprol, &etext); 869438Smckusick #endif MCRT0 8725247Smckusick errno = 0; 885102Smckusick exit(main(kfp->kargc, argv, environ)); 895102Smckusick } 909438Smckusick asm("#undef _start"); 919438Smckusick asm("#undef _eprol"); 925102Smckusick 939438Smckusick #ifdef MCRT0 949438Smckusick /*ARGSUSED*/ 959438Smckusick exit(code) 969438Smckusick register int code; /* r11 */ 979438Smckusick { 989438Smckusick monitor(0); 999438Smckusick _cleanup(); 10033363Smckusick _exit(code); 1019438Smckusick } 1029438Smckusick #endif MCRT0 1039438Smckusick 1049438Smckusick #ifdef CRT0 1055102Smckusick /* 10611795Speter * null mcount and moncontrol, 10711795Speter * just in case some routine is compiled for profiling 1085102Smckusick */ 10911795Speter moncontrol(val) 11011795Speter int val; 11111795Speter { 11211795Speter 11311795Speter } 1145397Smckusic asm(" .globl mcount"); 1155332Smckusic asm("mcount: rsb"); 1169438Smckusick #endif CRT0 117