Home | History | Annotate | Line # | Download | only in libdos
      1 #! /usr/bin/awk -f
      2 #
      3 #	create DOS call interface from dos.h
      4 #
      5 #	written by ITOH Yasufumi
      6 #	public domain
      7 #
      8 #	$NetBSD: makedoscalls.awk,v 1.4 2011/02/21 02:31:59 itohy Exp $
      9 
     10 BEGIN {
     11 	errno_nomem = 8		# errno for "Cannot allocate memory"
     12 	argsiz["l"] = 4; argsiz["w"] = 2
     13 	argsiz["lb31"] = 4; argsiz["wb8"] = 2; argsiz["wb15"] = 2
     14 	print "#include \"dos_asm.h\""
     15 }
     16 
     17 $1 == "/*" && $2 ~ /^ff[0-9a-f][0-9a-f]$/ {
     18 	funcnam=""
     19 	dosno=$2
     20 	ptrval=0
     21 	narg=0
     22 	ncarg=0		# number of 32bit C function argument
     23 	argbyte=0
     24 	opt_e=0
     25 	e_strict=0
     26 	e_alloc=0
     27 	e_proc=0
     28 	svreg=0
     29 	noret=0
     30 	super=0
     31 	super_jsr=0
     32 	alias=""
     33 	for (i = 3; i <= NF && $i != "*/" && $i != ";"; i++) {
     34 		arg[narg] = $i
     35 		narg++
     36 		if (argsiz[$i])
     37 			ncarg++
     38 	}
     39 	if ($i == ";") {
     40 		# process opts
     41 		for (i++; i <= NF && $i != "*/"; i++) {
     42 			if ($i == "e")
     43 				opt_e = 1
     44 			else if ($i == "estrct") {
     45 				opt_e = 1
     46 				e_strict = 1
     47 			} else if ($i == "ep") {
     48 				opt_e = 1
     49 				e_proc = 1
     50 			} else if ($i == "ealloc") {
     51 				opt_e = 1
     52 				e_alloc = 1
     53 			} else if ($i == "sv")
     54 				svreg = 1
     55 			else if ($i == "noret")
     56 				noret = 1
     57 			else if ($i == "alias") {
     58 				i++
     59 				alias = $i
     60 			} else if ($i == "super")
     61 				super = 1
     62 			else if ($i == "super_jsr")
     63 				super_jsr = 1
     64 			else {
     65 				print FILENAME ":" NR ": unknown opt", $i
     66 				exit(1)
     67 			}
     68 		}
     69 	}
     70 	if ($i != "*/") {
     71 		print FILENAME ":" NR ": malformed input line:" $0
     72 		exit(1)
     73 	}
     74 	# find out func name
     75 	printf "|"
     76 	for (i++; i <= NF; i++) {
     77 		printf " %s", $i
     78 		if ($i ~ /^\**DOS_[A-Z0-9_]*$/) {
     79 			funcnam = $i
     80 			while (funcnam ~ /^\*/) {
     81 				funcnam = substr(funcnam, 2, length(funcnam) -1)
     82 				ptrval = 1
     83 			}
     84 		}
     85 	}
     86 	print ""
     87 	if (!funcnam) {
     88 		print FILENAME ":" NR ": can't find function name"
     89 		exit(1)
     90 	}
     91 
     92 	# output assembly code
     93 	print "ENTRY_NOPROFILE(" funcnam ")"
     94 	if (alias) {
     95 		print "GLOBAL(" alias ")"
     96 	}
     97 	if (svreg)	print "\tmoveml\t%d2-%d7/%a2-%a6,%sp@-"
     98 
     99 	# PUSH ARGS
    100 	argoff = ncarg * 4
    101 	if (svreg)
    102 		argoff += 4 * 11
    103 	for (i = narg - 1; i >= 0; i--) {
    104 		a = arg[i]
    105 		asz = argsiz[a]
    106 		if (asz) {
    107 			if (a == "l") {
    108 				# optimize with movem
    109 				if (arg[i-1] == "l" && arg[i-2] == "l") {
    110 					if (arg[i-3] == "l") {
    111 						print "\tmoveml\t%sp@(" argoff - 12 "),%d0-%d1/%a0-%a1"
    112 						print "\tmoveml\t%d0-%d1/%a0-%a1,%sp@-"
    113 						asz = 16
    114 						i -= 3
    115 					} else if (arg[i-3] == "w") {
    116 						print "\tmoveml\t%sp@(" argoff - 12 "),%d0-%d1/%a0-%a1"
    117 						print "\tmoveml\t%d1/%a0-%a1,%sp@-"
    118 						print "\tmovew\t%d0,%sp@-"
    119 						asz = 14
    120 						i -= 3
    121 					} else {
    122 						print "\tmoveml\t%sp@(" argoff - 8 "),%d0-%d1/%a0"
    123 						print "\tmoveml\t%d0-%d1/%a0,%sp@-"
    124 						asz = 12
    125 						i -= 2
    126 					}
    127 				} else {
    128 					print "\tmovel\t%sp@(" argoff "),%sp@-"
    129 				}
    130 			} else if (a == "w")
    131 				print "\tmovew\t%sp@(" argoff + 2 "),%sp@-"
    132 			else if (a == "lb31") {
    133 				print "\tmovel\t%sp@(" argoff "),%d0"
    134 				print "\tbset\t#31,%d0"
    135 				print "\tmovel\t%d0,%sp@-"
    136 			} else if (a == "wb8") {
    137 				print "\tmovew\t%sp@(" argoff + 2 "),%d0"
    138 				print "\torw\t#0x100,%d0"
    139 				print "\tmovew\t%d0,%sp@-"
    140 			} else if (a == "wb15") {
    141 				print "\tmovew\t%sp@(" argoff + 2 "),%d0"
    142 				print "\torw\t#0x8000,%d0"
    143 				print "\tmovew\t%d0,%sp@-"
    144 			} else {
    145 				print "??? unknown type"
    146 				exit(1)
    147 			}
    148 
    149 			if (asz == 2)
    150 				argoff -= 2
    151 		} else if (a ~ /^[0-9][0-9]*\.w$/) {
    152 			asz = 2
    153 			argoff += 2
    154 			val = substr(a, 1, length(a) - 2)
    155 			if (val == 0)
    156 				print "\tclrw\t%sp@-"
    157 			else
    158 				print "\tmovew\t#" val ",%sp@-"
    159 		} else if (a ~ /^[0-9][0-9]*\.l$/) {
    160 			asz = 4;
    161 			argoff += 4
    162 			val = substr(a, 1, length(a) - 2)
    163 			if (val == 0)
    164 				print "\tclrl\t%sp@-"
    165 			else if (val <= 32767)
    166 				print "\tpea\t" val ":w"
    167 			else
    168 				print "\tmovel\t#" val ",%sp@-"
    169 		} else if (a == "drvctrl" && narg == 1) {
    170 			# only for DOS_DRVCTRL
    171 			asz = 2
    172 			print "\tmoveb\t%sp@(7),%d0"
    173 			print "\tlslw\t#8,%d0"
    174 			print "\tmoveb\t%sp@(11),%d0"
    175 			print "\tmovew\t%d0,%sp@-"
    176 		} else if (a == "super" && narg == 1) {
    177 			# only for DOS_SUPER
    178 			print "\tmoveal\t%sp@+,%a1"
    179 		} else {
    180 			print FILENAME ":" NR ": unknown arg type:", a
    181 			exit(1)
    182 		}
    183 		argbyte += asz
    184 	}
    185 
    186 	if (super_jsr) {
    187 		print "\tmoveal\t%sp@(" argoff + 8 "),%a0	| inregs"
    188 		print "\tmoveml\t%a0@,%d0-%d7/%a0-%a6"
    189 	}
    190 
    191 	if (dosno ~ /^ff[8a]./) {
    192 		if (dosno ~ /^..8./)
    193 			v2dosno = "ff5" substr(dosno, 4, 1)
    194 		else
    195 			v2dosno = "ff7" substr(dosno, 4, 1)
    196 		print "\tcmpiw	#0x200+14,_C_LABEL(_vernum)+2	| 2.14"
    197 #		print "\tbcss\tLv2doscall"
    198 		print "\tbcss\t2f"
    199 		print "\t.word\t0x" dosno
    200 		if (!noret)
    201 #			print "\tbras\tLedoscall"
    202 			print "\tbras\t3f"
    203 #		print "Lv2doscall:"
    204 		print "2:"
    205 		print "\t.word\t0x" v2dosno
    206 		if (!noret)
    207 #			print "Ledoscall:"
    208 			print "3:"
    209 	} else {
    210 		print "\t.word\t0x" dosno
    211 	}
    212 
    213 	# no postprocess needed for dead calls
    214 	if (noret)
    215 		next
    216 
    217 	if (super_jsr) {
    218 		print "\tmovel\t%a6,%sp@"
    219 		print "\tmoveal\t%sp@(" argoff + 12 "),%a6	| outregs"
    220 		print "\tmovel\t%sp@+,%a6@(" 4 * 14 ")"
    221 		print "\tmoveml\t%d0-%d7/%a0-%a5,%a6@"
    222 	} else if (argbyte > 0) {
    223 		# POP ARGS
    224 		if (argbyte <= 8)
    225 			print "\taddql\t#" argbyte ",%sp"
    226 		else
    227 			print "\tlea\t%sp@(" argbyte "),%sp"
    228 	}
    229 
    230 	if (svreg)	print "\tmoveml\t%sp@+,%d2-%d7/%a2-%a6"
    231 	if (ptrval)	print "#ifdef __SVR4_ABI__\n\tmoveal\t%d0,%a0\n#endif"
    232 	if (opt_e) {
    233 		if (e_strict) {
    234 			print "\tcmpil\t#0xffffff00,%d0"
    235 			print "\tbcc\tCERROR"
    236 		} else  {
    237 			print "\ttstl\t%d0"
    238 			if (super) {
    239 #				print "\tbpls\tLnoerr"
    240 				print "\tbpls\t5f"
    241 				print "\tnegl\t%d0"
    242 				print "\tmovel\t%d0,_C_LABEL(dos_errno)"
    243 				print "\tnegl\t%d0"
    244 #				print "Lnoerr:"
    245 				print "5:"
    246 			} else if (e_alloc) {
    247 #				print "\tbpls\tLnoerr"
    248 				print "\tbpls\t5f"
    249 				print "\tmovel\t#" errno_nomem ",_C_LABEL(dos_errno)"
    250 #				print "Lnoerr:"
    251 				print "5:"
    252 			} else if (e_proc) {
    253 				print "\tbmi\tPRCERROR"
    254 			} else
    255 				print "\tbmi\tCERROR"
    256 		}
    257 	}
    258 	if (super)
    259 		print "\tjmp\t%a1@"
    260 	else
    261 		print "\trts"
    262 }
    263