NetBSD/sys/arch/x68k/stand/common/start.S

498 lines
9.0 KiB
ArmAsm
Raw Normal View History

1998-09-01 23:51:56 +04:00
|-----------------------------------------------------------
|
| Simple C runtime startup for Human68k
|
| o no stdio support (DOS/IOCS only)
| o HUPAIR support
|
| written by Yasha (ITOH Yasufumi)
|
| This file is in the public domain
|
1999-11-11 11:12:50 +03:00
| $NetBSD: start.S,v 1.2 1999/11/11 08:12:50 itohy Exp $
#include <machine/asm.h>
1998-09-01 23:51:56 +04:00
|-----------------------------------------------------------
|
| configuration
|
#ifndef STACK_SIZE
#define STACK_SIZE 65536 /* stack size in bytes */
#endif
#ifndef STACK_SYMBOL
1999-11-11 11:12:50 +03:00
#ifdef __ELF__
#define STACK_SYMBOL _stack /* stack top symbol name */
#else /* a.out */
1998-09-01 23:51:56 +04:00
#define STACK_SYMBOL stack_8K_hUMAn6 /* has largest hash val on NetBSD ld */
#endif /* and will be at the end of bss */
1999-11-11 11:12:50 +03:00
#endif
1998-09-01 23:51:56 +04:00
#ifndef DUMMY___main
1999-11-11 11:12:50 +03:00
#define DUMMY___main 1 /* define dummy __main() for a.out */
1998-09-01 23:51:56 +04:00
#endif
#ifndef SUPPORT_R_EXEC /* support ".r" relocatable executable */
#define SUPPORT_R_EXEC 0 /* (clear bss, don't use a1 at startup) */
#endif /* XXX impossible for a.out */
#ifndef SUPPORT_HUPAIR
#define SUPPORT_HUPAIR 1 /* HUPAIR argument interface support */
#endif
#ifndef HUPAIR_ARGV0
#define HUPAIR_ARGV0 1 /* use argv[0] passed in HUPAIR manner */
#endif
#ifndef ADD_PATHNAME
#define ADD_PATHNAME 0 /* add command path to argv[0] if not HUPAIR */
#endif
#ifndef STRICT_SETBLOCK
#define STRICT_SETBLOCK 1 /* free unused memory after creating args */
#endif
#ifndef C_REGPARM
#define C_REGPARM 0 /* main() arguments are passed in registers */
#endif /* (for gcc -mregparm) */
#ifndef NEED_MEMCP
#define NEED_MEMCP 0 /* __memcp: MCB address */
#endif
#ifndef NEED_PROCP
#define NEED_PROCP 0 /* __procp: PDB address */
#endif
#ifndef NEED_VERNUM
#define NEED_VERNUM 1 /* __vernum: Human68k version */
#endif
#ifndef NEED_PROGNAME
#define NEED_PROGNAME 1 /* ___progname: program basename */
#endif
#ifndef NEED_ENVIRON
#define NEED_ENVIRON 1 /* _environ: environment vector */
#endif
|-----------------------------------------------------------
|
| DOS call
|
#define DOS(x) .word x
#define __FPUTS 0xFF1E
#define __VERNUM 0xFF30
#define __SETBLOCK 0xFF4A
#define __EXIT2 0xFF4C
|
| seed to estimate argument string/vector and environment vector size
| (max nohupair argv[0](92+4) + NULLs(8) + alignment(3)) <- donburi?
|
#define estimated_argsz 107
#define estimated_com 92 /* estimated command name length (included) */
|
| other constants
|
#define char_tab 0x09
#define char_space 0x20
#define char_dquote 0x22
#define char_squote 0x27
#define char_slash 0x2f
#define char_backslash 0x5c
#define pdb_mcb 0x10 /* PDB address - MCB address */
#define drvpath_pdb 0x070 /* drive and path address - PDB address */
#define command_pdb 0x0b4 /* command name address - PDB address */
#define top_pdb 0xf0 /* program load address - PDB address */
#define stderr 2 /* stderr file handle */
#define exit_nomem 127 /* exit status on SETBLOCK failure */
|-----------------------------------------------------------
|
| execution start
|
| a0: MCB address, a1: program end + 1,
| a2: command line, a3: environ, a4: execution start
|
|.cpu 68000
.text
.even
1999-11-11 11:12:50 +03:00
.globl _C_LABEL(main)
1998-09-01 23:51:56 +04:00
1999-11-11 11:12:50 +03:00
#ifdef __ELF__
ASENTRY_NOPROFILE(_start)
#else
ASENTRY_NOPROFILE(start)
#endif
1998-09-01 23:51:56 +04:00
#if SUPPORT_HUPAIR
.word 0x611e,0x2348,0x5550,0x4149,0x5200
#else
.word 0x6016
#endif
#if SUPPORT_R_EXEC
.word 0x7263
#else
.word 0x7863
#endif
.long 0x72743020,0x56312E31,0x42206279,0x20596173,0x68610000
|
| check if hupair
|
#if SUPPORT_HUPAIR
1999-11-11 11:12:50 +03:00
moveal %a7@+,%a4
lea %a2@(-8),%a6
moveql #7,%d3
1998-09-01 23:51:56 +04:00
chkhupair:
1999-11-11 11:12:50 +03:00
cmpmb %a6@+,%a4@+
dbne %d3,chkhupair
1998-09-01 23:51:56 +04:00
| d3.l: 0xFFFF: hupair, 0x000x: not hupair
1999-11-11 11:12:50 +03:00
addqw #1,%d3
1998-09-01 23:51:56 +04:00
beqs ishupair
#endif
1999-11-11 11:12:50 +03:00
moveql #char_tab,%d3 | tab (= 9)
1998-09-01 23:51:56 +04:00
ishupair: | d3.l: 0: hupair, 9: not hupair
|
| (over)estimate and allocate argument/environ area beforehand
|
1999-11-11 11:12:50 +03:00
addql #1,%a2 | skip byte count
moveql #estimated_argsz,%d1 | byte counter
moveal %a2,%a6
moveql #char_space,%d4 | space
acou1: addql #1,%d1
moveb %a6@+,%d0
1998-09-01 23:51:56 +04:00
beqs acou2
1999-11-11 11:12:50 +03:00
cmpb %d4,%d0 | space
1998-09-01 23:51:56 +04:00
beqs acous
1999-11-11 11:12:50 +03:00
cmpb %d3,%d0 | tab (if not hupair)
1998-09-01 23:51:56 +04:00
bnes acou1
1999-11-11 11:12:50 +03:00
acous: addql #4,%d1 | for argv area
1998-09-01 23:51:56 +04:00
bras acou1
acou2:
#if SUPPORT_HUPAIR && HUPAIR_ARGV0
1999-11-11 11:12:50 +03:00
tstb %d3
1998-09-01 23:51:56 +04:00
bnes anohp
1999-11-11 11:12:50 +03:00
moveql #-estimated_com,%d2 | reset argv[0] length
moveal %a6,%a4 | preserve argv[0] string address
acouhp: addql #1,%d2
tstb %a6@+
1998-09-01 23:51:56 +04:00
bnes acouhp
1999-11-11 11:12:50 +03:00
addl %d2,%d1
1998-09-01 23:51:56 +04:00
anohp:
#endif
| d1: estimated argument bytes
#if NEED_ENVIRON
1999-11-11 11:12:50 +03:00
addql #4,%a3 | skip length field
moveal %a3,%a6
ecou1: addql #4,%d1
tstb %a6@+
1998-09-01 23:51:56 +04:00
beqs ecoue
1999-11-11 11:12:50 +03:00
ecou2: tstb %a6@+
1998-09-01 23:51:56 +04:00
bnes ecou2
bras ecou1
ecoue:
#endif
| d1: estimated byte count
|
| free memory
| and ensure the bss/stack (for .r executable) and argument areas valid
|
1999-11-11 11:12:50 +03:00
lea %a0@(pdb_mcb),%a5 | a5: PDB address
subl %a5,%d1
1998-09-01 23:51:56 +04:00
#if SUPPORT_R_EXEC
1999-11-11 11:12:50 +03:00
#define RELOC(sym, reg) lea sym+top_pdb,reg; addl %a5,reg
moveal %a1,%a6 | end of data
RELOC(_end, %a1) | end of bss
1998-09-01 23:51:56 +04:00
#endif
1999-11-11 11:12:50 +03:00
pea %a1@(0,%d1:l) | _end + size - pdb
movel %a5,%a7@-
1998-09-01 23:51:56 +04:00
DOS(__SETBLOCK)
1999-11-11 11:12:50 +03:00
tstl %d0
1998-09-01 23:51:56 +04:00
bpls sbnoerr
setblock_err:
1999-11-11 11:12:50 +03:00
movew #stderr,%a7@
bsrs sberr1 | pea %pc@
1998-09-01 23:51:56 +04:00
.asciz "setblock failed\r\n"
.even
sberr1: DOS(__FPUTS)
1999-11-11 11:12:50 +03:00
movew #exit_nomem,%a7@
1998-09-01 23:51:56 +04:00
DOS(__EXIT2) | _exit(exit_nomem)
sbnoerr:
| here, the bss, stack, and argument/environ areas are certainly valid
|
| set stack
|
1999-11-11 11:12:50 +03:00
moveal #STACK_SYMBOL+STACK_SIZE,%a7
1998-09-01 23:51:56 +04:00
#if SUPPORT_R_EXEC
|
| clear bss section
|
loop_clrbss:
1999-11-11 11:12:50 +03:00
clrl %a6@+
cmpal %a1,%a6
1998-09-01 23:51:56 +04:00
bcss loop_clrbss
#endif
|
| save MCB address
|
#if NEED_MEMCP
# if SUPPORT_R_EXEC
1999-11-11 11:12:50 +03:00
RELOC(_C_LABEL(_memcp), %a6)
movel %a0,%a6@
1998-09-01 23:51:56 +04:00
# else
1999-11-11 11:12:50 +03:00
movel %a0,_C_LABEL(_memcp)
1998-09-01 23:51:56 +04:00
# endif
#endif
|
| save PDB address
|
#if NEED_PROCP
# if SUPPORT_R_EXEC
1999-11-11 11:12:50 +03:00
RELOC(_C_LABEL(_procp), %a6)
movel %a5,%a6@
1998-09-01 23:51:56 +04:00
# else
1999-11-11 11:12:50 +03:00
movel %a5,_C_LABEL(_procp)
1998-09-01 23:51:56 +04:00
# endif
#endif
|
| get version no of Human
|
#if NEED_VERNUM
DOS(__VERNUM)
# if SUPPORT_R_EXEC
1999-11-11 11:12:50 +03:00
RELOC(_C_LABEL(_vernum), %a6)
movel %d0,%a6@
1998-09-01 23:51:56 +04:00
# else
1999-11-11 11:12:50 +03:00
movel %d0,_C_LABEL(_vernum)
1998-09-01 23:51:56 +04:00
# endif
#endif
|
| create argv[0]
|
1999-11-11 11:12:50 +03:00
moveal %a1,%a0 | top of argument strings
1998-09-01 23:51:56 +04:00
#if SUPPORT_HUPAIR && HUPAIR_ARGV0
1999-11-11 11:12:50 +03:00
tstb %d3
1998-09-01 23:51:56 +04:00
beqs arg0lp
#endif
#if ADD_PATHNAME
1999-11-11 11:12:50 +03:00
lea %a5@(drvpath_pdb),%a4 | drive and path name
1998-09-01 23:51:56 +04:00
arg0path:
1999-11-11 11:12:50 +03:00
moveb %a4@+,%a1@+
1998-09-01 23:51:56 +04:00
bnes arg0path
1999-11-11 11:12:50 +03:00
subql #1,%a1 | remove nul char
1998-09-01 23:51:56 +04:00
#endif
1999-11-11 11:12:50 +03:00
lea %a5@(command_pdb),%a4 | command name
arg0lp: moveb %a4@+,%a1@+
1998-09-01 23:51:56 +04:00
bnes arg0lp
#if NEED_PROGNAME
|
| find program basename
|
1999-11-11 11:12:50 +03:00
moveal %a1,%a4
1998-09-01 23:51:56 +04:00
prognlp:
1999-11-11 11:12:50 +03:00
cmpal %a0,%a4
1998-09-01 23:51:56 +04:00
beqs prognexit
1999-11-11 11:12:50 +03:00
moveb %a4@-,%d0
cmpib #char_slash,%d0
1998-09-01 23:51:56 +04:00
beqs prognfou
1999-11-11 11:12:50 +03:00
cmpib #char_backslash,%d0
1998-09-01 23:51:56 +04:00
bnes prognlp
prognfou:
1999-11-11 11:12:50 +03:00
addql #1,%a4 | next of slash
1998-09-01 23:51:56 +04:00
prognexit:
# if SUPPORT_R_EXEC
1999-11-11 11:12:50 +03:00
RELOC(_C_LABEL(__progname), %a6)
movel %a4,%a6@
1998-09-01 23:51:56 +04:00
# else
1999-11-11 11:12:50 +03:00
movel %a4,_C_LABEL(__progname)
1998-09-01 23:51:56 +04:00
# endif
#endif
|
| create argument strings
|
1999-11-11 11:12:50 +03:00
moveql #1,%d0 | (d0:l) # arg
1998-09-01 23:51:56 +04:00
1999-11-11 11:12:50 +03:00
spskip: moveb %a2@+,%d2
1998-09-01 23:51:56 +04:00
beqs comline_end
1999-11-11 11:12:50 +03:00
cmpb %d4,%d2 | space
1998-09-01 23:51:56 +04:00
beqs spskip
1999-11-11 11:12:50 +03:00
cmpb %d3,%d2 | tab (if not hupair)
1998-09-01 23:51:56 +04:00
beqs spskip
| create an arg
1999-11-11 11:12:50 +03:00
clrb %d1 | no quote here
addql #1,%d0 | increment argc
1998-09-01 23:51:56 +04:00
1999-11-11 11:12:50 +03:00
arglp: tstb %d1
1998-09-01 23:51:56 +04:00
bnes in_quote
1999-11-11 11:12:50 +03:00
cmpib #char_dquote,%d2
1998-09-01 23:51:56 +04:00
beqs quote
1999-11-11 11:12:50 +03:00
cmpib #char_squote,%d2
1998-09-01 23:51:56 +04:00
bnes notquote
1999-11-11 11:12:50 +03:00
quote: moveb %d2,%d1 | save quote character
1998-09-01 23:51:56 +04:00
bras argnextc
in_quote:
1999-11-11 11:12:50 +03:00
cmpb %d1,%d2
1998-09-01 23:51:56 +04:00
bnes argcopyc
1999-11-11 11:12:50 +03:00
clrb %d1 | quote ended
1998-09-01 23:51:56 +04:00
bras argnextc
notquote:
1999-11-11 11:12:50 +03:00
cmpb %d4,%d2 | space
1998-09-01 23:51:56 +04:00
beqs arg_end
1999-11-11 11:12:50 +03:00
cmpb %d3,%d2 | tab (if not hupair)
1998-09-01 23:51:56 +04:00
bnes argcopyc
arg_end:
1999-11-11 11:12:50 +03:00
clrb %a1@+
1998-09-01 23:51:56 +04:00
bras spskip
argcopyc:
1999-11-11 11:12:50 +03:00
moveb %d2,%a1@+ | copy char
1998-09-01 23:51:56 +04:00
argnextc:
1999-11-11 11:12:50 +03:00
moveb %a2@+,%d2
1998-09-01 23:51:56 +04:00
bnes arglp
1999-11-11 11:12:50 +03:00
clrb %a1@+
1998-09-01 23:51:56 +04:00
comline_end:
|
| create argv vector
|
1999-11-11 11:12:50 +03:00
addql #3,%a1
movel %a1,%d1
andib #0xfc,%d1 | long alignment
moveal %d1,%a1 | argv
movel %d0,%d4 | argc
1998-09-01 23:51:56 +04:00
| a0 is at argument strings
mkargv:
1999-11-11 11:12:50 +03:00
movel %a0,%a1@+ | argv[0] ...
nxtarg: tstb %a0@+
1998-09-01 23:51:56 +04:00
bnes nxtarg
#if STRICT_SETBLOCK
1999-11-11 11:12:50 +03:00
subqw #1,%d0
1998-09-01 23:51:56 +04:00
#else
1999-11-11 11:12:50 +03:00
subqw #1,%d4
1998-09-01 23:51:56 +04:00
#endif
bnes mkargv
1999-11-11 11:12:50 +03:00
clrl %a1@+ | argv[argc] should be NULL
1998-09-01 23:51:56 +04:00
|
| create envp vector
|
#if NEED_ENVIRON
1999-11-11 11:12:50 +03:00
movel %a1,%d2
envlp: tstb %a3@
1998-09-01 23:51:56 +04:00
beqs envend
1999-11-11 11:12:50 +03:00
movel %a3,%a1@+
envskp: tstb %a3@+
1998-09-01 23:51:56 +04:00
bnes envskp
bras envlp
1999-11-11 11:12:50 +03:00
envend: clrl %a1@+ | NULL termination
1998-09-01 23:51:56 +04:00
# if SUPPORT_R_EXEC
1999-11-11 11:12:50 +03:00
RELOC(_C_LABEL(environ), %a0)
movel %d2,%a0@
1998-09-01 23:51:56 +04:00
# else
1999-11-11 11:12:50 +03:00
movel %d2,_C_LABEL(environ)
1998-09-01 23:51:56 +04:00
# endif
#endif
|
| free unused memory
|
#if STRICT_SETBLOCK
1999-11-11 11:12:50 +03:00
subal %a5,%a1
movel %a1,%a7@-
movel %a5,%a7@-
1998-09-01 23:51:56 +04:00
DOS(__SETBLOCK) | reset donburi-kanjo (never fails)
1999-11-11 11:12:50 +03:00
addql #8,%a7
movel %d4,%d0 | argc
1998-09-01 23:51:56 +04:00
#endif
|
| make parameter
|
#if NEED_ENVIRON
1999-11-11 11:12:50 +03:00
movel %d2,%a7@- | arg #3 --- envp
1998-09-01 23:51:56 +04:00
#endif
#if !C_REGPARM
1999-11-11 11:12:50 +03:00
movel %d1,%a7@- | arg #2 --- argv
movel %d0,%a7@- | arg #1 --- argc
1998-09-01 23:51:56 +04:00
#endif
#if SUPPORT_R_EXEC
1999-11-11 11:12:50 +03:00
RELOC(_C_LABEL(main), %a0)
jsr %a0@
1998-09-01 23:51:56 +04:00
#else
1999-11-11 11:12:50 +03:00
jsr _C_LABEL(main)
1998-09-01 23:51:56 +04:00
#endif
#if !C_REGPARM || NEED_ENVIRON
1999-11-11 11:12:50 +03:00
movew %d0,%a7@
1998-09-01 23:51:56 +04:00
#else
1999-11-11 11:12:50 +03:00
movew %d0,%a7@-
1998-09-01 23:51:56 +04:00
#endif
DOS(__EXIT2)
1999-11-11 11:12:50 +03:00
#if !defined(__ELF__) && DUMMY___main
ENTRY_NOPROFILE(__main)
1998-09-01 23:51:56 +04:00
rts
#endif
|-----------------------------------------------------------
|
| variables
|
#if NEED_MEMCP
1999-11-11 11:12:50 +03:00
.comm _C_LABEL(_memcp),4
1998-09-01 23:51:56 +04:00
#endif
#if NEED_PROCP
1999-11-11 11:12:50 +03:00
.comm _C_LABEL(_procp),4 | PDB address
1998-09-01 23:51:56 +04:00
#endif
#if NEED_VERNUM
1999-11-11 11:12:50 +03:00
.comm _C_LABEL(_vernum),4
1998-09-01 23:51:56 +04:00
#endif
#if NEED_PROGNAME
1999-11-11 11:12:50 +03:00
.comm _C_LABEL(__progname),4
1998-09-01 23:51:56 +04:00
#endif
#if NEED_ENVIRON
1999-11-11 11:12:50 +03:00
.comm _C_LABEL(environ),4 | environ address
1998-09-01 23:51:56 +04:00
#endif
|-----------------------------------------------------------
|
| stack
|
1999-11-11 11:12:50 +03:00
#ifdef __ELF__
.section .stack,"aw",@nobits
.align 4
STACK_SYMBOL:
.space STACK_SIZE
#else
1998-09-01 23:51:56 +04:00
.comm STACK_SYMBOL,STACK_SIZE
1999-11-11 11:12:50 +03:00
#endif