121414Sdist /* 221414Sdist * Copyright (c) 1980 Regents of the University of California. 321414Sdist * All rights reserved. The Berkeley software License Agreement 421414Sdist * specifies the terms and conditions for redistribution. 521414Sdist */ 65102Smckusick 721414Sdist #ifndef lint 8*25247Smckusick static char sccsid[] = "@(#)crt0.c 5.2 (Berkeley) 10/21/85"; 921414Sdist #endif not lint 1021414Sdist 115102Smckusick /* 125102Smckusick * C start up routine. 135102Smckusick * Robert Henry, UCB, 20 Oct 81 145102Smckusick * 155102Smckusick * We make the following (true) assumptions: 165102Smckusick * 1) when the kernel calls start, it does a jump to location 2, 175102Smckusick * and thus avoids the register save mask. We are NOT called 185102Smckusick * with a calls! see sys1.c:setregs(). 195102Smckusick * 2) The only register variable that we can trust is sp, 205102Smckusick * which points to the base of the kernel calling frame. 215102Smckusick * Do NOT believe the documentation in exec(2) regarding the 225102Smckusick * values of fp and ap. 235102Smckusick * 3) We can allocate as many register variables as we want, 245102Smckusick * and don't have to save them for anybody. 255102Smckusick * 4) Because of the ways that asm's work, we can't have 265102Smckusick * any automatic variables allocated on the stack, because 275102Smckusick * we must catch the value of sp before any automatics are 285102Smckusick * allocated. 295102Smckusick */ 305102Smckusick 319438Smckusick char **environ = (char **)0; 32*25247Smckusick static int fd; 335102Smckusick 345332Smckusic asm("#define _start start"); 359438Smckusick asm("#define _eprol eprol"); 369438Smckusick extern unsigned char etext; 379438Smckusick extern unsigned char eprol; 385102Smckusick start() 395102Smckusick { 405102Smckusick struct kframe { 415102Smckusick int kargc; 425102Smckusick char *kargv[1]; /* size depends on kargc */ 435102Smckusick char kargstr[1]; /* size varies */ 445102Smckusick char kenvstr[1]; /* size varies */ 455102Smckusick }; 465102Smckusick /* 475102Smckusick * ALL REGISTER VARIABLES!!! 485102Smckusick */ 496852Srrh register int r11; /* needed for init */ 506852Srrh register struct kframe *kfp; /* r10 */ 515102Smckusick register char **targv; 525102Smckusick register char **argv; 53*25247Smckusick extern int errno; 545102Smckusick 555102Smckusick #ifdef lint 565102Smckusick kfp = 0; 579438Smckusick initcode = initcode = 0; 585102Smckusick #else not lint 596852Srrh asm(" movl sp,r10"); /* catch it quick */ 605102Smckusick #endif not lint 615102Smckusick for (argv = targv = &kfp->kargv[0]; *targv++; /* void */) 625102Smckusick /* void */ ; 635102Smckusick if (targv >= (char **)(*argv)) 645102Smckusick --targv; 655102Smckusick environ = targv; 669438Smckusick asm("eprol:"); 67*25247Smckusick 68*25247Smckusick #ifdef paranoid 69*25247Smckusick /* 70*25247Smckusick * The standard I/O library assumes that file descriptors 0, 1, and 2 71*25247Smckusick * are open. If one of these descriptors is closed prior to the start 72*25247Smckusick * of the process, I/O gets very confused. To avoid this problem, we 73*25247Smckusick * insure that the first three file descriptors are open before calling 74*25247Smckusick * main(). Normally this is undefined, as it adds two unnecessary 75*25247Smckusick * system calls. 76*25247Smckusick */ 77*25247Smckusick do { 78*25247Smckusick fd = open("/dev/null", 2); 79*25247Smckusick } while (fd >= 0 && fd < 3); 80*25247Smckusick close(fd); 81*25247Smckusick #endif paranoid 82*25247Smckusick 839438Smckusick #ifdef MCRT0 849438Smckusick monstartup(&eprol, &etext); 859438Smckusick #endif MCRT0 86*25247Smckusick errno = 0; 875102Smckusick exit(main(kfp->kargc, argv, environ)); 885102Smckusick } 899438Smckusick asm("#undef _start"); 909438Smckusick asm("#undef _eprol"); 915102Smckusick 929438Smckusick #ifdef MCRT0 939438Smckusick /*ARGSUSED*/ 949438Smckusick exit(code) 959438Smckusick register int code; /* r11 */ 969438Smckusick { 979438Smckusick monitor(0); 989438Smckusick _cleanup(); 999438Smckusick asm(" movl r11,r0"); 1009438Smckusick asm(" chmk $1"); 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