1 /* C code startup routine.
2 Copyright (C) 1985, 1986, 1992, 1993 Free Software Foundation, Inc.
4 This file is part of XEmacs.
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Synched up with: FSF 19.30. */
24 /* The standard Vax 4.2 Unix crt0.c cannot be used for Emacs
25 because it makes `environ' an initialized variable.
26 It is easiest to have a special crt0.c on all machines
27 though I don't know whether other machines actually need it. */
29 /* On the vax and 68000, in BSD4.2 and USG5.2,
30 this is the data format on startup:
31 (vax) ap and fp are unpredictable as far as I know; don't use them.
32 sp -> word containing argc
33 word pointing to first arg string
34 [word pointing to next arg string]... 0 or more times
37 [word pointing to environment variable]... 1 or more times
42 [next arg string]... 0 or more times
45 /* On the 16000, at least in the one 4.2 system I know about,
46 the initial data format is
47 sp -> word containing argc
49 word pointing to first arg string, and so on as above
60 /* Workaround for Sun cc 3.0, which doesn't handle asm's outside a fn. */
61 #if __SUNPRO_C >= 0x300
62 #define no_toplevel_asm
65 /* ******** WARNING ********
66 Do not insert any data definitions before data_start!
67 Since this is the first file linked, the address of the following
68 variable should correspond to the start of initialized data space.
69 On some systems this is a constant that is independent of the text
70 size for shared executables. On others, it is a function of the
71 text size. In short, this seems to be the most portable way to
72 discover the start of initialized data space dynamically at runtime,
73 for either shared or unshared executables, on either swapping or
74 virtual systems. It only requires that the linker allocate objects
75 in the order encountered, a reasonable model for most Unix systems.
76 Similarly, note that the address of _start() should be the start
77 of text space. Fred Fish, UniSoft Systems Inc. */
85 #ifndef DONT_NEED_ENVIRON
90 /* On systems where the static storage class is usable, this function
91 should be declared as static. Otherwise, the static keyword has
92 been defined to be something else, and code for those systems must
93 take care of this declaration appropriately. */
98 extern char *malloc(), *realloc(), *(*_libc_malloc) (), *(*_libc_realloc)();
99 extern void free(), (*_libc_free) (); extern int main();
100 std_$call void unix_$main();
104 _libc_malloc = malloc;
105 _libc_realloc = realloc;
107 unix_$main(main); /* no return */
111 #if defined(orion) || defined(pyramid) || defined(celerity) || defined(ALLIANT) || defined(clipper) || defined(sps7)
113 #if defined(sps7) && defined(V3x)
119 /* _start must initialize _curbrk and _minbrk on the first startup;
120 when starting up after dumping, it must initialize them to what they were
121 before the dumping, since they are in the shared library and
122 are not dumped. See ADJUST_EXEC_HEADER in m-alliant.h. */
123 extern unsigned char *_curbrk, *_minbrk;
124 extern unsigned char end;
125 unsigned char *_setbrk = &end;
127 unsigned char *_end = &end;
135 _start (DUMMIES argc, argv, envp)
151 exit (main (argc, argv, envp));
154 #endif /* orion or pyramid or celerity or alliant or clipper */
156 #if defined (ns16000) && !defined (sequent) && !defined (UMAX) && !defined (CRT0_DUMMIES)
160 /* On 16000, _start pushes fp onto stack */
164 /* ignore takes care of skipping the fp value pushed in start. */
166 start1 (ignore, argc, argv)
171 environ = argv + argc + 1;
173 if (environ == *argv)
175 exit (main (argc, argv, environ));
177 #endif /* ns16000, not sequent and not UMAX, and not the CRT0_DUMMIES method */
182 asm(" exit [] # undo enter");
183 asm(" .set exitsc,1");
184 asm(" .set sigcatchall,0x400");
186 asm(" .globl _exit");
187 asm(" .globl start");
188 asm(" .globl __start");
189 asm(" .globl _main");
190 asm(" .globl _environ");
191 asm(" .globl _sigvec");
192 asm(" .globl sigentry");
197 asm(" .double p_glbl,0,0xf00000,0");
201 asm(" movd 8(sp),0(sp) # argc");
202 asm(" addr 12(sp),r0");
203 asm(" movd r0,4(sp) # argv");
207 asm(" cmpqd $0,0(r1) # null args term ?");
209 asm(" cmpd r0,0(4(sp)) # end of 'env' or 'argv' ?");
211 asm(" addqd $-4,r0 # envp's are in list");
213 asm(" movd r0,8(sp) # env");
214 asm(" movd r0,@_environ # indir is 0 if no env ; not 0 if env");
215 asm(" movqd $0,tos # setup intermediate signal handler");
216 asm(" addr @sv,tos");
217 asm(" movzwd $sigcatchall,tos");
218 asm(" jsr @_sigvec");
225 asm(" addr @exitsc,r0");
227 asm(" .align 4 # sigvec arg");
229 asm(" .double sigentry");
233 asm(" .comm p_glbl,1");
239 /* Define symbol "start": here; some systems want that symbol. */
240 #ifdef DOT_GLOBAL_START
242 asm(" .globl start ");
244 #endif /* DOT_GLOBAL_START */
246 #ifdef NODOT_GLOBAL_START
248 asm(" global start ");
250 #endif /* NODOT_GLOBAL_START */
254 /* GCC 2.1, when optimization is turned off, seems to want to push a
255 word of garbage on the stack, which screws up the CRT0_DUMMIES
256 hack. So we hand-code _start in assembly language. */
260 #else /* sony_news (not gas) */
262 #endif /* sony_news (not gas) */
263 asm(".globl __start ");
266 asm(" jbsr _start1 ");
270 #else /* not m68000 */
275 /* On vax, nothing is pushed here */
276 /* On sequent, bogus fp is pushed here */
280 #endif /* possibly m68000 */
282 #ifdef __bsdi__ /* for version number */
283 #include <sys/param.h>
285 #if defined(_BSDI_VERSION) && (_BSDI_VERSION >= 199501)
289 start1 (CRT0_DUMMIES int argc, char *xargv)
291 char **argv = &xargv;
292 environ = argv + argc + 1;
293 #if defined(_BSDI_VERSION) && (_BSDI_VERSION >= 199501)
294 __progname = argv[0];
297 if ((char *)environ == xargv)
299 exit (main (argc, argv, environ));
301 /* Refer to `start1' so GCC will not think it is never called
302 and optimize it out. */
305 #else /* not CRT0_DUMMIES */
307 /* "m68k" and "m68000" both stand for m68000 processors,
308 but with different program-entry conventions.
309 This is a kludge. Now that the CRT0_DUMMIES mechanism above exists,
310 most of these machines could use the vax code above
311 with some suitable definition of CRT0_DUMMIES.
312 Then the symbol m68k could be flushed.
313 But I don't want to risk breaking these machines
314 in a version 17 patch release, so that change is being put off. */
316 #ifdef m68k /* Can't do it all from C */
317 asm (" global _start");
322 asm (" comm havefpu%,2");
323 #else /* m68k, not STRIDE */
324 asm (" comm splimit%,4");
326 asm (" global exit");
330 asm (" mov.w %d0,havefpu%");
331 #else /* m68k, not STRIDE */
332 asm (" mov.l %d0,splimit%");
336 asm (" mov.l %d0,(%sp)");
338 asm (" mov.l &1,%d0"); /* d0 = 1 => exit */
340 #else /* m68000, not m68k */
345 /* Added by ESM Sun May 24 12:44:02 1987 to get new ISI library to work */
346 /* Edited by Ray Mon May 15 15:59:56 EST 1989 so we can compile with gcc */
347 #if defined(BSD4_3) && !defined(__GNUC__)
350 asm (" .globl is68020");
353 asm (" .long 0x00000000");
354 asm (" .long 0xffffffff");
355 /* End of stuff added by ESM */
358 asm (" .globl __start");
362 asm (" jbsr _start1");
365 #if defined(BSD4_3) && !defined(__GNUC__)
368 #else /* not ISI68K */
373 #ifdef LISP_FLOAT_TYPE
377 /* On 68000, _start pushes a6 onto stack */
380 #endif /* not ISI68k */
384 #if defined(m68k) || defined(m68000)
385 /* ignore takes care of skipping the a6 value pushed in start. */
390 start1 (ignore, argc, xargv)
395 char **argv = &xargv;
396 environ = argv + argc + 1;
398 if ((char *)environ == xargv)
401 asm(" jsr f68881_used");
404 asm(" jsr ffpa_used");
407 asm(" jsr start_float");
409 exit (main (argc, argv, environ));
412 #endif /* m68k or m68000 */
414 #endif /* not CRT0_DUMMIES */
419 #ifdef OLD_HP_ASSEMBLER
421 asm(" globl __start");
426 asm(" subq.w #0x1,d0");
427 asm(" move.w d0,float_soft");
428 asm(" move.l 0x4(a7),d0");
429 asm(" beq.s skip_1");
430 asm(" move.l d0,a0");
431 asm(" clr.l -0x4(a0)");
433 asm(" move.l a7,a0");
434 asm(" subq.l #0x8,a7");
435 asm(" move.l (a0),(a7)");
436 asm(" move.l (a0),_argc_value");
437 asm(" addq.l #0x4,a0");
438 asm(" move.l a0,0x4(a7)");
439 asm(" move.l a0,_argv_value");
442 asm(" bne.s incr_loop");
443 asm(" move.l 0x4(a7),a1");
444 asm(" cmp.l (a1),a0");
445 asm(" blt.s skip_2");
446 asm(" subq.l #0x4,a0");
448 asm(" move.l a0,0x8(a7)");
449 asm(" move.l a0,_environ");
451 asm(" addq.l #0x8,a7");
452 asm(" move.l d0,-(a7)");
454 asm(" move.w #0x1,d0");
456 asm(" comm float_soft,4");
457 /* float_soft is allocated in this way because C would
458 put an underscore character in its name otherwise. */
460 #else /* new hp assembler */
463 asm(" global float_loc");
464 asm(" set float_loc,0xFFFFB000");
465 asm(" global fpa_loc");
466 asm(" set fpa_loc,0xfff08000");
467 asm(" global __start");
468 asm(" global _exit");
469 asm(" global _main");
471 asm(" byte 0,0,0,0");
472 asm(" subq.w &1,%d0");
473 asm(" mov.w %d0,float_soft");
474 asm(" mov.w %d1,flag_68881");
476 asm(" beq.b skip_float");
477 asm(" fmov.l &0x7400,%fpcr");
478 /* asm(" fmov.l &0x7480,%fpcr"); */
479 #endif /* HPUX_68010 */
481 asm(" mov.l %a0,%d0");
482 asm(" add.l %d0,%d0");
483 asm(" subx.w %d1,%d1");
484 asm(" mov.w %d1,flag_68010");
485 asm(" add.l %d0,%d0");
486 asm(" subx.w %d1,%d1");
487 asm(" mov.w %d1,flag_fpa");
489 asm(" ble.b skip_3");
490 asm(" lsl flag_68881");
491 asm(" lsl flag_fpa");
493 asm(" mov.l 4(%a7),%d0");
494 asm(" beq.b skip_1");
495 asm(" mov.l %d0,%a0");
496 asm(" clr.l -4(%a0)");
498 asm(" mov.l %a7,%a0");
499 asm(" subq.l &8,%a7");
500 asm(" mov.l (%a0),(%a7)");
501 asm(" mov.l (%a0),_argc_value");
502 asm(" addq.l &4,%a0");
503 asm(" mov.l %a0,4(%a7)");
504 asm(" mov.l %a0,_argv_value");
506 asm(" tst.l (%a0)+");
507 asm(" bne.b incr_loop");
508 asm(" mov.l 4(%a7),%a1");
509 asm(" cmp.l %a0,(%a1)");
510 asm(" blt.b skip_2");
511 asm(" subq.l &4,%a0");
513 asm(" mov.l %a0,8(%a7)");
514 asm(" mov.l %a0,_environ");
516 asm(" addq.l &8,%a7");
517 asm(" mov.l %d0,-(%a7)");
519 asm(" mov.w &1,%d0");
521 asm(" comm float_soft, 4");
522 asm(" comm flag_68881, 4");
523 asm(" comm flag_68010, 4");
524 asm(" comm flag_68040, 4");
525 asm(" comm flag_fpa, 4");
527 #endif /* new hp assembler */
528 #endif /* hp9000s300 */
532 /* startup code has to be in near text rather
533 than fartext as allocated by the C compiler. */
536 asm(" .globl __start");
539 /* setup base register b1 (function base). */
542 /* setup base registers b3 through b7 (data references). */
543 asm(" file basevals,b3");
544 /* setup base register b2 (stack pointer); it should be
545 aligned on a 8-word boundary; but because it is pointing
546 to argc, its value should be remembered (in r5). */
549 asm(" andw #~0x1f,r4");
551 /* allocate stack frame to do some work. */
552 asm(" subea 16w,b2");
553 /* initialize signal catching for UTX/32 1.2; this is
554 necessary to make restart from saved image work. */
555 asm(" movea sigcatch,r1");
556 asm(" movw r1,8w[b2]");
558 /* setup address of argc for start1. */
559 asm(" movw r5,8w[b2]");
560 asm(" func #1,_start1");
562 /* space for ld to store base register initial values. */
565 asm(" .word __base3,__base4,__base5,__base6,__base7");
575 argv = (char **)(xargc) + 1;
576 environ = argv + argc + 1;
580 exit (main (argc, argv, environ));
587 #include <elxsi/argvcache.h>
589 extern char **environ;
591 extern void _init_doscan(), _init_iob();
593 char *_init_brk = end;
597 environ = exec_cache.ac_envp;
602 _exit (exit (main (exec_cache.ac_argc,
604 exec_cache.ac_envp)));
610 #ifdef no_toplevel_asm
611 static no_toplevel_asm_wrapper() {
613 asm (".pushsection \".text\"");
615 #endif /* no_toplevel_asm */
617 asm (".global _start");
621 asm (" ld [%sp + 64], %o0");
622 asm (" add %sp, 68, %o1");
623 asm (" sll %o0, 2, %o2");
624 asm (" add %o2, 4, %o2");
625 asm (" add %o1, %o2, %o2");
626 asm (" sethi %hi(_environ), %o3");
627 asm (" st %o2, [%o3+%lo(_environ)]");
628 asm (" andn %sp, 7, %sp");
630 asm (" sub %sp, 24, %sp");
634 asm (".global __start");
638 asm (" ld [%sp + 64], %o0");
639 asm (" add %sp, 68, %o1");
640 asm (" sll %o0, 2, %o2");
641 asm (" add %o2, 4, %o2");
642 asm (" add %o1, %o2, %o2");
643 asm (" sethi %hi(_environ), %o3");
644 asm (" st %o2, [%o3+%lo(_environ)]");
645 asm (" andn %sp, 7, %sp");
647 asm (" sub %sp, 24, %sp");
648 asm (" call __exit");
651 #ifdef no_toplevel_asm
655 } /* no_toplevel_asm_wrapper() */
656 #endif /* no_toplevel_asm */
663 #include <sys/param.h> /* for version number */
664 #if defined(_BSDI_VERSION) && (_BSDI_VERSION >= 199501)
667 #endif /* __bsdi__ */