Home | History | Annotate | Line # | Download | only in common
      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 ITOH Yasufumi
      9 |
     10 |	This file is in the public domain
     11 |
     12 |	$NetBSD: start.S,v 1.4 2024/01/07 07:58:34 isaki 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