xref: /netbsd/sys/arch/x68k/stand/common/start.S (revision bf9ec67e)
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__
126ASENTRY_NOPROFILE(_start)
127#else
128ASENTRY_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
149chkhupair:
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)
157ishupair:				| 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
166acou1:	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
173acous:	addql	#4,%d1			| for argv area
174	bras	acou1
175
176acou2:
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
182acouhp:	addql	#1,%d2
183	tstb	%a6@+
184	bnes	acouhp
185	addl	%d2,%d1
186anohp:
187#endif
188					| d1: estimated argument bytes
189
190#if NEED_ENVIRON
191	addql	#4,%a3			| skip length field
192	moveal	%a3,%a6
193ecou1:	addql	#4,%d1
194	tstb	%a6@+
195	beqs	ecoue
196ecou2:	tstb	%a6@+
197	bnes	ecou2
198	bras	ecou1
199ecoue:
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
220setblock_err:
221	movew	#stderr,%a7@
222	bsrs	sberr1			| pea %pc@
223	.asciz	"setblock failed\r\n"
224	.even
225sberr1:	DOS(__FPUTS)
226	movew	#exit_nomem,%a7@
227	DOS(__EXIT2)			| _exit(exit_nomem)
228
229sbnoerr:
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|
242loop_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
295arg0path:
296	moveb	%a4@+,%a1@+
297	bnes	arg0path
298	subql	#1,%a1			| remove nul char
299#endif
300	lea	%a5@(command_pdb),%a4	| command name
301arg0lp:	moveb	%a4@+,%a1@+
302	bnes	arg0lp
303
304#if NEED_PROGNAME
305|
306|	find program basename
307|
308	moveal	%a1,%a4
309prognlp:
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
317prognfou:
318	addql	#1,%a4			| next of slash
319prognexit:
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
333spskip:	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
344arglp:	tstb	%d1
345	bnes	in_quote
346	cmpib	#char_dquote,%d2
347	beqs	quote
348	cmpib	#char_squote,%d2
349	bnes	notquote
350quote:	moveb	%d2,%d1			| save quote character
351	bras	argnextc
352
353in_quote:
354	cmpb	%d1,%d2
355	bnes	argcopyc
356	clrb	%d1			| quote ended
357	bras	argnextc
358
359notquote:
360	cmpb	%d4,%d2			| space
361	beqs	arg_end
362	cmpb	%d3,%d2			| tab (if not hupair)
363	bnes	argcopyc
364arg_end:
365	clrb	%a1@+
366	bras	spskip
367
368argcopyc:
369	moveb	%d2,%a1@+		| copy char
370
371argnextc:
372	moveb	%a2@+,%d2
373	bnes	arglp
374	clrb	%a1@+
375
376comline_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
387mkargv:
388	movel	%a0,%a1@+		| argv[0] ...
389nxtarg:	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
405envlp:	tstb	%a3@
406	beqs	envend
407	movel	%a3,%a1@+
408envskp:	tstb	%a3@+
409	bnes	envskp
410	bras	envlp
411envend:	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
458ENTRY_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
493STACK_SYMBOL:
494	.space	STACK_SIZE
495#else
496	.comm	STACK_SYMBOL,STACK_SIZE
497#endif
498