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