Sync usage with man page.
[netbsd-mini2440.git] / sys / arch / x68k / stand / common / start.S
blob235419d8ba3859a7b304f438a2cf959e5bd7cffb
1 |-----------------------------------------------------------
3 |       Simple C runtime startup for Human68k
5 |         o no stdio support (DOS/IOCS only)
6 |         o HUPAIR support
8 |       written by Yasha (ITOH Yasufumi)
10 |       This file is in the public domain
12 |       $NetBSD: start.S,v 1.1 1998/09/01 19:51:56 itohy Exp $
14 #include <machine/asm.h>
16 |-----------------------------------------------------------
18 |       configuration
20 #ifndef STACK_SIZE
21 #define STACK_SIZE      65536   /* stack size in bytes */
22 #endif
24 #ifndef STACK_SYMBOL
25 #ifdef  __ELF__
26 #define STACK_SYMBOL    _stack  /* stack top symbol name */
27 #else   /* a.out */
28 #define STACK_SYMBOL    stack_8K_hUMAn6 /* has largest hash val on NetBSD ld */
29 #endif                                  /* and will be at the end of bss */
30 #endif
32 #ifndef DUMMY___main
33 #define DUMMY___main    1       /* define dummy __main() for a.out */
34 #endif
36 #ifndef SUPPORT_R_EXEC          /* support  ".r"  relocatable executable */
37 #define SUPPORT_R_EXEC  0       /* (clear bss, don't use a1 at startup) */
38 #endif                          /* XXX impossible for a.out */
40 #ifndef SUPPORT_HUPAIR
41 #define SUPPORT_HUPAIR  1       /* HUPAIR argument interface support */
42 #endif
44 #ifndef HUPAIR_ARGV0
45 #define HUPAIR_ARGV0    1       /* use argv[0] passed in HUPAIR manner */
46 #endif
48 #ifndef ADD_PATHNAME
49 #define ADD_PATHNAME    0       /* add command path to argv[0] if not HUPAIR */
50 #endif
52 #ifndef STRICT_SETBLOCK
53 #define STRICT_SETBLOCK 1       /* free unused memory after creating args */
54 #endif
56 #ifndef C_REGPARM
57 #define C_REGPARM       0       /* main() arguments are passed in registers */
58 #endif                          /* (for  gcc -mregparm) */
60 #ifndef NEED_MEMCP
61 #define NEED_MEMCP      0       /* __memcp: MCB address */
62 #endif
63 #ifndef NEED_PROCP
64 #define NEED_PROCP      0       /* __procp: PDB address */
65 #endif
66 #ifndef NEED_VERNUM
67 #define NEED_VERNUM     1       /* __vernum: Human68k version */
68 #endif
69 #ifndef NEED_PROGNAME
70 #define NEED_PROGNAME   1       /* ___progname: program basename */
71 #endif
72 #ifndef NEED_ENVIRON
73 #define NEED_ENVIRON    1       /* _environ: environment vector */
74 #endif
76 |-----------------------------------------------------------
78 |       DOS call
80 #define DOS(x)          .word x
82 #define __FPUTS         0xFF1E
83 #define __VERNUM        0xFF30
84 #define __SETBLOCK      0xFF4A
85 #define __EXIT2         0xFF4C
87 |       
88 |       seed to estimate argument string/vector and environment vector size
89 |       (max nohupair argv[0](92+4) + NULLs(8) + alignment(3))  <- donburi?
90 |       
91 #define estimated_argsz 107
92 #define estimated_com   92      /* estimated command name length (included) */
95 |       other constants
97 #define char_tab        0x09
98 #define char_space      0x20
99 #define char_dquote     0x22
100 #define char_squote     0x27
101 #define char_slash      0x2f
102 #define char_backslash  0x5c
104 #define pdb_mcb         0x10    /* PDB address - MCB address */
105 #define drvpath_pdb     0x070   /* drive and path address - PDB address */
106 #define command_pdb     0x0b4   /* command name address - PDB address */
107 #define top_pdb         0xf0    /* program load address - PDB address */
109 #define stderr          2       /* stderr  file handle */
110 #define exit_nomem      127     /* exit status on SETBLOCK failure */
112 |-----------------------------------------------------------
114 |       execution start
116 |       a0: MCB address, a1: program end + 1,
117 |       a2: command line, a3: environ, a4: execution start
119         |.cpu   68000
120         .text
121         .even
123         .globl  _C_LABEL(main)
125 #ifdef  __ELF__
126 ASENTRY_NOPROFILE(_start)
127 #else
128 ASENTRY_NOPROFILE(start)
129 #endif
130 #if SUPPORT_HUPAIR
131         .word   0x611e,0x2348,0x5550,0x4149,0x5200
132 #else
133         .word   0x6016
134 #endif
135 #if SUPPORT_R_EXEC
136         .word   0x7263
137 #else
138         .word   0x7863
139 #endif
140         .long   0x72743020,0x56312E31,0x42206279,0x20596173,0x68610000
143 |       check if hupair
145 #if SUPPORT_HUPAIR
146         moveal  %a7@+,%a4
147         lea     %a2@(-8),%a6
148         moveql  #7,%d3
149 chkhupair:
150         cmpmb   %a6@+,%a4@+
151         dbne    %d3,chkhupair
152                                 | d3.l: 0xFFFF: hupair, 0x000x: not hupair
153         addqw   #1,%d3
154         beqs    ishupair
155 #endif
156         moveql  #char_tab,%d3           | tab (= 9)
157 ishupair:                               | d3.l: 0: hupair, 9: not hupair
160 |       (over)estimate and allocate argument/environ area beforehand
162         addql   #1,%a2                  | skip byte count
163         moveql  #estimated_argsz,%d1    | byte counter
164         moveal  %a2,%a6
165         moveql  #char_space,%d4         | space
166 acou1:  addql   #1,%d1
167         moveb   %a6@+,%d0
168         beqs    acou2
169         cmpb    %d4,%d0                 | space
170         beqs    acous
171         cmpb    %d3,%d0                 | tab (if not hupair)
172         bnes    acou1
173 acous:  addql   #4,%d1                  | for argv area
174         bras    acou1
176 acou2:
177 #if SUPPORT_HUPAIR && HUPAIR_ARGV0
178         tstb    %d3
179         bnes    anohp
180         moveql  #-estimated_com,%d2     | reset argv[0] length
181         moveal  %a6,%a4                 | preserve argv[0] string address
182 acouhp: addql   #1,%d2
183         tstb    %a6@+
184         bnes    acouhp
185         addl    %d2,%d1
186 anohp:
187 #endif
188                                         | d1: estimated argument bytes
190 #if NEED_ENVIRON
191         addql   #4,%a3                  | skip length field
192         moveal  %a3,%a6
193 ecou1:  addql   #4,%d1
194         tstb    %a6@+
195         beqs    ecoue
196 ecou2:  tstb    %a6@+
197         bnes    ecou2
198         bras    ecou1
199 ecoue:
200 #endif
201                                         | d1: estimated byte count
204 |       free memory
205 |       and ensure the bss/stack (for .r executable) and argument areas valid
207         lea     %a0@(pdb_mcb),%a5       | a5: PDB address
208         subl    %a5,%d1
209 #if SUPPORT_R_EXEC
210 #define RELOC(sym, reg)         lea sym+top_pdb,reg; addl %a5,reg
211         moveal  %a1,%a6                 | end of data
212         RELOC(_end, %a1)                | end of bss
213 #endif
214         pea     %a1@(0,%d1:l)           | _end + size - pdb
215         movel   %a5,%a7@-
216         DOS(__SETBLOCK)
217         tstl    %d0
218         bpls    sbnoerr
220 setblock_err:
221         movew   #stderr,%a7@
222         bsrs    sberr1                  | pea %pc@
223         .asciz  "setblock failed\r\n"
224         .even
225 sberr1: DOS(__FPUTS)
226         movew   #exit_nomem,%a7@
227         DOS(__EXIT2)                    | _exit(exit_nomem)
229 sbnoerr:
231 |       here, the bss, stack, and argument/environ areas are certainly valid
234 |       set stack
236         moveal  #STACK_SYMBOL+STACK_SIZE,%a7
238 #if SUPPORT_R_EXEC
240 |       clear bss section
242 loop_clrbss:
243         clrl    %a6@+
244         cmpal   %a1,%a6
245         bcss    loop_clrbss
246 #endif
249 |       save MCB address
251 #if NEED_MEMCP
252 # if SUPPORT_R_EXEC
253         RELOC(_C_LABEL(_memcp), %a6)
254         movel   %a0,%a6@
255 # else
256         movel   %a0,_C_LABEL(_memcp)
257 # endif
258 #endif
261 |       save PDB address
263 #if NEED_PROCP
264 # if SUPPORT_R_EXEC
265         RELOC(_C_LABEL(_procp), %a6)
266         movel   %a5,%a6@
267 # else
268         movel   %a5,_C_LABEL(_procp)
269 # endif
270 #endif
273 |       get version no of Human
275 #if NEED_VERNUM
276         DOS(__VERNUM)
277 # if SUPPORT_R_EXEC
278         RELOC(_C_LABEL(_vernum), %a6)
279         movel   %d0,%a6@
280 # else
281         movel   %d0,_C_LABEL(_vernum)
282 # endif
283 #endif
286 |       create argv[0]
288         moveal  %a1,%a0                 | top of argument strings
289 #if SUPPORT_HUPAIR && HUPAIR_ARGV0
290         tstb    %d3
291         beqs    arg0lp
292 #endif
293 #if ADD_PATHNAME
294         lea     %a5@(drvpath_pdb),%a4   | drive and path name
295 arg0path:
296         moveb   %a4@+,%a1@+
297         bnes    arg0path
298         subql   #1,%a1                  | remove nul char
299 #endif
300         lea     %a5@(command_pdb),%a4   | command name
301 arg0lp: moveb   %a4@+,%a1@+
302         bnes    arg0lp
304 #if NEED_PROGNAME
306 |       find program basename
308         moveal  %a1,%a4
309 prognlp:
310         cmpal   %a0,%a4
311         beqs    prognexit
312         moveb   %a4@-,%d0
313         cmpib   #char_slash,%d0
314         beqs    prognfou
315         cmpib   #char_backslash,%d0
316         bnes    prognlp
317 prognfou:
318         addql   #1,%a4                  | next of slash
319 prognexit:
320 # if SUPPORT_R_EXEC
321         RELOC(_C_LABEL(__progname), %a6)
322         movel   %a4,%a6@
323 # else
324         movel   %a4,_C_LABEL(__progname)
325 # endif
326 #endif
329 |       create argument strings
331         moveql  #1,%d0                  | (d0:l) # arg
333 spskip: moveb   %a2@+,%d2
334         beqs    comline_end
335         cmpb    %d4,%d2                 | space
336         beqs    spskip
337         cmpb    %d3,%d2                 | tab (if not hupair)
338         beqs    spskip
340         | create an arg
341         clrb    %d1                     | no quote here
342         addql   #1,%d0                  | increment argc
344 arglp:  tstb    %d1
345         bnes    in_quote
346         cmpib   #char_dquote,%d2
347         beqs    quote
348         cmpib   #char_squote,%d2
349         bnes    notquote
350 quote:  moveb   %d2,%d1                 | save quote character
351         bras    argnextc
353 in_quote:
354         cmpb    %d1,%d2
355         bnes    argcopyc
356         clrb    %d1                     | quote ended
357         bras    argnextc
359 notquote:
360         cmpb    %d4,%d2                 | space
361         beqs    arg_end
362         cmpb    %d3,%d2                 | tab (if not hupair)
363         bnes    argcopyc
364 arg_end:
365         clrb    %a1@+
366         bras    spskip
368 argcopyc:
369         moveb   %d2,%a1@+               | copy char
371 argnextc:
372         moveb   %a2@+,%d2
373         bnes    arglp
374         clrb    %a1@+
376 comline_end:
379 |       create argv vector
381         addql   #3,%a1
382         movel   %a1,%d1
383         andib   #0xfc,%d1               | long alignment
384         moveal  %d1,%a1                 | argv
385         movel   %d0,%d4                 | argc
386                                         | a0 is at argument strings
387 mkargv:
388         movel   %a0,%a1@+               | argv[0] ...
389 nxtarg: tstb    %a0@+
390         bnes    nxtarg
391 #if STRICT_SETBLOCK
392         subqw   #1,%d0
393 #else
394         subqw   #1,%d4
395 #endif
396         bnes    mkargv
398         clrl    %a1@+                   | argv[argc] should be NULL
401 |       create envp vector
403 #if NEED_ENVIRON
404         movel   %a1,%d2
405 envlp:  tstb    %a3@
406         beqs    envend
407         movel   %a3,%a1@+
408 envskp: tstb    %a3@+
409         bnes    envskp
410         bras    envlp
411 envend: clrl    %a1@+                   | NULL termination
412 # if SUPPORT_R_EXEC
413         RELOC(_C_LABEL(environ), %a0)
414         movel   %d2,%a0@
415 # else
416         movel   %d2,_C_LABEL(environ)
417 # endif
418 #endif
421 |       free unused memory
423 #if STRICT_SETBLOCK
424         subal   %a5,%a1
425         movel   %a1,%a7@-
426         movel   %a5,%a7@-
427         DOS(__SETBLOCK)                 | reset donburi-kanjo (never fails)
428         addql   #8,%a7
429         movel   %d4,%d0                 | argc
430 #endif
433 |       make parameter
435 #if NEED_ENVIRON
436         movel   %d2,%a7@-               | arg #3 --- envp
437 #endif
438 #if !C_REGPARM
439         movel   %d1,%a7@-               | arg #2 --- argv
440         movel   %d0,%a7@-               | arg #1 --- argc
441 #endif
443 #if SUPPORT_R_EXEC
444         RELOC(_C_LABEL(main), %a0)
445         jsr     %a0@
446 #else
447         jsr     _C_LABEL(main)
448 #endif
450 #if !C_REGPARM || NEED_ENVIRON
451         movew   %d0,%a7@
452 #else
453         movew   %d0,%a7@-
454 #endif
455         DOS(__EXIT2)
457 #if !defined(__ELF__) && DUMMY___main
458 ENTRY_NOPROFILE(__main)
459         rts
460 #endif
462 |-----------------------------------------------------------
464 |       variables
466 #if NEED_MEMCP
467         .comm   _C_LABEL(_memcp),4
468 #endif
470 #if NEED_PROCP
471         .comm   _C_LABEL(_procp),4              | PDB address
472 #endif
474 #if NEED_VERNUM
475         .comm   _C_LABEL(_vernum),4
476 #endif
478 #if NEED_PROGNAME
479         .comm   _C_LABEL(__progname),4
480 #endif
482 #if NEED_ENVIRON
483         .comm   _C_LABEL(environ),4             | environ address
484 #endif
486 |-----------------------------------------------------------
488 |       stack
490 #ifdef  __ELF__
491         .section        .stack,"aw",@nobits
492         .align  4
493 STACK_SYMBOL:
494         .space  STACK_SIZE
495 #else
496         .comm   STACK_SYMBOL,STACK_SIZE
497 #endif