1*21414Sdist /* 2*21414Sdist * Copyright (c) 1980 Regents of the University of California. 3*21414Sdist * All rights reserved. The Berkeley software License Agreement 4*21414Sdist * specifies the terms and conditions for redistribution. 5*21414Sdist */ 65102Smckusick 7*21414Sdist #ifndef lint 8*21414Sdist static char sccsid[] = "@(#)crt0.c 5.1 (Berkeley) 05/30/85"; 9*21414Sdist #endif not lint 10*21414Sdist 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; 325102Smckusick 335332Smckusic asm("#define _start start"); 349438Smckusick asm("#define _eprol eprol"); 359438Smckusick extern unsigned char etext; 369438Smckusick extern unsigned char eprol; 375102Smckusick start() 385102Smckusick { 395102Smckusick struct kframe { 405102Smckusick int kargc; 415102Smckusick char *kargv[1]; /* size depends on kargc */ 425102Smckusick char kargstr[1]; /* size varies */ 435102Smckusick char kenvstr[1]; /* size varies */ 445102Smckusick }; 455102Smckusick /* 465102Smckusick * ALL REGISTER VARIABLES!!! 475102Smckusick */ 486852Srrh register int r11; /* needed for init */ 496852Srrh register struct kframe *kfp; /* r10 */ 505102Smckusick register char **targv; 515102Smckusick register char **argv; 525102Smckusick 535102Smckusick #ifdef lint 545102Smckusick kfp = 0; 559438Smckusick initcode = initcode = 0; 565102Smckusick #else not lint 576852Srrh asm(" movl sp,r10"); /* catch it quick */ 585102Smckusick #endif not lint 595102Smckusick for (argv = targv = &kfp->kargv[0]; *targv++; /* void */) 605102Smckusick /* void */ ; 615102Smckusick if (targv >= (char **)(*argv)) 625102Smckusick --targv; 635102Smckusick environ = targv; 649438Smckusick asm("eprol:"); 659438Smckusick #ifdef MCRT0 669438Smckusick monstartup(&eprol, &etext); 679438Smckusick #endif MCRT0 685102Smckusick exit(main(kfp->kargc, argv, environ)); 695102Smckusick } 709438Smckusick asm("#undef _start"); 719438Smckusick asm("#undef _eprol"); 725102Smckusick 739438Smckusick #ifdef MCRT0 749438Smckusick /*ARGSUSED*/ 759438Smckusick exit(code) 769438Smckusick register int code; /* r11 */ 779438Smckusick { 789438Smckusick monitor(0); 799438Smckusick _cleanup(); 809438Smckusick asm(" movl r11,r0"); 819438Smckusick asm(" chmk $1"); 829438Smckusick } 839438Smckusick #endif MCRT0 849438Smckusick 859438Smckusick #ifdef CRT0 865102Smckusick /* 8711795Speter * null mcount and moncontrol, 8811795Speter * just in case some routine is compiled for profiling 895102Smckusick */ 9011795Speter moncontrol(val) 9111795Speter int val; 9211795Speter { 9311795Speter 9411795Speter } 955397Smckusic asm(" .globl mcount"); 965332Smckusic asm("mcount: rsb"); 979438Smckusick #endif CRT0 98