|
|
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.