home *** CD-ROM | disk | FTP | other *** search
/ Education Sampler 1992 [NeXTSTEP] / Education_1992_Sampler.iso / NeXT / GnuSource / cplusplus-8 / crt0.c < prev    next >
C/C++ Source or Header  |  1991-04-30  |  23KB  |  802 lines

  1. /* C++ code startup routine.
  2.    Copyright (C) 1985, 1986 Free Software Foundation, Inc.
  3.    Hacked by Michael Tiemann (tiemann@mcc.com)
  4.  
  5.                NO WARRANTY
  6.  
  7.   BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
  8. NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW.  EXCEPT
  9. WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
  10. RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
  11. WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
  12. BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  13. FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY
  14. AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE
  15. DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
  16. CORRECTION.
  17.  
  18.  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
  19. STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
  20. WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
  21. LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
  22. OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
  23. USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
  24. DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
  25. A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
  26. PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
  27. DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
  28.  
  29.         GENERAL PUBLIC LICENSE TO COPY
  30.  
  31.   1. You may copy and distribute verbatim copies of this source file
  32. as you receive it, in any medium, provided that you conspicuously and
  33. appropriately publish on each copy a valid copyright notice "Copyright
  34. (C) 1986 Free Software Foundation, Inc."; and include following the
  35. copyright notice a verbatim copy of the above disclaimer of warranty
  36. and of this License.
  37.  
  38.   2. You may modify your copy or copies of this source file or
  39. any portion of it, and copy and distribute such modifications under
  40. the terms of Paragraph 1 above, provided that you also do the following:
  41.  
  42.     a) cause the modified files to carry prominent notices stating
  43.     that you changed the files and the date of any change; and
  44.  
  45.     b) cause the whole of any work that you distribute or publish,
  46.     that in whole or in part contains or is a derivative of this
  47.     program or any part thereof, to be licensed at no charge to all
  48.     third parties on terms identical to those contained in this
  49.     License Agreement (except that you may choose to grant more extensive
  50.     warranty protection to some or all third parties, at your option).
  51.  
  52.     c) You may charge a distribution fee for the physical act of
  53.     transferring a copy, and you may at your option offer warranty
  54.     protection in exchange for a fee.
  55.  
  56. Mere aggregation of another unrelated program with this program (or its
  57. derivative) on a volume of a storage or distribution medium does not bring
  58. the other program under the scope of these terms.
  59.  
  60.   3. You may copy and distribute this program (or a portion or derivative
  61. of it, under Paragraph 2) in object code or executable form under the terms
  62. of Paragraphs 1 and 2 above provided that you also do one of the following:
  63.  
  64.     a) accompany it with the complete corresponding machine-readable
  65.     source code, which must be distributed under the terms of
  66.     Paragraphs 1 and 2 above; or,
  67.  
  68.     b) accompany it with a written offer, valid for at least three
  69.     years, to give any third party free (except for a nominal
  70.     shipping charge) a complete machine-readable copy of the
  71.     corresponding source code, to be distributed under the terms of
  72.     Paragraphs 1 and 2 above; or,
  73.  
  74.     c) accompany it with the information you received as to where the
  75.     corresponding source code may be obtained.  (This alternative is
  76.     allowed only for noncommercial distribution and only if you
  77.     received the program in object code or executable form alone.)
  78.  
  79. For an executable file, complete source code means all the source code for
  80. all modules it contains; but, as a special exception, it need not include
  81. source code for modules which are standard libraries that accompany the
  82. operating system on which the executable file runs.
  83.  
  84.   4. You may not copy, sublicense, distribute or transfer this program
  85. except as expressly provided under this License Agreement.  Any attempt
  86. otherwise to copy, sublicense, distribute or transfer this program is void and
  87. your rights to use the program under this License agreement shall be
  88. automatically terminated.  However, parties who have received computer
  89. software programs from you with this License Agreement will not have
  90. their licenses terminated so long as such parties remain in full compliance.
  91.  
  92.   5. If you wish to incorporate parts of this program into other free
  93. programs whose distribution conditions are different, write to the Free
  94. Software Foundation at 675 Mass Ave, Cambridge, MA 02139.  We have not yet
  95. worked out a simple rule that can be stated here, but we will often permit
  96. this.  We will be guided by the two goals of preserving the free status of
  97. all derivatives of our free software and of promoting the sharing and reuse of
  98. software.
  99.  
  100.  
  101. In other words, you are welcome to use, share and improve this program.
  102. You are forbidden to forbid anyone else to use, share and improve
  103. what you give them.   Help stamp out software-hoarding!  */
  104.  
  105.  
  106. /* The standard Vax 4.2 Unix crt0.c cannot be used for Emacs
  107.    because it makes `envron' an initialized variable.
  108.    It is easiest to have a special crt0.c on all machines
  109.    though I don't know whether other machines actually need it.  */
  110.  
  111. /* Also, the standard crt0.c cannot be used for C++, since C++
  112.    guarantees to call global constructors before main () is
  113.    called, and to call global destructors after control has left from
  114.    main ().  */
  115.  
  116. /* On the vax and 68000, in BSD4.2 and USG5.2,
  117.    this is the data format on startup:
  118.   (vax) ap and fp are unpredictable as far as I know; don't use them.
  119.   sp ->  word containing argc
  120.          word pointing to first arg string
  121.      [word pointing to next arg string]... 0 or more times
  122.      0
  123. Optionally:
  124.      [word pointing to environment variable]... 1 or more times
  125.      ...
  126.      0
  127. And always:
  128.      first arg string
  129.      [next arg string]... 0 or more times
  130. */
  131.  
  132. /* On the 16000, at least in the one 4.2 system I know about,
  133.   the initial data format is
  134.   sp ->  word containing argc
  135.          word containing argp
  136.          word pointing to first arg string, and so on as above
  137. */
  138.  
  139. /* On Suns, and possibly on other machines, a routine called
  140.    `on_exit' is used to call termination handling routines.
  141.    If your system provides this feature, define the macro
  142.    ON_EXIT to perform this task.  It is called after a  program
  143.    calls exit(3)  or  returns  normally,  and before its process
  144.    terminates.  The routine named is called as
  145.  
  146.         (*procp)(status, arg);
  147.  
  148.    where status is the argument with which exit was called,  or
  149.    zero  if  main returns.  Typically, arg is the address of an
  150.    argument vector to (*procp), but may be  an  integer  value.
  151.    Several  calls  may  be  made to ON_EXIT, specifying several
  152.    termination handlers. The order in which they are called  is
  153.    the reverse of that in which they were given to ON_EXIT.
  154.  
  155.    Some systems may impose a limit on the number of termination
  156.    handlers which can be specified.  Users near that limit are
  157.    warned that GNU C++ will take one of those slots.
  158.  
  159.    Note that proper GNU C++ code will not need to rely on this
  160.    mechanism at the application level, because thoughtfully
  161.    constructed classes will take care of this automatically.
  162.    There is no limit to the number of classes which GNU C++
  163.    can destroy.  :-) */
  164.  
  165. #include "config.h"
  166.  
  167. extern void exit ();
  168. extern void __do_global_init ();
  169. extern void __do_global_cleanup ();
  170.  
  171. /*        ********  WARNING ********
  172.     Do not insert any data definitions before data_start!
  173.     Since this is the first file linked, the address of the following
  174.     variable should correspond to the start of initialized data space.
  175.     On some systems this is a constant that is independent of the text
  176.     size for shared executables.  On others, it is a function of the
  177.     text size. In short, this seems to be the most portable way to
  178.     discover the start of initialized data space dynamically at runtime,
  179.     for either shared or unshared executables, on either swapping or
  180.     virtual systems.  It only requires that the linker allocate objects
  181.     in the order encountered, a reasonable model for most Unix systems.
  182.     Similarly, note that the address of _start() should be the start
  183.     of text space.   Fred Fish, UniSoft Systems Inc.  */
  184.  
  185. int data_start = 0;
  186.    
  187. #ifdef NEED_ERRNO
  188. int errno = 0;
  189. #endif
  190.  
  191. #ifndef DONT_NEED_ENVIRON 
  192. char **environ;
  193. #endif
  194.  
  195. #if defined(sequent)
  196.     asm("    .globl _387_flt");
  197.     asm("    .set    _387_flt,0");
  198. #endif
  199.  
  200. #ifdef convex
  201. int use_libc_sema = 0;
  202. #endif
  203.  
  204. #if defined(sun)
  205. #define ON_EXIT(PROCP, ARG) \
  206.   do { extern void PROCP (); on_exit (PROCP, ARG); } while (0)
  207. #endif
  208.  
  209. #ifndef sun386            /* Not compatible with i386, sigh */
  210. #if defined(i386) || defined(ALTOS)
  211. _start(arg)
  212. char *arg;
  213. {
  214.   int argc = (int)(&arg)[-1];
  215.   environ = &arg + argc + 1;
  216. #ifndef sequent
  217.   setchrclass((char *)0);
  218. #endif
  219.   __do_global_init();
  220.   exit(main(argc, &arg, environ));
  221. }
  222. #endif
  223. #endif /* sun386 */
  224.  
  225. #if defined(orion) || defined(pyramid) || defined(celerity) || defined(ALLIANT)
  226.  
  227. #ifdef ALLIANT
  228. /* _start must initialize _curbrk and _minbrk on the first startup;
  229.    when starting up after dumping, it must initialize them to what they were
  230.    before the dumping, since they are in the shared library and
  231.    are not dumped.  See ADJUST_EXEC_HEADER in m-alliant.h.  */
  232. extern unsigned char *_curbrk, *_minbrk;
  233. extern unsigned char end;
  234. unsigned char *_setbrk = &end;
  235. #endif
  236.  
  237. _start (argc, argv, envp)
  238.      int argc;
  239.      char **argv, **envp;
  240. {
  241. #ifdef ALLIANT
  242.   _curbrk = _setbrk;
  243.   _minbrk = _setbrk;
  244. #endif
  245.  
  246.   environ = envp;
  247.  
  248.   __do_global_init ();
  249.   exit (main (argc, argv, envp));
  250. }
  251.  
  252. #endif /* orion or pyramid or celerity or alliant */
  253.  
  254. #if defined (ns16000) && !defined (sequent) && !defined (UMAX)
  255.  
  256. _start ()
  257. {
  258. /* On 16000, _start pushes fp onto stack */
  259.   start1 ();
  260. }
  261.  
  262. /* ignore takes care of skipping the fp value pushed in start.  */
  263. static
  264. start1 (ignore, argc, argv)
  265.      int ignore;
  266.      int argc;
  267.      register char **argv;
  268. {
  269.   environ = argv + argc + 1;
  270.  
  271.   if (environ == *argv)
  272.     environ--;
  273.  
  274.   __do_global_init ();
  275.   exit (main (argc, argv, environ));
  276. }
  277. #endif /* ns16000, not sequent and not UMAX */
  278.  
  279. #ifdef UMAX
  280. _start()
  281. {
  282.     asm("    exit []            # undo enter");
  283.     asm("    .set    exitsc,1");
  284.     asm("    .set    sigcatchall,0x400");
  285.  
  286.     asm("    .globl    _exit");
  287.     asm("    .globl    start");
  288.     asm("    .globl    __start");
  289.     asm("    .globl    _main");
  290.     asm("    .globl    _environ");
  291.     asm("    .globl    _sigvec");
  292.     asm("    .globl    sigentry");
  293.  
  294.     asm("start:");
  295.     asm("    br    .xstart");
  296.     asm("    .org    0x20");
  297.     asm("    .double    p_glbl,0,0xf00000,0");
  298.     asm("    .org    0x30");
  299.     asm(".xstart:");
  300.     asm("    adjspb    $8");
  301.     asm("    movd    8(sp),0(sp)    # argc");
  302.     asm("    addr    12(sp),r0");
  303.     asm("    movd    r0,4(sp)    # argv");
  304.     asm("L1:");
  305.     asm("    movd    r0,r1");
  306.     asm("    addqd    $4,r0");
  307.     asm("    cmpqd    $0,0(r1)    # null args term ?");
  308.     asm("    bne    L1");
  309.     asm("    cmpd    r0,0(4(sp))    # end of 'env' or 'argv' ?");
  310.     asm("    blt    L2");
  311.     asm("    addqd    $-4,r0        # envp's are in list");
  312.     asm("L2:");
  313.     asm("    movd    r0,8(sp)    # env");
  314.     asm("    movd    r0,@_environ    # indir is 0 if no env ; not 0 if env");
  315.     asm("    movqd    $0,tos        # setup intermediate signal handler");
  316.     asm("    addr    @sv,tos");
  317.     asm("    movzwd    $sigcatchall,tos");
  318.     asm("    jsr    @_sigvec");
  319.     asm("    adjspb    $-12");
  320.     asm("    jsr    @___do_global_init");
  321.     asm("    jsr    @_main");
  322.     asm("    adjspb    $-12");
  323.     asm("    movd    r0,tos");
  324.     asm("    jsr    @___do_global_cleanup");
  325.     asm("    jsr    @_exit");
  326.     asm("    adjspb    $-4");
  327.     asm("    addr    @exitsc,r0");
  328.     asm("    svc");
  329.     asm("    .align    4        # sigvec arg");
  330.     asm("sv:");
  331.     asm("    .double    sigentry");
  332.     asm("    .double    0");
  333.     asm("    .double    0");
  334.  
  335.     asm("    .comm    p_glbl,1");
  336. }
  337. #endif /* UMAX */
  338.  
  339. #ifdef CRT0_DUMMIES
  340.  
  341. /* Define symbol "start": here; some systems want that symbol.  */
  342. #ifdef DOT_GLOBAL_START
  343. asm("    .text        ");
  344. asm("    .globl start    ");
  345. asm("    start:        ");
  346. #endif /* DOT_GLOBAL_START */
  347.  
  348. #ifdef NODOT_GLOBAL_START
  349. asm("    text        ");
  350. asm("    global start    ");
  351. asm("    start:        ");
  352. #endif /* NODOT_GLOBAL_START */
  353.  
  354. #ifdef hp300
  355. asm("    .text        ");
  356. asm("    .long 0        ");    /* conveniently both a 0 and a nop */
  357. #endif
  358.  
  359. _start ()
  360. {
  361. /* On vax, nothing is pushed here  */
  362. /* On sequent, bogus fp is pushed here  */
  363.   start1 ();
  364. }
  365.  
  366. static
  367. start1 (CRT0_DUMMIES argc, xargv)
  368.      int argc;
  369.      char *xargv;
  370. {
  371.   register char **argv = &xargv;
  372.   environ = argv + argc + 1;
  373.  
  374.   if ((char *)environ == xargv)
  375.     environ--;
  376.  
  377.   __do_global_init ();
  378.   exit (main (argc, argv, environ));
  379. }
  380. #else /* not CRT0_DUMMIES */
  381.  
  382. /* "m68k" and "m68000" both stand for m68000 processors,
  383.    but with different program-entry conventions.
  384.    This is a kludge.  Now that the CRT0_DUMMIES mechanism above exists,
  385.    most of these machines could use the vax code above
  386.    with some suitable definition of CRT0_DUMMIES.
  387.    Then the symbol m68k could be flushed.
  388.    But I don't want to risk breaking these machines
  389.    in a version 17 patch release, so that change is being put off.  */
  390.  
  391. #ifdef m68k            /* Can't do it all from C */
  392.     asm ("    global    _start");
  393.     asm ("    text");
  394.     asm ("_start:");
  395. #ifndef NU
  396. #ifdef STRIDE
  397.     asm ("    comm    havefpu%,2");
  398. #else /* m68k, not STRIDE */
  399.     asm ("    data");
  400.     asm ("    even");
  401.     asm ("    global    splimit%");
  402.     asm ("splimit%:");
  403.     asm ("    space 4");
  404. #endif /* STRIDE */
  405.     asm ("    global    exit");
  406.     asm ("    text");
  407. #ifdef STRIDE
  408.     asm ("    trap    &3");
  409.     asm ("    mov.w    %d0,havefpu%");
  410. #else /* m68k, not STRIDE */
  411.       asm ("    mov.l    %d0,splimit%");
  412. #endif /* STRIDE */
  413. #endif /* not NU */
  414.     asm ("    jsr    start1");
  415.     asm ("    mov.l    %d0,(%sp)");
  416.     asm ("    jsr    exit");
  417.     asm ("    mov.l    &1,%d0");    /* d0 = 1 => exit */
  418.     asm ("    trap    &0");
  419. #else /* m68000, not m68k */
  420.  
  421. #if defined(m68000) || defined(mc68000) || defined(mc68020) || defined(sun386)
  422.   
  423. #ifdef ISI68K
  424. /* Added by ESM Sun May 24 12:44:02 1987 to get new ISI library to work */
  425.     asm ("    .globl  is68020");
  426.     asm ("is68020:");
  427.     asm ("    .long   0x00000000");
  428.     asm ("    .long   0xffffffff");
  429. /* End of stuff added by ESM */
  430.     asm ("    .text");
  431.     asm ("    .globl    __start");
  432.     asm ("__start:");
  433.     asm ("    .word 0");
  434.     asm ("    link    fp,#0");
  435.     asm ("    jbsr    _start1");
  436.     asm ("    unlk    fp");
  437.     asm ("    rts");
  438. #else /* not ISI68K */
  439. _start ()
  440. {
  441.   static start1 ();
  442.   /* On 68000, _start pushes a6 onto stack (as does the sun386i, sort of...) */
  443.   start1 ();
  444. }
  445. #endif /* not ISI68k */
  446. #endif /* m68000 || mc68000 || mc68020 || sun386 */
  447. #endif /* m68k */
  448.  
  449. #if defined(m68k) || defined(m68000) || defined(mc68000) || defined(mc68020) || defined(sun386)
  450. /* ignore takes care of skipping the a6 value pushed in start.  */
  451. static
  452. #if defined(m68k)
  453. start1 (argc, xargv)
  454. #else
  455. start1 (ignore, argc, xargv)
  456. #endif
  457.      int argc;
  458.      char *xargv;
  459. {
  460.   register char **argv = &xargv;
  461.   environ = argv + argc + 1;
  462.  
  463.   if ((char *)environ == xargv)
  464.     environ--;
  465.  
  466. #ifdef ON_EXIT
  467.  
  468. #ifdef sun
  469.   ON_EXIT (_cleanup, 0);
  470. #endif
  471.  
  472.   ON_EXIT (__do_global_cleanup, 0);
  473.  
  474. #endif
  475.  
  476.   __do_global_init ();
  477.   exit (main (argc, argv, environ));
  478. }
  479.  
  480. #endif /* m68k or m68000 or mc68000 or mc68020 or sun386 */
  481.  
  482. #endif /* not CRT0_DUMMIES */
  483.  
  484. /* Should "hp9000" be completely removed?  */
  485. #if defined(hp9000) || defined(hp9000s300)
  486. int argc_value;
  487. char **argv_value;
  488. #ifdef OLD_HP_ASSEMBLER
  489.     asm("   text");
  490.     asm("    globl __start");
  491.     asm("    globl _exit");
  492.     asm("    globl _main");
  493.     asm("__start");
  494.     asm("    dc.l    0");
  495.     asm("    subq.w    #0x1,d0");
  496.     asm("    move.w    d0,float_soft");
  497.     asm("    move.l    0x4(a7),d0");
  498.     asm("    beq.s    skip_1");
  499.     asm("    move.l    d0,a0");
  500.     asm("    clr.l    -0x4(a0)");
  501.     asm("skip_1");
  502.     asm("    move.l    a7,a0");
  503.     asm("    subq.l    #0x8,a7");
  504.     asm("    move.l    (a0),(a7)");
  505.     asm("    move.l    (a0),_argc_value");
  506.     asm("    addq.l    #0x4,a0");
  507.     asm("    move.l    a0,0x4(a7)");
  508.     asm("    move.l    a0,_argv_value");
  509.     asm("incr_loop");
  510.     asm("    tst.l    (a0)+");
  511.     asm("    bne.s    incr_loop");
  512.     asm("    move.l    0x4(a7),a1");
  513.     asm("    cmp.l    (a1),a0");
  514.     asm("    blt.s    skip_2");
  515.     asm("    subq.l    #0x4,a0");
  516.     asm("skip_2");
  517.     asm("    move.l    a0,0x8(a7)");
  518.     asm("    move.l    a0,_environ");
  519.     asm("    jsr    ___do_global_init");
  520.     asm("    jsr    _main");
  521.     asm("    addq.l    #0x8,a7");
  522.     asm("    move.l    d0,-(a7)");
  523.     asm("    jsr    _exit");
  524.     asm("    move.w    #0x1,d0");
  525.     asm("    trap    #0x0");
  526.     asm("    comm    float_soft,4");
  527. /* float_soft is allocated in this way because C would
  528.    put an underscore character in its name otherwise. */ 
  529.  
  530. #else /* new hp assembler */
  531.  
  532.     asm("    text");
  533.     asm("    global    __start");
  534.     asm("    global    _exit");
  535.     asm("    global    _main");
  536.         asm("   global  flag_fpa,flag_68010,fpa_loc,float_loc");
  537.     asm("__start:");
  538.     asm("    byte    0,0,0,0");
  539.     asm("   sub.l   %a6,%a6");
  540.     asm("    subq.w    &1,%d0");
  541.     asm("    mov.w    %d0,float_soft");
  542.     asm("    mov.w    %d1,flag_68881");
  543.     asm("    beq.b    skip_float"); 
  544.     asm("    fmov.l    &0x7400,%fpcr");
  545.     asm("skip_float:");
  546.     asm("   move.l  %a0,%d0");
  547.     asm("   add.l   %d0,%d0");
  548.     asm("   subx.w  %d1,%d1");
  549.     asm("   move.w  %d1,flag_68010");
  550.     asm("   add.l   %d0,%d0");
  551.     asm("   subx.w  %d1,%d1");
  552.     asm("   move.w  %d1,flag_fpa");
  553.     asm("    mov.l    4(%a7),%d0");
  554.     asm("    beq.b    skip_1");
  555.     asm("    mov.l    %d0,%a0");
  556.     asm("    clr.l    -4(%a0)");
  557.     asm("skip_1:");
  558.     asm("    mov.l    %a7,%a0");
  559.     asm("    subq.l    &8,%a7");
  560.     asm("    mov.l    (%a0),(%a7)");
  561.     asm("    mov.l    (%a0),_argc_value");
  562.     asm("    addq.l    &4,%a0");
  563.     asm("    mov.l    %a0,4(%a7)");
  564.     asm("    mov.l    %a0,_argv_value");
  565.     asm("incr_loop:");
  566.     asm("    tst.l    (%a0)+");
  567.     asm("    bne.b    incr_loop");
  568.     asm("    mov.l    4(%a7),%a1");
  569.     asm("    cmp.l    %a0,(%a1)");
  570.     asm("    blt.b    skip_2");
  571.     asm("    subq.l    &4,%a0");
  572.     asm("skip_2:");
  573.     asm("    mov.l    %a0,8(%a7)");
  574.     asm("    mov.l    %a0,_environ");
  575.     asm("    jsr    ___do_global_init");
  576.     asm("    jsr    _main");
  577.     asm("    addq.l    &8,%a7");
  578.     asm("    mov.l    %d0,-(%a7)");
  579.     asm("    jsr    _exit");
  580.     asm("    mov.w    &1,%d0");
  581.     asm("    trap    &0");
  582.     asm("    comm    float_soft, 4");
  583.     asm("    comm    flag_68881, 4");
  584.     asm("    comm    flag_68010, 4");
  585.     asm("    comm    flag_fpa,   4");
  586.     asm("   set     float_loc,0xffffb000");
  587.     asm("   set     fpa_loc,0xfff08000");
  588.  
  589. #endif /* new hp assembler */
  590. #endif /* hp9000 */
  591.  
  592. #ifdef GOULD
  593.  
  594. /* startup code has to be in near text rather
  595.    than fartext as allocated by the C compiler. */
  596.     asm("    .text");
  597.     asm("    .align    2");
  598.     asm("    .globl    __start");
  599.     asm("    .text");
  600.     asm("__start:");
  601. /* setup base register b1 (function base). */
  602.     asm("    .using    b1,.");
  603.     asm("    tpcbr    b1");
  604. /* setup base registers b3 through b7 (data references). */
  605.     asm("    file    basevals,b3");
  606. /* setup base register b2 (stack pointer); it should be
  607.    aligned on a 8-word boundary; but because it is pointing
  608.    to argc, its value should be remembered (in r5). */
  609.     asm("    movw    b2,r4");
  610.     asm("    movw    b2,r5");
  611.     asm("    andw    #~0x1f,r4");
  612.     asm("    movw    r4,b2");
  613. /* allocate stack frame to do some work. */
  614.     asm("    subea    16w,b2");
  615. /* initialize signal catching for UTX/32 1.2; this is 
  616.    necessary to make restart from saved image work. */
  617.     asm("    movea    sigcatch,r1");
  618.     asm("    movw    r1,8w[b2]");
  619.     asm("    svc    #1,#150");
  620. /* setup address of argc for start1. */
  621.     asm("    movw    r5,8w[b2]");
  622.     asm("   func    #1,_start1");
  623.     asm("    halt");
  624. /* space for ld to store base register initial values. */
  625.     asm("    .align    5");
  626.     asm("basevals:");
  627.     asm("    .word    __base3,__base4,__base5,__base6,__base7");
  628.  
  629. static
  630. start1 (xargc)
  631.      int *xargc;
  632. {
  633.   register int    argc;
  634.   register char **argv;
  635.  
  636.   argc = *xargc;
  637.   argv = (char **)(xargc) + 1;
  638.   environ = argv + argc + 1;
  639.  
  640.   if (environ == argv)
  641.     environ--;
  642.  
  643.   __do_global_init ();
  644.   exit (main (argc, argv, environ));
  645. }
  646.  
  647. #endif /* GOULD */
  648.  
  649. #ifdef elxsi
  650. extern int errno;
  651. extern char **environ;
  652.  
  653. _start()
  654. {
  655.   errno = 0;
  656.   environ = *(&environ + 8);
  657.   _stdinit();
  658.  
  659.   __do_global_init ();
  660.   exit (main(*(&environ + 6), *(&environ + 7), environ));
  661. }
  662. #endif /* elxsi */
  663.  
  664. #ifdef sparc
  665. asm (".global start");
  666. asm (".text");
  667. asm ("start:");
  668.  
  669. /* Set up `argc', `argv', and `envp' into local registers.  */
  670. asm ("    mov    0, %fp");
  671. asm ("    ld    [%sp + 64], %l0");
  672. asm ("    add    %sp, 68, %l1");
  673. asm ("    sll    %l0, 2,    %l2");
  674. asm ("    add    %l2, 4,    %l2");
  675. asm ("    add    %l1, %l2, %l2");
  676. asm ("    sethi    %hi(_environ), %l3");
  677. asm ("    st    %l2, [%l3+%lo(_environ)]");
  678.  
  679. #ifdef ON_EXIT
  680.  
  681. #ifdef sun
  682. asm ("    set __cleanup,%o0");
  683. asm ("    call _on_exit,0");
  684. asm ("    mov %g0,%o1");
  685. #endif
  686.  
  687. asm ("    set ___do_global_cleanup,%o0");
  688. asm ("    call _on_exit,0");
  689. asm ("    mov %g0,%o1");
  690.  
  691. #endif
  692.  
  693. /* Finish diddling with stack and call `__do_global_init'.  */
  694. asm ("    andn    %sp, 7,    %sp");
  695. asm ("    sub    %sp, 24, %sp");
  696. asm ("    call    ___do_global_init");
  697.  
  698. /* Move `argc', `argv', and `envp' from locals to parameters for `main'.  */
  699. asm ("    mov    %l0,%o0");
  700. asm ("    mov    %l1,%o1");
  701. asm ("    call    _main");
  702. asm ("    mov    %l2,%o2");
  703.  
  704. #ifndef ON_EXIT
  705. /* Save return value from `main', and call `__do_global_cleanup',
  706.    if necessary.  In any event, get return value from `main' into
  707.    a safe register.  */
  708. asm ("    call    ___do_global_cleanup");
  709. #endif
  710. asm ("    mov    %o0,%l0");
  711.  
  712. #ifdef ON_EXIT
  713. /* Call `exit' or `_exit' with return value from `main'.  */
  714. asm ("    call    _exit");
  715. #else
  716. asm ("    call    __exit");
  717. #endif
  718. asm ("    mov    %l0,%o0");
  719. #endif /* sparc */
  720.  
  721. #ifndef sun
  722. /* For C++, calls to exit(3) must perform their cleanup duties.
  723.    This means calling destructors on all of the items which
  724.    need to have their destructors called.  After calling these
  725.    destructors, a call is made to _exit (2), which is serious
  726.    business.  */
  727. void
  728. exit (status)
  729.      int status;
  730. {
  731.   __do_global_cleanup ();
  732. #if defined(hp9000s300) || defined(i386) || defined(ALTOS) || defined(vax) || defined(hp300)
  733.   _cleanup ();
  734. #endif
  735.   _exit (status);
  736. }
  737. #endif
  738.  
  739. #if 0
  740.  
  741. static int _end_crt0 ();
  742.  
  743. void
  744. __do_global_init ()
  745. {
  746.   extern void (*__CTOR_LIST__)();
  747.   register void (**ppf)() = &__CTOR_LIST__;
  748.   register int *pi = (int *)ppf;
  749.  
  750. #ifdef VIRTUAL_FUNCTION_MASK
  751.   if ((int)_end_crt0 < VINDEX_MAX)
  752.     {
  753.       printf ("virtual function index too large--encroaches text space at address 0x%x\n", _end_crt0);
  754.       abort ();
  755.     }
  756. #else
  757.   /* @@What to do for losing segmented architectures?  */
  758. #endif
  759.  
  760.   while (*pi++)
  761.     {
  762.       /* Losing PCC cannot handle this statement as (*ppf++)().  Pity.  */
  763.       (*ppf)();
  764.       ppf++;
  765.     }
  766. }
  767.  
  768. typedef struct dtor_table_entry
  769. {
  770.   struct dtor_table_entry *next;
  771.   void (*fp)();
  772. } dtor_table_entry;
  773.  
  774. extern dtor_table_entry *__DTOR_LIST__;
  775.  
  776. void
  777. __do_global_cleanup ()
  778. {
  779.   register int i;
  780.  
  781.   while (__DTOR_LIST__)
  782.     {
  783.       /* Prevent problems if a destructor should mistakenly call
  784.      exit() by always consuming one entry per round.  */
  785.       void (*fp)() = __DTOR_LIST__->fp;
  786.       __DTOR_LIST__ = __DTOR_LIST__->next;
  787.       (*fp)();
  788.     }
  789. }
  790.  
  791. static int
  792. _end_crt0 ()
  793. {
  794. }
  795. #else
  796. void
  797. __do_global_init () {}
  798.  
  799. void
  800. __do_global_cleanup () {}
  801. #endif
  802.