Initial git import
[sxemacs] / src / ecrt0.c
1 /* C code startup routine.
2    Copyright (C) 1985, 1986, 1992, 1993 Free Software Foundation, Inc.
3
4 This file is part of SXEmacs
5
6 SXEmacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 SXEmacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
18
19
20 /* Synched up with: FSF 19.30. */
21
22 /* The standard Vax 4.2 Unix crt0.c cannot be used for Emacs
23    because it makes `environ' an initialized variable.
24    It is easiest to have a special crt0.c on all machines
25    though I don't know whether other machines actually need it.  */
26
27 /* On the vax and 68000, in BSD4.2 and USG5.2,
28    this is the data format on startup:
29   (vax) ap and fp are unpredictable as far as I know; don't use them.
30   sp ->  word containing argc
31          word pointing to first arg string
32          [word pointing to next arg string]... 0 or more times
33          0
34 Optionally:
35          [word pointing to environment variable]... 1 or more times
36          ...
37          0
38 And always:
39          first arg string
40          [next arg string]... 0 or more times
41 */
42
43 /* On the 16000, at least in the one 4.2 system I know about,
44   the initial data format is
45   sp ->  word containing argc
46          word containing argp
47          word pointing to first arg string, and so on as above
48 */
49
50 #ifdef emacs
51 #include <config.h>
52 #endif
53
54 #ifdef __GNUC__
55 #define asm __asm
56 #endif
57
58 /* Workaround for Sun cc 3.0, which doesn't handle asm's outside a fn. */
59 #if __SUNPRO_C >= 0x300
60 #define no_toplevel_asm
61 #endif
62
63 /*              ********  WARNING ********
64     Do not insert any data definitions before data_start!
65     Since this is the first file linked, the address of the following
66     variable should correspond to the start of initialized data space.
67     On some systems this is a constant that is independent of the text
68     size for shared executables.  On others, it is a function of the
69     text size. In short, this seems to be the most portable way to
70     discover the start of initialized data space dynamically at runtime,
71     for either shared or unshared executables, on either swapping or
72     virtual systems.  It only requires that the linker allocate objects
73     in the order encountered, a reasonable model for most Unix systems.
74     Similarly, note that the address of _start() should be the start
75     of text space.   Fred Fish, UniSoft Systems Inc.  */
76
77 int data_start = 0;
78
79 #ifdef NEED_ERRNO
80 int errno;
81 #endif
82
83 #ifndef DONT_NEED_ENVIRON
84 char **environ;
85 #endif
86
87 #ifndef static
88 /* On systems where the static storage class is usable, this function
89    should be declared as static.  Otherwise, the static keyword has
90    been defined to be something else, and code for those systems must
91    take care of this declaration appropriately.  */
92 static start1();
93 #endif
94
95 #ifdef APOLLO
96 extern char *malloc(), *realloc(), *(*_libc_malloc) (), *(*_libc_realloc) ();
97 extern void free(), (*_libc_free) ();
98 extern int main();
99 std_$call void unix_$main();
100
101 _start()
102 {
103         _libc_malloc = malloc;
104         _libc_realloc = realloc;
105         _libc_free = free;
106         unix_$main(main);       /* no return */
107 }
108 #endif                          /* APOLLO */
109
110 #if defined(orion) || defined(pyramid) || defined(celerity) || defined(ALLIANT) || defined(clipper) || defined(sps7)
111
112 #if defined(sps7) && defined(V3x)
113 asm("   section 10");
114 asm("   ds.b    0xb0");
115 #endif
116
117 #ifdef ALLIANT
118 /* _start must initialize _curbrk and _minbrk on the first startup;
119    when starting up after dumping, it must initialize them to what they were
120    before the dumping, since they are in the shared library and
121    are not dumped.  See ADJUST_EXEC_HEADER in m-alliant.h.  */
122 extern unsigned char *_curbrk, *_minbrk;
123 extern unsigned char end;
124 unsigned char *_setbrk = &end;
125 #ifdef ALLIANT_2800
126 unsigned char *_end = &end;
127 #endif
128 #endif
129
130 #ifndef DUMMIES
131 #define DUMMIES
132 #endif
133
134 _start(DUMMIES argc, argv, envp)
135 int argc;
136 char **argv, **envp;
137 {
138 #ifdef ALLIANT
139 #ifdef ALLIANT_2800
140         _curbrk = _end;
141         _minbrk = _end;
142 #else
143         _curbrk = _setbrk;
144         _minbrk = _setbrk;
145 #endif
146 #endif
147
148         environ = envp;
149
150         exit(main(argc, argv, envp));
151 }
152
153 #endif                          /* orion or pyramid or celerity or alliant or clipper */
154
155 #if defined (ns16000) && !defined (sequent) && !defined (UMAX) && !defined (CRT0_DUMMIES)
156
157 _start()
158 {
159 /* On 16000, _start pushes fp onto stack */
160         start1();
161 }
162
163 /* ignore takes care of skipping the fp value pushed in start.  */
164 static start1(ignore, argc, argv)
165 int ignore;
166 int argc;
167 char **argv;
168 {
169         environ = argv + argc + 1;
170
171         if (environ == *argv)
172                 environ--;
173         exit(main(argc, argv, environ));
174 }
175 #endif                          /* ns16000, not sequent and not UMAX, and not the CRT0_DUMMIES method */
176
177 #ifdef UMAX
178 _start()
179 {
180         asm("   exit []                 # undo enter");
181         asm("   .set    exitsc,1");
182         asm("   .set    sigcatchall,0x400");
183
184         asm("   .globl  _exit");
185         asm("   .globl  start");
186         asm("   .globl  __start");
187         asm("   .globl  _main");
188         asm("   .globl  _environ");
189         asm("   .globl  _sigvec");
190         asm("   .globl  sigentry");
191
192         asm("start:");
193         asm("   br      .xstart");
194         asm("   .org    0x20");
195         asm("   .double p_glbl,0,0xf00000,0");
196         asm("   .org    0x30");
197         asm(".xstart:");
198         asm("   adjspb  $8");
199         asm("   movd    8(sp),0(sp)     # argc");
200         asm("   addr    12(sp),r0");
201         asm("   movd    r0,4(sp)        # argv");
202         asm("L1:");
203         asm("   movd    r0,r1");
204         asm("   addqd   $4,r0");
205         asm("   cmpqd   $0,0(r1)        # null args term ?");
206         asm("   bne     L1");
207         asm("   cmpd    r0,0(4(sp))     # end of 'env' or 'argv' ?");
208         asm("   blt     L2");
209         asm("   addqd   $-4,r0          # envp's are in list");
210         asm("L2:");
211         asm("   movd    r0,8(sp)        # env");
212         asm("   movd    r0,@_environ    # indir is 0 if no env ; not 0 if env");
213         asm("   movqd   $0,tos          # setup intermediate signal handler");
214         asm("   addr    @sv,tos");
215         asm("   movzwd  $sigcatchall,tos");
216         asm("   jsr     @_sigvec");
217         asm("   adjspb  $-12");
218         asm("   jsr     @_main");
219         asm("   adjspb  $-12");
220         asm("   movd    r0,tos");
221         asm("   jsr     @_exit");
222         asm("   adjspb  $-4");
223         asm("   addr    @exitsc,r0");
224         asm("   svc");
225         asm("   .align  4               # sigvec arg");
226         asm("sv:");
227         asm("   .double sigentry");
228         asm("   .double 0");
229         asm("   .double 0");
230
231         asm("   .comm   p_glbl,1");
232 }
233 #endif                          /* UMAX */
234
235 #ifdef CRT0_DUMMIES
236
237 /* Define symbol "start": here; some systems want that symbol.  */
238 #ifdef DOT_GLOBAL_START
239 asm("   .text           ");
240 asm("   .globl start    ");
241 asm("   start:          ");
242 #endif                          /* DOT_GLOBAL_START */
243
244 #ifdef NODOT_GLOBAL_START
245 asm("   text            ");
246 asm("   global start    ");
247 asm("   start:          ");
248 #endif                          /* NODOT_GLOBAL_START */
249
250 #ifdef m68000
251
252 /* GCC 2.1, when optimization is turned off, seems to want to push a
253    word of garbage on the stack, which screws up the CRT0_DUMMIES
254    hack.  So we hand-code _start in assembly language.  */
255 asm(".text                      ");
256 #ifndef sony_news
257 asm("   .even                   ");
258 #else                           /* sony_news (not gas) */
259 +asm("  .align 2                ");
260 #endif                          /* sony_news (not gas) */
261 asm(".globl __start             ");
262 asm("__start:                   ");
263 asm("   link a6,#0              ");
264 asm("   jbsr _start1            ");
265 asm("   unlk a6                 ");
266 asm("   rts                     ");
267
268 #else                           /* not m68000 */
269
270 int _start()
271 {
272 /* On vax, nothing is pushed here  */
273 /* On sequent, bogus fp is pushed here  */
274         start1();
275 }
276
277 #endif                          /* possibly m68000 */
278
279 #ifdef __bsdi__                 /* for version number */
280 #include <sys/param.h>
281 #endif
282 #if defined(_BSDI_VERSION) && (_BSDI_VERSION >= 199501)
283 char *__progname;
284 #endif
285 static int start1(CRT0_DUMMIES int argc, char *xargv)
286 {
287         char **argv = &xargv;
288         environ = argv + argc + 1;
289 #if defined(_BSDI_VERSION) && (_BSDI_VERSION >= 199501)
290         __progname = argv[0];
291 #endif
292
293         if ((char *)environ == xargv)
294                 environ--;
295         exit(main(argc, argv, environ));
296
297         /* Refer to `start1' so GCC will not think it is never called
298            and optimize it out.  */
299         (void)&start1;
300 }
301 #else                           /* not CRT0_DUMMIES */
302
303 /* "m68k" and "m68000" both stand for m68000 processors,
304    but with different program-entry conventions.
305    This is a kludge.  Now that the CRT0_DUMMIES mechanism above exists,
306    most of these machines could use the vax code above
307    with some suitable definition of CRT0_DUMMIES.
308    Then the symbol m68k could be flushed.
309    But I don't want to risk breaking these machines
310    in a version 17 patch release, so that change is being put off.  */
311
312 #ifdef m68k                     /* Can't do it all from C */
313 asm("   global  _start");
314 asm("   text");
315 asm("_start:");
316 #ifndef NU
317 #ifdef STRIDE
318 asm("   comm    havefpu%,2");
319 #else                           /* m68k, not STRIDE */
320 asm("  comm     splimit%,4");
321 #endif                          /* STRIDE */
322 asm("   global  exit");
323 asm("   text");
324 #ifdef STRIDE
325 asm("   trap    &3");
326 asm("   mov.w   %d0,havefpu%");
327 #else                           /* m68k, not STRIDE */
328 asm("   mov.l   %d0,splimit%");
329 #endif                          /* STRIDE */
330 #endif                          /* not NU */
331 asm("   jsr     start1");
332 asm("   mov.l   %d0,(%sp)");
333 asm("   jsr     exit");
334 asm("   mov.l   &1,%d0");       /* d0 = 1 => exit */
335 asm("   trap    &0");
336 #else                           /* m68000, not m68k */
337
338 #ifdef m68000
339
340 #ifdef ISI68K
341 /* Added by ESM Sun May 24 12:44:02 1987 to get new ISI library to work */
342 /* Edited by Ray Mon May 15 15:59:56 EST 1989 so we can compile with gcc */
343 #if defined(BSD4_3) && !defined(__GNUC__)
344 static foo()
345 {
346 #endif
347         asm("   .globl  is68020");
348         asm("is68020:");
349 #ifndef BSD4_3
350         asm("   .long   0x00000000");
351         asm("   .long   0xffffffff");
352 /* End of stuff added by ESM */
353 #endif
354         asm("   .text");
355         asm("   .globl  __start");
356         asm("__start:");
357         asm("   .word 0");
358         asm("   link    a6,#0");
359         asm("   jbsr    _start1");
360         asm("   unlk    a6");
361         asm("   rts");
362 #if defined(BSD4_3) && !defined(__GNUC__)
363 }
364 #endif
365 #else                           /* not ISI68K */
366
367 _start()
368 {
369 #ifdef sun
370 #ifdef HAVE_FPFLOAT
371         finitfp_();
372 #endif
373 #endif
374 /* On 68000, _start pushes a6 onto stack  */
375         start1();
376 }
377 #endif                          /* not ISI68k */
378 #endif                          /* m68000 */
379 #endif                          /* m68k */
380
381 #if defined(m68k) || defined(m68000)
382 /* ignore takes care of skipping the a6 value pushed in start.  */
383 static
384 #if defined(m68k)
385 start1(argc, xargv)
386 #else
387 start1(ignore, argc, xargv)
388 #endif
389 int argc;
390 char *xargv;
391 {
392         char **argv = &xargv;
393         environ = argv + argc + 1;
394
395         if ((char *)environ == xargv)
396                 environ--;
397 #ifdef sun_68881
398         asm("    jsr     f68881_used");
399 #endif
400 #ifdef sun_fpa
401         asm("    jsr     ffpa_used");
402 #endif
403 #ifdef sun_soft
404         asm("    jsr     start_float");
405 #endif
406         exit(main(argc, argv, environ));
407 }
408
409 #endif                          /* m68k or m68000 */
410
411 #endif                          /* not CRT0_DUMMIES */
412
413 #ifdef hp9000s300
414 int argc_value;
415 char **argv_value;
416 #ifdef OLD_HP_ASSEMBLER
417 asm("   text");
418 asm("   globl __start");
419 asm("   globl _exit");
420 asm("   globl _main");
421 asm("__start");
422 asm("   dc.l    0");
423 asm("   subq.w  #0x1,d0");
424 asm("   move.w  d0,float_soft");
425 asm("   move.l  0x4(a7),d0");
426 asm("   beq.s   skip_1");
427 asm("   move.l  d0,a0");
428 asm("   clr.l   -0x4(a0)");
429 asm("skip_1");
430 asm("   move.l  a7,a0");
431 asm("   subq.l  #0x8,a7");
432 asm("   move.l  (a0),(a7)");
433 asm("   move.l  (a0),_argc_value");
434 asm("   addq.l  #0x4,a0");
435 asm("   move.l  a0,0x4(a7)");
436 asm("   move.l  a0,_argv_value");
437 asm("incr_loop");
438 asm("   tst.l   (a0)+");
439 asm("   bne.s   incr_loop");
440 asm("   move.l  0x4(a7),a1");
441 asm("   cmp.l   (a1),a0");
442 asm("   blt.s   skip_2");
443 asm("   subq.l  #0x4,a0");
444 asm("skip_2");
445 asm("   move.l  a0,0x8(a7)");
446 asm("   move.l  a0,_environ");
447 asm("   jsr     _main");
448 asm("   addq.l  #0x8,a7");
449 asm("   move.l  d0,-(a7)");
450 asm("   jsr     _exit");
451 asm("   move.w  #0x1,d0");
452 asm("   trap    #0x0");
453 asm("   comm    float_soft,4");
454 /* float_soft is allocated in this way because C would
455    put an underscore character in its name otherwise. */
456
457 #else                           /* new hp assembler */
458
459 asm("   text");
460 asm("   global  float_loc");
461 asm("   set     float_loc,0xFFFFB000");
462 asm("   global  fpa_loc");
463 asm("   set     fpa_loc,0xfff08000");
464 asm("   global  __start");
465 asm("   global  _exit");
466 asm("   global  _main");
467 asm("__start:");
468 asm("   byte    0,0,0,0");
469 asm("   subq.w  &1,%d0");
470 asm("   mov.w   %d0,float_soft");
471 asm("   mov.w   %d1,flag_68881");
472 #ifndef HPUX_68010
473 asm("   beq.b   skip_float");
474 asm("   fmov.l  &0x7400,%fpcr");
475 /*      asm("   fmov.l  &0x7480,%fpcr"); */
476 #endif                          /* HPUX_68010 */
477 asm("skip_float:");
478 asm("   mov.l   %a0,%d0");
479 asm("   add.l   %d0,%d0");
480 asm("   subx.w  %d1,%d1");
481 asm("   mov.w   %d1,flag_68010");
482 asm("   add.l   %d0,%d0");
483 asm("   subx.w  %d1,%d1");
484 asm("   mov.w   %d1,flag_fpa");
485 asm("   tst.l   %d2");
486 asm("   ble.b   skip_3");
487 asm("   lsl     flag_68881");
488 asm("   lsl     flag_fpa");
489 asm("skip_3:");
490 asm("   mov.l   4(%a7),%d0");
491 asm("   beq.b   skip_1");
492 asm("   mov.l   %d0,%a0");
493 asm("   clr.l   -4(%a0)");
494 asm("skip_1:");
495 asm("   mov.l   %a7,%a0");
496 asm("   subq.l  &8,%a7");
497 asm("   mov.l   (%a0),(%a7)");
498 asm("   mov.l   (%a0),_argc_value");
499 asm("   addq.l  &4,%a0");
500 asm("   mov.l   %a0,4(%a7)");
501 asm("   mov.l   %a0,_argv_value");
502 asm("incr_loop:");
503 asm("   tst.l   (%a0)+");
504 asm("   bne.b   incr_loop");
505 asm("   mov.l   4(%a7),%a1");
506 asm("   cmp.l   %a0,(%a1)");
507 asm("   blt.b   skip_2");
508 asm("   subq.l  &4,%a0");
509 asm("skip_2:");
510 asm("   mov.l   %a0,8(%a7)");
511 asm("   mov.l   %a0,_environ");
512 asm("   jsr     _main");
513 asm("   addq.l  &8,%a7");
514 asm("   mov.l   %d0,-(%a7)");
515 asm("   jsr     _exit");
516 asm("   mov.w   &1,%d0");
517 asm("   trap    &0");
518 asm("   comm    float_soft, 4");
519 asm("   comm    flag_68881, 4");
520 asm("   comm    flag_68010, 4");
521 asm("   comm    flag_68040, 4");
522 asm("   comm    flag_fpa, 4");
523
524 #endif                          /* new hp assembler */
525 #endif                          /* hp9000s300 */
526
527 #ifdef GOULD
528
529 /* startup code has to be in near text rather
530    than fartext as allocated by the C compiler. */
531 asm("   .text");
532 asm("   .align  2");
533 asm("   .globl  __start");
534 asm("   .text");
535 asm("__start:");
536 /* setup base register b1 (function base). */
537 asm("   .using  b1,.");
538 asm("   tpcbr   b1");
539 /* setup base registers b3 through b7 (data references). */
540 asm("   file    basevals,b3");
541 /* setup base register b2 (stack pointer); it should be
542    aligned on a 8-word boundary; but because it is pointing
543    to argc, its value should be remembered (in r5). */
544 asm("   movw    b2,r4");
545 asm("   movw    b2,r5");
546 asm("   andw    #~0x1f,r4");
547 asm("   movw    r4,b2");
548 /* allocate stack frame to do some work. */
549 asm("   subea   16w,b2");
550 /* initialize signal catching for UTX/32 1.2; this is
551    necessary to make restart from saved image work. */
552 asm("   movea   sigcatch,r1");
553 asm("   movw    r1,8w[b2]");
554 asm("   svc     #1,#150");
555 /* setup address of argc for start1. */
556 asm("   movw    r5,8w[b2]");
557 asm("   func    #1,_start1");
558 asm("   halt");
559 /* space for ld to store base register initial values. */
560 asm("   .align  5");
561 asm("basevals:");
562 asm("   .word   __base3,__base4,__base5,__base6,__base7");
563
564 static start1(xargc)
565 int *xargc;
566 {
567         int argc;
568         char **argv;
569
570         argc = *xargc;
571         argv = (char **)(xargc) + 1;
572         environ = argv + argc + 1;
573
574         if (environ == argv)
575                 environ--;
576         exit(main(argc, argv, environ));
577
578 }
579
580 #endif                          /* GOULD */
581
582 #ifdef elxsi
583 #include <elxsi/argvcache.h>
584
585 extern char **environ;
586 extern int errno;
587 extern void _init_doscan(), _init_iob();
588 extern char end[];
589 char *_init_brk = end;
590
591 _start()
592 {
593         environ = exec_cache.ac_envp;
594         brk(_init_brk);
595         errno = 0;
596         _init_doscan();
597         _init_iob();
598         _exit(exit(main(exec_cache.ac_argc,
599                         exec_cache.ac_argv, exec_cache.ac_envp)));
600 }
601 #endif                          /* elxsi */
602
603 #ifdef sparc
604 #ifdef no_toplevel_asm
605 static no_toplevel_asm_wrapper()
606 {
607 #ifdef USG5_4
608         asm(".pushsection \".text\"");
609 #endif                          /* USG5_4 */
610 #endif                          /* no_toplevel_asm */
611 #ifdef USG5_4
612         asm(".global _start");
613         asm(".text");
614         asm("_start:");
615         asm("   mov     0, %fp");
616         asm("   ld      [%sp + 64], %o0");
617         asm("   add     %sp, 68, %o1");
618         asm("   sll     %o0, 2, %o2");
619         asm("   add     %o2, 4, %o2");
620         asm("   add     %o1, %o2, %o2");
621         asm("   sethi   %hi(_environ), %o3");
622         asm("   st      %o2, [%o3+%lo(_environ)]");
623         asm("   andn    %sp, 7, %sp");
624         asm("   call    main");
625         asm("   sub     %sp, 24, %sp");
626         asm("   call    _exit");
627         asm("   nop");
628 #else
629         asm(".global __start");
630         asm(".text");
631         asm("__start:");
632         asm("   mov     0, %fp");
633         asm("   ld      [%sp + 64], %o0");
634         asm("   add     %sp, 68, %o1");
635         asm("   sll     %o0, 2, %o2");
636         asm("   add     %o2, 4, %o2");
637         asm("   add     %o1, %o2, %o2");
638         asm("   sethi   %hi(_environ), %o3");
639         asm("   st      %o2, [%o3+%lo(_environ)]");
640         asm("   andn    %sp, 7, %sp");
641         asm("   call    _main");
642         asm("   sub     %sp, 24, %sp");
643         asm("   call    __exit");
644         asm("   nop");
645 #endif                          /* USG5_4 */
646 #ifdef no_toplevel_asm
647 #ifdef USG5_4
648         asm(".popsection");
649 #endif                          /* USG5_4 */
650 }                               /* no_toplevel_asm_wrapper() */
651 #endif                          /* no_toplevel_asm */
652 #endif                          /* sparc */
653
654 #if __FreeBSD__ == 2
655 char *__progname;
656 #endif
657 #ifdef __bsdi__
658 #include <sys/param.h>          /* for version number */
659 #if defined(_BSDI_VERSION) && (_BSDI_VERSION >= 199501)
660 char *__progname;
661 #endif
662 #endif                          /* __bsdi__ */