start.S revision 1.2 1 |-----------------------------------------------------------
2 |
3 | Simple C runtime startup for Human68k
4 |
5 | o no stdio support (DOS/IOCS only)
6 | o HUPAIR support
7 |
8 | written by Yasha (ITOH Yasufumi)
9 |
10 | This file is in the public domain
11 |
12 | $NetBSD: start.S,v 1.2 1999/11/11 08:12:50 itohy Exp $
13
14 #include <machine/asm.h>
15
16 |-----------------------------------------------------------
17 |
18 | configuration
19 |
20 #ifndef STACK_SIZE
21 #define STACK_SIZE 65536 /* stack size in bytes */
22 #endif
23
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
31
32 #ifndef DUMMY___main
33 #define DUMMY___main 1 /* define dummy __main() for a.out */
34 #endif
35
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 */
39
40 #ifndef SUPPORT_HUPAIR
41 #define SUPPORT_HUPAIR 1 /* HUPAIR argument interface support */
42 #endif
43
44 #ifndef HUPAIR_ARGV0
45 #define HUPAIR_ARGV0 1 /* use argv[0] passed in HUPAIR manner */
46 #endif
47
48 #ifndef ADD_PATHNAME
49 #define ADD_PATHNAME 0 /* add command path to argv[0] if not HUPAIR */
50 #endif
51
52 #ifndef STRICT_SETBLOCK
53 #define STRICT_SETBLOCK 1 /* free unused memory after creating args */
54 #endif
55
56 #ifndef C_REGPARM
57 #define C_REGPARM 0 /* main() arguments are passed in registers */
58 #endif /* (for gcc -mregparm) */
59
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
75
76 |-----------------------------------------------------------
77 |
78 | DOS call
79 |
80 #define DOS(x) .word x
81
82 #define __FPUTS 0xFF1E
83 #define __VERNUM 0xFF30
84 #define __SETBLOCK 0xFF4A
85 #define __EXIT2 0xFF4C
86
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) */
93
94 |
95 | other constants
96 |
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
103
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 */
108
109 #define stderr 2 /* stderr file handle */
110 #define exit_nomem 127 /* exit status on SETBLOCK failure */
111
112 |-----------------------------------------------------------
113 |
114 | execution start
115 |
116 | a0: MCB address, a1: program end + 1,
117 | a2: command line, a3: environ, a4: execution start
118 |
119 |.cpu 68000
120 .text
121 .even
122
123 .globl _C_LABEL(main)
124
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
141
142 |
143 | check if hupair
144 |
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
158
159 |
160 | (over)estimate and allocate argument/environ area beforehand
161 |
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
175
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
189
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
202
203 |
204 | free memory
205 | and ensure the bss/stack (for .r executable) and argument areas valid
206 |
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
219
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)
228
229 sbnoerr:
230
231 | here, the bss, stack, and argument/environ areas are certainly valid
232
233 |
234 | set stack
235 |
236 moveal #STACK_SYMBOL+STACK_SIZE,%a7
237
238 #if SUPPORT_R_EXEC
239 |
240 | clear bss section
241 |
242 loop_clrbss:
243 clrl %a6@+
244 cmpal %a1,%a6
245 bcss loop_clrbss
246 #endif
247
248 |
249 | save MCB address
250 |
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
259
260 |
261 | save PDB address
262 |
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
271
272 |
273 | get version no of Human
274 |
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
284
285 |
286 | create argv[0]
287 |
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
303
304 #if NEED_PROGNAME
305 |
306 | find program basename
307 |
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
327
328 |
329 | create argument strings
330 |
331 moveql #1,%d0 | (d0:l) # arg
332
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
339
340 | create an arg
341 clrb %d1 | no quote here
342 addql #1,%d0 | increment argc
343
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
352
353 in_quote:
354 cmpb %d1,%d2
355 bnes argcopyc
356 clrb %d1 | quote ended
357 bras argnextc
358
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
367
368 argcopyc:
369 moveb %d2,%a1@+ | copy char
370
371 argnextc:
372 moveb %a2@+,%d2
373 bnes arglp
374 clrb %a1@+
375
376 comline_end:
377
378 |
379 | create argv vector
380 |
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
397
398 clrl %a1@+ | argv[argc] should be NULL
399
400 |
401 | create envp vector
402 |
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
419
420 |
421 | free unused memory
422 |
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
431
432 |
433 | make parameter
434 |
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
442
443 #if SUPPORT_R_EXEC
444 RELOC(_C_LABEL(main), %a0)
445 jsr %a0@
446 #else
447 jsr _C_LABEL(main)
448 #endif
449
450 #if !C_REGPARM || NEED_ENVIRON
451 movew %d0,%a7@
452 #else
453 movew %d0,%a7@-
454 #endif
455 DOS(__EXIT2)
456
457 #if !defined(__ELF__) && DUMMY___main
458 ENTRY_NOPROFILE(__main)
459 rts
460 #endif
461
462 |-----------------------------------------------------------
463 |
464 | variables
465 |
466 #if NEED_MEMCP
467 .comm _C_LABEL(_memcp),4
468 #endif
469
470 #if NEED_PROCP
471 .comm _C_LABEL(_procp),4 | PDB address
472 #endif
473
474 #if NEED_VERNUM
475 .comm _C_LABEL(_vernum),4
476 #endif
477
478 #if NEED_PROGNAME
479 .comm _C_LABEL(__progname),4
480 #endif
481
482 #if NEED_ENVIRON
483 .comm _C_LABEL(environ),4 | environ address
484 #endif
485
486 |-----------------------------------------------------------
487 |
488 | stack
489 |
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
498