|
|
1.1 ! root 1: /* C code startup routine. ! 2: Copyright (C) 1985, 1986 Free Software Foundation, Inc. ! 3: ! 4: This program is free software; you can redistribute it and/or modify ! 5: it under the terms of the GNU General Public License as published by ! 6: the Free Software Foundation; either version 1, or (at your option) ! 7: any later version. ! 8: ! 9: This program is distributed in the hope that it will be useful, ! 10: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 12: GNU General Public License for more details. ! 13: ! 14: You should have received a copy of the GNU General Public License ! 15: along with this program; if not, write to the Free Software ! 16: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 17: ! 18: In other words, you are welcome to use, share and improve this program. ! 19: You are forbidden to forbid anyone else to use, share and improve ! 20: what you give them. Help stamp out software-hoarding! */ ! 21: ! 22: ! 23: /* The standard Vax 4.2 Unix crt0.c cannot be used for Emacs ! 24: because it makes `envron' an initialized variable. ! 25: It is easiest to have a special crt0.c on all machines ! 26: though I don't know whether other machines actually need it. */ ! 27: ! 28: /* On the vax and 68000, in BSD4.2 and USG5.2, ! 29: this is the data format on startup: ! 30: (vax) ap and fp are unpredictable as far as I know; don't use them. ! 31: sp -> word containing argc ! 32: word pointing to first arg string ! 33: [word pointing to next arg string]... 0 or more times ! 34: 0 ! 35: Optionally: ! 36: [word pointing to environment variable]... 1 or more times ! 37: ... ! 38: 0 ! 39: And always: ! 40: first arg string ! 41: [next arg string]... 0 or more times ! 42: */ ! 43: ! 44: /* On the 16000, at least in the one 4.2 system I know about, ! 45: the initial data format is ! 46: sp -> word containing argc ! 47: word containing argp ! 48: word pointing to first arg string, and so on as above ! 49: */ ! 50: ! 51: #include "config.h" ! 52: ! 53: /* ******** WARNING ******** ! 54: Do not insert any data definitions before data_start! ! 55: Since this is the first file linked, the address of the following ! 56: variable should correspond to the start of initialized data space. ! 57: On some systems this is a constant that is independent of the text ! 58: size for shared executables. On others, it is a function of the ! 59: text size. In short, this seems to be the most portable way to ! 60: discover the start of initialized data space dynamically at runtime, ! 61: for either shared or unshared executables, on either swapping or ! 62: virtual systems. It only requires that the linker allocate objects ! 63: in the order encountered, a reasonable model for most Unix systems. ! 64: Similarly, note that the address of _start() should be the start ! 65: of text space. Fred Fish, UniSoft Systems Inc. */ ! 66: ! 67: int data_start = 0; ! 68: ! 69: #ifdef NEED_ERRNO ! 70: int errno; ! 71: #endif ! 72: ! 73: #ifndef DONT_NEED_ENVIRON ! 74: char **environ; ! 75: #endif ! 76: ! 77: #if defined(orion) || defined(pyramid) || defined(celerity) || defined(ALLIANT) || defined(clipper) ! 78: ! 79: #ifdef ALLIANT ! 80: /* _start must initialize _curbrk and _minbrk on the first startup; ! 81: when starting up after dumping, it must initialize them to what they were ! 82: before the dumping, since they are in the shared library and ! 83: are not dumped. See ADJUST_EXEC_HEADER in m-alliant.h. */ ! 84: extern unsigned char *_curbrk, *_minbrk; ! 85: extern unsigned char end; ! 86: unsigned char *_setbrk = &end; ! 87: #ifdef ALLIANT_2800 ! 88: unsigned char *_end = &end; ! 89: #endif ! 90: #endif ! 91: ! 92: #ifndef DUMMIES ! 93: #define DUMMIES ! 94: #endif ! 95: ! 96: _start (DUMMIES argc, argv, envp) ! 97: int argc; ! 98: char **argv, **envp; ! 99: { ! 100: #ifdef ALLIANT ! 101: #ifdef ALLIANT_2800 ! 102: _curbrk = _end; ! 103: _minbrk = _end; ! 104: #else ! 105: _curbrk = _setbrk; ! 106: _minbrk = _setbrk; ! 107: #endif ! 108: #endif ! 109: ! 110: environ = envp; ! 111: ! 112: exit (main (argc, argv, envp)); ! 113: } ! 114: ! 115: #endif /* orion or pyramid or celerity or alliant or clipper */ ! 116: ! 117: #if defined (ns16000) && !defined (sequent) && !defined (UMAX) ! 118: ! 119: _start () ! 120: { ! 121: /* On 16000, _start pushes fp onto stack */ ! 122: start1 (); ! 123: } ! 124: ! 125: /* ignore takes care of skipping the fp value pushed in start. */ ! 126: static ! 127: start1 (ignore, argc, argv) ! 128: int ignore; ! 129: int argc; ! 130: register char **argv; ! 131: { ! 132: environ = argv + argc + 1; ! 133: ! 134: if (environ == *argv) ! 135: environ--; ! 136: exit (main (argc, argv, environ)); ! 137: } ! 138: #endif /* ns16000, not sequent and not UMAX */ ! 139: ! 140: #ifdef UMAX ! 141: _start() ! 142: { ! 143: asm(" exit [] # undo enter"); ! 144: asm(" .set exitsc,1"); ! 145: asm(" .set sigcatchall,0x400"); ! 146: ! 147: asm(" .globl _exit"); ! 148: asm(" .globl start"); ! 149: asm(" .globl __start"); ! 150: asm(" .globl _main"); ! 151: asm(" .globl _environ"); ! 152: asm(" .globl _sigvec"); ! 153: asm(" .globl sigentry"); ! 154: ! 155: asm("start:"); ! 156: asm(" br .xstart"); ! 157: asm(" .org 0x20"); ! 158: asm(" .double p_glbl,0,0xf00000,0"); ! 159: asm(" .org 0x30"); ! 160: asm(".xstart:"); ! 161: asm(" adjspb $8"); ! 162: asm(" movd 8(sp),0(sp) # argc"); ! 163: asm(" addr 12(sp),r0"); ! 164: asm(" movd r0,4(sp) # argv"); ! 165: asm("L1:"); ! 166: asm(" movd r0,r1"); ! 167: asm(" addqd $4,r0"); ! 168: asm(" cmpqd $0,0(r1) # null args term ?"); ! 169: asm(" bne L1"); ! 170: asm(" cmpd r0,0(4(sp)) # end of 'env' or 'argv' ?"); ! 171: asm(" blt L2"); ! 172: asm(" addqd $-4,r0 # envp's are in list"); ! 173: asm("L2:"); ! 174: asm(" movd r0,8(sp) # env"); ! 175: asm(" movd r0,@_environ # indir is 0 if no env ; not 0 if env"); ! 176: asm(" movqd $0,tos # setup intermediate signal handler"); ! 177: asm(" addr @sv,tos"); ! 178: asm(" movzwd $sigcatchall,tos"); ! 179: asm(" jsr @_sigvec"); ! 180: asm(" adjspb $-12"); ! 181: asm(" jsr @_main"); ! 182: asm(" adjspb $-12"); ! 183: asm(" movd r0,tos"); ! 184: asm(" jsr @_exit"); ! 185: asm(" adjspb $-4"); ! 186: asm(" addr @exitsc,r0"); ! 187: asm(" svc"); ! 188: asm(" .align 4 # sigvec arg"); ! 189: asm("sv:"); ! 190: asm(" .double sigentry"); ! 191: asm(" .double 0"); ! 192: asm(" .double 0"); ! 193: ! 194: asm(" .comm p_glbl,1"); ! 195: } ! 196: #endif /* UMAX */ ! 197: ! 198: #ifdef CRT0_DUMMIES ! 199: ! 200: /* Define symbol "start": here; some systems want that symbol. */ ! 201: #ifdef DOT_GLOBAL_START ! 202: asm(" .text "); ! 203: asm(" .globl start "); ! 204: asm(" start: "); ! 205: #endif /* DOT_GLOBAL_START */ ! 206: ! 207: #ifdef NODOT_GLOBAL_START ! 208: asm(" text "); ! 209: asm(" global start "); ! 210: asm(" start: "); ! 211: #endif /* NODOT_GLOBAL_START */ ! 212: ! 213: static start1 (); ! 214: ! 215: _start () ! 216: { ! 217: /* On vax, nothing is pushed here */ ! 218: /* On sequent, bogus fp is pushed here */ ! 219: start1 (); ! 220: } ! 221: ! 222: static ! 223: start1 (CRT0_DUMMIES argc, xargv) ! 224: int argc; ! 225: char *xargv; ! 226: { ! 227: register char **argv = &xargv; ! 228: environ = argv + argc + 1; ! 229: ! 230: if ((char *)environ == xargv) ! 231: environ--; ! 232: exit (main (argc, argv, environ)); ! 233: } ! 234: #else /* not CRT0_DUMMIES */ ! 235: ! 236: /* "m68k" and "m68000" both stand for m68000 processors, ! 237: but with different program-entry conventions. ! 238: This is a kludge. Now that the CRT0_DUMMIES mechanism above exists, ! 239: most of these machines could use the vax code above ! 240: with some suitable definition of CRT0_DUMMIES. ! 241: Then the symbol m68k could be flushed. ! 242: But I don't want to risk breaking these machines ! 243: in a version 17 patch release, so that change is being put off. */ ! 244: ! 245: #ifdef m68k /* Can't do it all from C */ ! 246: asm (" global _start"); ! 247: asm (" text"); ! 248: asm ("_start:"); ! 249: #ifndef NU ! 250: #ifdef STRIDE ! 251: asm (" comm havefpu%,2"); ! 252: #else /* m68k, not STRIDE */ ! 253: asm (" comm splimit%,4"); ! 254: #endif /* STRIDE */ ! 255: asm (" global exit"); ! 256: asm (" text"); ! 257: #ifdef STRIDE ! 258: asm (" trap &3"); ! 259: asm (" mov.w %d0,havefpu%"); ! 260: #else /* m68k, not STRIDE */ ! 261: asm (" mov.l %d0,splimit%"); ! 262: #endif /* STRIDE */ ! 263: #endif /* not NU */ ! 264: asm (" jsr start1"); ! 265: asm (" mov.l %d0,(%sp)"); ! 266: asm (" jsr exit"); ! 267: asm (" mov.l &1,%d0"); /* d0 = 1 => exit */ ! 268: asm (" trap &0"); ! 269: #else /* m68000, not m68k */ ! 270: ! 271: #ifdef m68000 ! 272: ! 273: #ifdef ISI68K ! 274: /* Added by ESM Sun May 24 12:44:02 1987 to get new ISI library to work */ ! 275: #ifdef BSD4_3 ! 276: static foo () { ! 277: #endif ! 278: asm (" .globl is68020"); ! 279: asm ("is68020:"); ! 280: #ifndef BSD4_3 ! 281: asm (" .long 0x00000000"); ! 282: asm (" .long 0xffffffff"); ! 283: /* End of stuff added by ESM */ ! 284: #endif ! 285: asm (" .text"); ! 286: asm (" .globl __start"); ! 287: asm ("__start:"); ! 288: asm (" .word 0"); ! 289: asm (" link fp,#0"); ! 290: asm (" jbsr _start1"); ! 291: asm (" unlk fp"); ! 292: asm (" rts"); ! 293: #ifdef BSD4_3 ! 294: } ! 295: #endif ! 296: #else /* not ISI68K */ ! 297: ! 298: _start () ! 299: { ! 300: /* On 68000, _start pushes a6 onto stack */ ! 301: start1 (); ! 302: } ! 303: #endif /* not ISI68k */ ! 304: #endif /* m68000 */ ! 305: #endif /* m68k */ ! 306: ! 307: #if defined(m68k) || defined(m68000) ! 308: /* ignore takes care of skipping the a6 value pushed in start. */ ! 309: static ! 310: #if defined(m68k) ! 311: start1 (argc, xargv) ! 312: #else ! 313: start1 (ignore, argc, xargv) ! 314: #endif ! 315: int argc; ! 316: char *xargv; ! 317: { ! 318: register char **argv = &xargv; ! 319: environ = argv + argc + 1; ! 320: ! 321: if ((char *)environ == xargv) ! 322: environ--; ! 323: exit (main (argc, argv, environ)); ! 324: } ! 325: ! 326: #endif /* m68k or m68000 */ ! 327: ! 328: #endif /* not CRT0_DUMMIES */ ! 329: ! 330: #ifdef hp9000s300 ! 331: int argc_value; ! 332: char **argv_value; ! 333: #ifdef OLD_HP_ASSEMBLER ! 334: asm(" text"); ! 335: asm(" globl __start"); ! 336: asm(" globl _exit"); ! 337: asm(" globl _main"); ! 338: asm("__start"); ! 339: asm(" dc.l 0"); ! 340: asm(" subq.w #0x1,d0"); ! 341: asm(" move.w d0,float_soft"); ! 342: asm(" move.l 0x4(a7),d0"); ! 343: asm(" beq.s skip_1"); ! 344: asm(" move.l d0,a0"); ! 345: asm(" clr.l -0x4(a0)"); ! 346: asm("skip_1"); ! 347: asm(" move.l a7,a0"); ! 348: asm(" subq.l #0x8,a7"); ! 349: asm(" move.l (a0),(a7)"); ! 350: asm(" move.l (a0),_argc_value"); ! 351: asm(" addq.l #0x4,a0"); ! 352: asm(" move.l a0,0x4(a7)"); ! 353: asm(" move.l a0,_argv_value"); ! 354: asm("incr_loop"); ! 355: asm(" tst.l (a0)+"); ! 356: asm(" bne.s incr_loop"); ! 357: asm(" move.l 0x4(a7),a1"); ! 358: asm(" cmp.l (a1),a0"); ! 359: asm(" blt.s skip_2"); ! 360: asm(" subq.l #0x4,a0"); ! 361: asm("skip_2"); ! 362: asm(" move.l a0,0x8(a7)"); ! 363: asm(" move.l a0,_environ"); ! 364: asm(" jsr _main"); ! 365: asm(" addq.l #0x8,a7"); ! 366: asm(" move.l d0,-(a7)"); ! 367: asm(" jsr _exit"); ! 368: asm(" move.w #0x1,d0"); ! 369: asm(" trap #0x0"); ! 370: asm(" comm float_soft,4"); ! 371: /* float_soft is allocated in this way because C would ! 372: put an underscore character in its name otherwise. */ ! 373: ! 374: #else /* new hp assembler */ ! 375: ! 376: asm(" text"); ! 377: asm(" global float_loc"); ! 378: asm(" set float_loc,0xFFFFB000"); ! 379: asm(" global fpa_loc"); ! 380: asm(" set fpa_loc,0xfff08000"); ! 381: asm(" global __start"); ! 382: asm(" global _exit"); ! 383: asm(" global _main"); ! 384: asm("__start:"); ! 385: asm(" byte 0,0,0,0"); ! 386: asm(" subq.w &1,%d0"); ! 387: asm(" mov.w %d0,float_soft"); ! 388: asm(" mov.w %d1,flag_68881"); ! 389: #ifndef HPUX_68010 ! 390: asm(" beq.b skip_float"); ! 391: asm(" fmov.l &0x7400,%fpcr"); ! 392: /* asm(" fmov.l &0x7480,%fpcr"); */ ! 393: #endif /* HPUX_68010 */ ! 394: asm("skip_float:"); ! 395: asm(" mov.l %a0,%d0"); ! 396: asm(" add.l %d0,%d0"); ! 397: asm(" subx.w %d1,%d1"); ! 398: asm(" mov.w %d1,flag_68010"); ! 399: asm(" add.l %d0,%d0"); ! 400: asm(" subx.w %d1,%d1"); ! 401: asm(" mov.w %d1,flag_fpa"); ! 402: asm(" tst.l %d2"); ! 403: asm(" ble.b skip_3"); ! 404: asm(" lsl flag_68881"); ! 405: asm(" lsl flag_fpa"); ! 406: asm("skip_3:"); ! 407: asm(" mov.l 4(%a7),%d0"); ! 408: asm(" beq.b skip_1"); ! 409: asm(" mov.l %d0,%a0"); ! 410: asm(" clr.l -4(%a0)"); ! 411: asm("skip_1:"); ! 412: asm(" mov.l %a7,%a0"); ! 413: asm(" subq.l &8,%a7"); ! 414: asm(" mov.l (%a0),(%a7)"); ! 415: asm(" mov.l (%a0),_argc_value"); ! 416: asm(" addq.l &4,%a0"); ! 417: asm(" mov.l %a0,4(%a7)"); ! 418: asm(" mov.l %a0,_argv_value"); ! 419: asm("incr_loop:"); ! 420: asm(" tst.l (%a0)+"); ! 421: asm(" bne.b incr_loop"); ! 422: asm(" mov.l 4(%a7),%a1"); ! 423: asm(" cmp.l %a0,(%a1)"); ! 424: asm(" blt.b skip_2"); ! 425: asm(" subq.l &4,%a0"); ! 426: asm("skip_2:"); ! 427: asm(" mov.l %a0,8(%a7)"); ! 428: asm(" mov.l %a0,_environ"); ! 429: asm(" jsr _main"); ! 430: asm(" addq.l &8,%a7"); ! 431: asm(" mov.l %d0,-(%a7)"); ! 432: asm(" jsr _exit"); ! 433: asm(" mov.w &1,%d0"); ! 434: asm(" trap &0"); ! 435: asm(" comm float_soft, 4"); ! 436: asm(" comm flag_68881, 4"); ! 437: asm(" comm flag_68010, 4"); ! 438: asm(" comm flag_fpa, 4"); ! 439: ! 440: #endif /* new hp assembler */ ! 441: #endif /* hp9000s300 */ ! 442: ! 443: #ifdef GOULD ! 444: ! 445: /* startup code has to be in near text rather ! 446: than fartext as allocated by the C compiler. */ ! 447: asm(" .text"); ! 448: asm(" .align 2"); ! 449: asm(" .globl __start"); ! 450: asm(" .text"); ! 451: asm("__start:"); ! 452: /* setup base register b1 (function base). */ ! 453: asm(" .using b1,."); ! 454: asm(" tpcbr b1"); ! 455: /* setup base registers b3 through b7 (data references). */ ! 456: asm(" file basevals,b3"); ! 457: /* setup base register b2 (stack pointer); it should be ! 458: aligned on a 8-word boundary; but because it is pointing ! 459: to argc, its value should be remembered (in r5). */ ! 460: asm(" movw b2,r4"); ! 461: asm(" movw b2,r5"); ! 462: asm(" andw #~0x1f,r4"); ! 463: asm(" movw r4,b2"); ! 464: /* allocate stack frame to do some work. */ ! 465: asm(" subea 16w,b2"); ! 466: /* initialize signal catching for UTX/32 1.2; this is ! 467: necessary to make restart from saved image work. */ ! 468: asm(" movea sigcatch,r1"); ! 469: asm(" movw r1,8w[b2]"); ! 470: asm(" svc #1,#150"); ! 471: /* setup address of argc for start1. */ ! 472: asm(" movw r5,8w[b2]"); ! 473: asm(" func #1,_start1"); ! 474: asm(" halt"); ! 475: /* space for ld to store base register initial values. */ ! 476: asm(" .align 5"); ! 477: asm("basevals:"); ! 478: asm(" .word __base3,__base4,__base5,__base6,__base7"); ! 479: ! 480: static ! 481: start1 (xargc) ! 482: int *xargc; ! 483: { ! 484: register int argc; ! 485: register char **argv; ! 486: ! 487: argc = *xargc; ! 488: argv = (char **)(xargc) + 1; ! 489: environ = argv + argc + 1; ! 490: ! 491: if (environ == argv) ! 492: environ--; ! 493: exit (main (argc, argv, environ)); ! 494: ! 495: } ! 496: ! 497: #endif /* GOULD */ ! 498: ! 499: #ifdef elxsi ! 500: extern int errno; ! 501: extern char **environ; ! 502: ! 503: _start() ! 504: { ! 505: register int r; ! 506: ! 507: errno = 0; ! 508: environ = *(&environ + 8); ! 509: _stdinit(); ! 510: r = main(*(&environ + 6), *(&environ + 7), environ); ! 511: exit(r); ! 512: _exit(r); ! 513: } ! 514: #endif /* elxsi */ ! 515: ! 516: ! 517: #ifdef sparc ! 518: asm (".global __start"); ! 519: asm (".text"); ! 520: asm ("__start:"); ! 521: asm (" mov 0, %fp"); ! 522: asm (" ld [%sp + 64], %o0"); ! 523: asm (" add %sp, 68, %o1"); ! 524: asm (" sll %o0, 2, %o2"); ! 525: asm (" add %o2, 4, %o2"); ! 526: asm (" add %o1, %o2, %o2"); ! 527: asm (" sethi %hi(_environ), %o3"); ! 528: asm (" st %o2, [%o3+%lo(_environ)]"); ! 529: asm (" andn %sp, 7, %sp"); ! 530: asm (" call _main"); ! 531: asm (" sub %sp, 24, %sp"); ! 532: asm (" call __exit"); ! 533: asm (" nop"); ! 534: ! 535: #endif /* sparc */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.