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