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