update.
[chise/xemacs-chise.git-] / 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 XEmacs.
5
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
9 later version.
10
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
14 for more details.
15
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.  */
20
21 /* Synched up with: FSF 19.30. */
22
23
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.  */
28
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
35          0
36 Optionally:
37          [word pointing to environment variable]... 1 or more times
38          ...
39          0
40 And always:
41          first arg string
42          [next arg string]... 0 or more times
43 */
44
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
48          word containing argp
49          word pointing to first arg string, and so on as above
50 */
51
52 #ifdef emacs
53 #include <config.h>
54 #endif
55
56 #ifdef __GNUC__
57 #define asm __asm
58 #endif
59
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
63 #endif
64
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.  */
78
79 int data_start = 0;
80
81 #ifdef NEED_ERRNO
82 int errno;
83 #endif
84
85 #ifndef DONT_NEED_ENVIRON
86 char **environ;
87 #endif
88
89 #ifndef static
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.  */
94 static start1 ();
95 #endif
96
97 #ifdef APOLLO
98 extern  char   *malloc(), *realloc(), *(*_libc_malloc) (), *(*_libc_realloc)();
99 extern  void    free(), (*_libc_free) (); extern int main();
100 std_$call void  unix_$main();
101
102 _start()
103 {
104         _libc_malloc = malloc;
105         _libc_realloc = realloc;
106         _libc_free = free;
107         unix_$main(main);       /* no return */
108 }
109 #endif /* APOLLO */
110
111 #if defined(orion) || defined(pyramid) || defined(celerity) || defined(ALLIANT) || defined(clipper) || defined(sps7)
112
113 #if defined(sps7) && defined(V3x)
114         asm("   section 10");
115         asm("   ds.b    0xb0");
116 #endif
117
118 #ifdef ALLIANT
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;
126 #ifdef ALLIANT_2800
127 unsigned char *_end = &end;
128 #endif
129 #endif
130
131 #ifndef DUMMIES
132 #define DUMMIES
133 #endif
134
135 _start (DUMMIES argc, argv, envp)
136      int argc;
137      char **argv, **envp;
138 {
139 #ifdef ALLIANT
140 #ifdef ALLIANT_2800
141   _curbrk = _end;
142   _minbrk = _end;
143 #else
144   _curbrk = _setbrk;
145   _minbrk = _setbrk;
146 #endif
147 #endif
148
149   environ = envp;
150
151   exit (main (argc, argv, envp));
152 }
153
154 #endif /* orion or pyramid or celerity or alliant or clipper */
155
156 #if defined (ns16000) && !defined (sequent) && !defined (UMAX) && !defined (CRT0_DUMMIES)
157
158 _start ()
159 {
160 /* On 16000, _start pushes fp onto stack */
161   start1 ();
162 }
163
164 /* ignore takes care of skipping the fp value pushed in start.  */
165 static
166 start1 (ignore, argc, argv)
167      int ignore;
168      int argc;
169      char **argv;
170 {
171   environ = argv + argc + 1;
172
173   if (environ == *argv)
174     environ--;
175   exit (main (argc, argv, environ));
176 }
177 #endif /* ns16000, not sequent and not UMAX, and not the CRT0_DUMMIES method */
178
179 #ifdef UMAX
180 _start()
181 {
182         asm("   exit []                 # undo enter");
183         asm("   .set    exitsc,1");
184         asm("   .set    sigcatchall,0x400");
185
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");
193
194         asm("start:");
195         asm("   br      .xstart");
196         asm("   .org    0x20");
197         asm("   .double p_glbl,0,0xf00000,0");
198         asm("   .org    0x30");
199         asm(".xstart:");
200         asm("   adjspb  $8");
201         asm("   movd    8(sp),0(sp)     # argc");
202         asm("   addr    12(sp),r0");
203         asm("   movd    r0,4(sp)        # argv");
204         asm("L1:");
205         asm("   movd    r0,r1");
206         asm("   addqd   $4,r0");
207         asm("   cmpqd   $0,0(r1)        # null args term ?");
208         asm("   bne     L1");
209         asm("   cmpd    r0,0(4(sp))     # end of 'env' or 'argv' ?");
210         asm("   blt     L2");
211         asm("   addqd   $-4,r0          # envp's are in list");
212         asm("L2:");
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");
219         asm("   adjspb  $-12");
220         asm("   jsr     @_main");
221         asm("   adjspb  $-12");
222         asm("   movd    r0,tos");
223         asm("   jsr     @_exit");
224         asm("   adjspb  $-4");
225         asm("   addr    @exitsc,r0");
226         asm("   svc");
227         asm("   .align  4               # sigvec arg");
228         asm("sv:");
229         asm("   .double sigentry");
230         asm("   .double 0");
231         asm("   .double 0");
232
233         asm("   .comm   p_glbl,1");
234 }
235 #endif /* UMAX */
236
237 #ifdef CRT0_DUMMIES
238
239 /* Define symbol "start": here; some systems want that symbol.  */
240 #ifdef DOT_GLOBAL_START
241 asm("   .text           ");
242 asm("   .globl start    ");
243 asm("   start:          ");
244 #endif /* DOT_GLOBAL_START */
245
246 #ifdef NODOT_GLOBAL_START
247 asm("   text            ");
248 asm("   global start    ");
249 asm("   start:          ");
250 #endif /* NODOT_GLOBAL_START */
251
252 #ifdef m68000
253
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.  */
257 asm(".text                      ");
258 #ifndef sony_news
259   asm(" .even                   ");
260 #else /* sony_news (not gas) */
261 + asm(" .align 2                ");
262 #endif /* sony_news (not gas) */
263 asm(".globl __start             ");
264 asm("__start:                   ");
265 asm("   link a6,#0              ");
266 asm("   jbsr _start1            ");
267 asm("   unlk a6                 ");
268 asm("   rts                     ");
269
270 #else /* not m68000 */
271
272 int
273 _start ()
274 {
275 /* On vax, nothing is pushed here  */
276 /* On sequent, bogus fp is pushed here  */
277   start1 ();
278 }
279
280 #endif /* possibly m68000 */
281
282 #ifdef __bsdi__ /* for version number */
283 #include <sys/param.h>
284 #endif
285 #if defined(_BSDI_VERSION) && (_BSDI_VERSION >= 199501)
286 char *__progname;
287 #endif
288 static int
289 start1 (CRT0_DUMMIES int argc, char *xargv)
290 {
291   char **argv = &xargv;
292   environ = argv + argc + 1;
293 #if defined(_BSDI_VERSION) && (_BSDI_VERSION >= 199501)
294   __progname = argv[0];
295 #endif
296
297   if ((char *)environ == xargv)
298     environ--;
299   exit (main (argc, argv, environ));
300
301   /* Refer to `start1' so GCC will not think it is never called
302      and optimize it out.  */
303   (void) &start1;
304 }
305 #else /* not CRT0_DUMMIES */
306
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.  */
315
316 #ifdef m68k                     /* Can't do it all from C */
317         asm ("  global  _start");
318         asm ("  text");
319         asm ("_start:");
320 #ifndef NU
321 #ifdef STRIDE
322         asm ("  comm    havefpu%,2");
323 #else /* m68k, not STRIDE */
324         asm ("  comm    splimit%,4");
325 #endif /* STRIDE */
326         asm ("  global  exit");
327         asm ("  text");
328 #ifdef STRIDE
329         asm ("  trap    &3");
330         asm ("  mov.w   %d0,havefpu%");
331 #else /* m68k, not STRIDE */
332         asm ("  mov.l   %d0,splimit%");
333 #endif /* STRIDE */
334 #endif /* not NU */
335         asm ("  jsr     start1");
336         asm ("  mov.l   %d0,(%sp)");
337         asm ("  jsr     exit");
338         asm ("  mov.l   &1,%d0");       /* d0 = 1 => exit */
339         asm ("  trap    &0");
340 #else /* m68000, not m68k */
341
342 #ifdef m68000
343
344 #ifdef ISI68K
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__)
348 static foo () {
349 #endif
350         asm ("  .globl  is68020");
351         asm ("is68020:");
352 #ifndef BSD4_3
353         asm ("  .long   0x00000000");
354         asm ("  .long   0xffffffff");
355 /* End of stuff added by ESM */
356 #endif
357         asm ("  .text");
358         asm ("  .globl  __start");
359         asm ("__start:");
360         asm ("  .word 0");
361         asm ("  link    a6,#0");
362         asm ("  jbsr    _start1");
363         asm ("  unlk    a6");
364         asm ("  rts");
365 #if defined(BSD4_3) && !defined(__GNUC__)
366       }
367 #endif
368 #else /* not ISI68K */
369
370 _start ()
371 {
372 #ifdef sun
373 #ifdef LISP_FLOAT_TYPE
374   finitfp_();
375 #endif
376 #endif     
377 /* On 68000, _start pushes a6 onto stack  */
378   start1 ();
379 }
380 #endif /* not ISI68k */
381 #endif /* m68000 */
382 #endif /* m68k */
383
384 #if defined(m68k) || defined(m68000)
385 /* ignore takes care of skipping the a6 value pushed in start.  */
386 static
387 #if defined(m68k)
388 start1 (argc, xargv)
389 #else
390 start1 (ignore, argc, xargv)
391 #endif
392      int argc;
393      char *xargv;
394 {
395   char **argv = &xargv;
396   environ = argv + argc + 1;
397
398   if ((char *)environ == xargv)
399     environ--;
400 #ifdef sun_68881
401   asm("    jsr     f68881_used");
402 #endif
403 #ifdef sun_fpa
404   asm("    jsr     ffpa_used");
405 #endif
406 #ifdef sun_soft
407   asm("    jsr     start_float");
408 #endif
409   exit (main (argc, argv, environ));
410 }
411
412 #endif /* m68k or m68000 */
413
414 #endif /* not CRT0_DUMMIES */
415
416 #ifdef hp9000s300
417 int argc_value;
418 char **argv_value;
419 #ifdef OLD_HP_ASSEMBLER
420         asm("   text");
421         asm("   globl __start");
422         asm("   globl _exit");
423         asm("   globl _main");
424         asm("__start");
425         asm("   dc.l    0");
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)");
432         asm("skip_1");
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");
440         asm("incr_loop");
441         asm("   tst.l   (a0)+");
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");
447         asm("skip_2");
448         asm("   move.l  a0,0x8(a7)");
449         asm("   move.l  a0,_environ");
450         asm("   jsr     _main");
451         asm("   addq.l  #0x8,a7");
452         asm("   move.l  d0,-(a7)");
453         asm("   jsr     _exit");
454         asm("   move.w  #0x1,d0");
455         asm("   trap    #0x0");
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. */
459
460 #else /* new hp assembler */
461
462         asm("   text");
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");
470         asm("__start:");
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");
475 #ifndef HPUX_68010
476         asm("   beq.b   skip_float");
477         asm("   fmov.l  &0x7400,%fpcr");
478 /*      asm("   fmov.l  &0x7480,%fpcr"); */
479 #endif /* HPUX_68010 */
480         asm("skip_float:");
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");
488         asm("   tst.l   %d2");
489         asm("   ble.b   skip_3");
490         asm("   lsl     flag_68881");
491         asm("   lsl     flag_fpa");
492         asm("skip_3:");
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)");
497         asm("skip_1:");
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");
505         asm("incr_loop:");
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");
512         asm("skip_2:");
513         asm("   mov.l   %a0,8(%a7)");
514         asm("   mov.l   %a0,_environ");
515         asm("   jsr     _main");
516         asm("   addq.l  &8,%a7");
517         asm("   mov.l   %d0,-(%a7)");
518         asm("   jsr     _exit");
519         asm("   mov.w   &1,%d0");
520         asm("   trap    &0");
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");
526
527 #endif /* new hp assembler */
528 #endif /* hp9000s300 */
529
530 #ifdef GOULD
531
532 /* startup code has to be in near text rather
533    than fartext as allocated by the C compiler. */
534         asm("   .text");
535         asm("   .align  2");
536         asm("   .globl  __start");
537         asm("   .text");
538         asm("__start:");
539 /* setup base register b1 (function base). */
540         asm("   .using  b1,.");
541         asm("   tpcbr   b1");
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). */
547         asm("   movw    b2,r4");
548         asm("   movw    b2,r5");
549         asm("   andw    #~0x1f,r4");
550         asm("   movw    r4,b2");
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]");
557         asm("   svc     #1,#150");
558 /* setup address of argc for start1. */
559         asm("   movw    r5,8w[b2]");
560         asm("   func    #1,_start1");
561         asm("   halt");
562 /* space for ld to store base register initial values. */
563         asm("   .align  5");
564         asm("basevals:");
565         asm("   .word   __base3,__base4,__base5,__base6,__base7");
566
567 static
568 start1 (xargc)
569      int *xargc;
570 {
571   int   argc;
572   char **argv;
573
574   argc = *xargc;
575   argv = (char **)(xargc) + 1;
576   environ = argv + argc + 1;
577
578   if (environ == argv)
579     environ--;
580   exit (main (argc, argv, environ));
581
582 }
583
584 #endif /* GOULD */
585
586 #ifdef elxsi
587 #include <elxsi/argvcache.h>
588
589 extern char **environ;
590 extern int      errno;
591 extern void     _init_doscan(), _init_iob();
592 extern char     end[];
593 char            *_init_brk = end;
594
595 _start()
596 {
597   environ = exec_cache.ac_envp;
598   brk (_init_brk);
599   errno = 0;
600   _init_doscan ();
601   _init_iob ();
602   _exit (exit (main (exec_cache.ac_argc,
603                      exec_cache.ac_argv,
604                      exec_cache.ac_envp)));
605 }
606 #endif /* elxsi */
607
608
609 #ifdef sparc
610 #ifdef no_toplevel_asm
611 static no_toplevel_asm_wrapper() {
612 #ifdef USG5_4
613 asm (".pushsection \".text\"");
614 #endif /* USG5_4 */
615 #endif /* no_toplevel_asm */
616 #ifdef USG5_4
617 asm (".global _start");
618 asm (".text");
619 asm ("_start:");
620 asm ("  mov     0, %fp");
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");
629 asm ("  call    main");
630 asm ("  sub     %sp, 24, %sp");
631 asm ("  call    _exit");
632 asm ("  nop");
633 #else
634 asm (".global __start");
635 asm (".text");
636 asm ("__start:");
637 asm ("  mov     0, %fp");
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");
646 asm ("  call    _main");
647 asm ("  sub     %sp, 24, %sp");
648 asm ("  call    __exit");
649 asm ("  nop");
650 #endif /* USG5_4 */
651 #ifdef no_toplevel_asm
652 #ifdef USG5_4
653 asm (".popsection");
654 #endif /* USG5_4 */
655 } /* no_toplevel_asm_wrapper() */
656 #endif /* no_toplevel_asm */
657 #endif /* sparc */
658
659 #if __FreeBSD__ == 2
660 char *__progname;
661 #endif
662 #ifdef __bsdi__
663 #include <sys/param.h> /* for version number */
664 #if defined(_BSDI_VERSION) && (_BSDI_VERSION >= 199501)
665 char *__progname;
666 #endif
667 #endif /* __bsdi__ */