Training courses

Kernel and Embedded Linux

Bootlin training courses

Embedded Linux, kernel,
Yocto Project, Buildroot, real-time,
graphics, boot time, debugging...

Bootlin logo

Elixir Cross Referencer

#! /usr/bin/awk -f
#
#	create DOS call interface from dos.h
#
#	written by ITOH Yasufumi
#	public domain
#
#	$NetBSD: makedoscalls.awk,v 1.4 2011/02/21 02:31:59 itohy Exp $

BEGIN {
	errno_nomem = 8		# errno for "Cannot allocate memory"
	argsiz["l"] = 4; argsiz["w"] = 2
	argsiz["lb31"] = 4; argsiz["wb8"] = 2; argsiz["wb15"] = 2
	print "#include \"dos_asm.h\""
}

$1 == "/*" && $2 ~ /^ff[0-9a-f][0-9a-f]$/ {
	funcnam=""
	dosno=$2
	ptrval=0
	narg=0
	ncarg=0		# number of 32bit C function argument
	argbyte=0
	opt_e=0
	e_strict=0
	e_alloc=0
	e_proc=0
	svreg=0
	noret=0
	super=0
	super_jsr=0
	alias=""
	for (i = 3; i <= NF && $i != "*/" && $i != ";"; i++) {
		arg[narg] = $i
		narg++
		if (argsiz[$i])
			ncarg++
	}
	if ($i == ";") {
		# process opts
		for (i++; i <= NF && $i != "*/"; i++) {
			if ($i == "e")
				opt_e = 1
			else if ($i == "estrct") {
				opt_e = 1
				e_strict = 1
			} else if ($i == "ep") {
				opt_e = 1
				e_proc = 1
			} else if ($i == "ealloc") {
				opt_e = 1
				e_alloc = 1
			} else if ($i == "sv")
				svreg = 1
			else if ($i == "noret")
				noret = 1
			else if ($i == "alias") {
				i++
				alias = $i
			} else if ($i == "super")
				super = 1
			else if ($i == "super_jsr")
				super_jsr = 1
			else {
				print FILENAME ":" NR ": unknown opt", $i
				exit(1)
			}
		}
	}
	if ($i != "*/") {
		print FILENAME ":" NR ": malformed input line:" $0
		exit(1)
	}
	# find out func name
	printf "|"
	for (i++; i <= NF; i++) {
		printf " %s", $i
		if ($i ~ /^\**DOS_[A-Z0-9_]*$/) {
			funcnam = $i
			while (funcnam ~ /^\*/) {
				funcnam = substr(funcnam, 2, length(funcnam) -1)
				ptrval = 1
			}
		}
	}
	print ""
	if (!funcnam) {
		print FILENAME ":" NR ": can't find function name"
		exit(1)
	}

	# output assembly code
	print "ENTRY_NOPROFILE(" funcnam ")"
	if (alias) {
		print "GLOBAL(" alias ")"
	}
	if (svreg)	print "\tmoveml\t%d2-%d7/%a2-%a6,%sp@-"

	# PUSH ARGS
	argoff = ncarg * 4
	if (svreg)
		argoff += 4 * 11
	for (i = narg - 1; i >= 0; i--) {
		a = arg[i]
		asz = argsiz[a]
		if (asz) {
			if (a == "l") {
				# optimize with movem
				if (arg[i-1] == "l" && arg[i-2] == "l") {
					if (arg[i-3] == "l") {
						print "\tmoveml\t%sp@(" argoff - 12 "),%d0-%d1/%a0-%a1"
						print "\tmoveml\t%d0-%d1/%a0-%a1,%sp@-"
						asz = 16
						i -= 3
					} else if (arg[i-3] == "w") {
						print "\tmoveml\t%sp@(" argoff - 12 "),%d0-%d1/%a0-%a1"
						print "\tmoveml\t%d1/%a0-%a1,%sp@-"
						print "\tmovew\t%d0,%sp@-"
						asz = 14
						i -= 3
					} else {
						print "\tmoveml\t%sp@(" argoff - 8 "),%d0-%d1/%a0"
						print "\tmoveml\t%d0-%d1/%a0,%sp@-"
						asz = 12
						i -= 2
					}
				} else {
					print "\tmovel\t%sp@(" argoff "),%sp@-"
				}
			} else if (a == "w")
				print "\tmovew\t%sp@(" argoff + 2 "),%sp@-"
			else if (a == "lb31") {
				print "\tmovel\t%sp@(" argoff "),%d0"
				print "\tbset\t#31,%d0"
				print "\tmovel\t%d0,%sp@-"
			} else if (a == "wb8") {
				print "\tmovew\t%sp@(" argoff + 2 "),%d0"
				print "\torw\t#0x100,%d0"
				print "\tmovew\t%d0,%sp@-"
			} else if (a == "wb15") {
				print "\tmovew\t%sp@(" argoff + 2 "),%d0"
				print "\torw\t#0x8000,%d0"
				print "\tmovew\t%d0,%sp@-"
			} else {
				print "??? unknown type"
				exit(1)
			}

			if (asz == 2)
				argoff -= 2
		} else if (a ~ /^[0-9][0-9]*\.w$/) {
			asz = 2
			argoff += 2
			val = substr(a, 1, length(a) - 2)
			if (val == 0)
				print "\tclrw\t%sp@-"
			else
				print "\tmovew\t#" val ",%sp@-"
		} else if (a ~ /^[0-9][0-9]*\.l$/) {
			asz = 4;
			argoff += 4
			val = substr(a, 1, length(a) - 2)
			if (val == 0)
				print "\tclrl\t%sp@-"
			else if (val <= 32767)
				print "\tpea\t" val ":w"
			else
				print "\tmovel\t#" val ",%sp@-"
		} else if (a == "drvctrl" && narg == 1) {
			# only for DOS_DRVCTRL
			asz = 2
			print "\tmoveb\t%sp@(7),%d0"
			print "\tlslw\t#8,%d0"
			print "\tmoveb\t%sp@(11),%d0"
			print "\tmovew\t%d0,%sp@-"
		} else if (a == "super" && narg == 1) {
			# only for DOS_SUPER
			print "\tmoveal\t%sp@+,%a1"
		} else {
			print FILENAME ":" NR ": unknown arg type:", a
			exit(1)
		}
		argbyte += asz
	}

	if (super_jsr) {
		print "\tmoveal\t%sp@(" argoff + 8 "),%a0	| inregs"
		print "\tmoveml\t%a0@,%d0-%d7/%a0-%a6"
	}

	if (dosno ~ /^ff[8a]./) {
		if (dosno ~ /^..8./)
			v2dosno = "ff5" substr(dosno, 4, 1)
		else
			v2dosno = "ff7" substr(dosno, 4, 1)
		print "\tcmpiw	#0x200+14,_C_LABEL(_vernum)+2	| 2.14"
#		print "\tbcss\tLv2doscall"
		print "\tbcss\t2f"
		print "\t.word\t0x" dosno
		if (!noret)
#			print "\tbras\tLedoscall"
			print "\tbras\t3f"
#		print "Lv2doscall:"
		print "2:"
		print "\t.word\t0x" v2dosno
		if (!noret)
#			print "Ledoscall:"
			print "3:"
	} else {
		print "\t.word\t0x" dosno
	}

	# no postprocess needed for dead calls
	if (noret)
		next

	if (super_jsr) {
		print "\tmovel\t%a6,%sp@"
		print "\tmoveal\t%sp@(" argoff + 12 "),%a6	| outregs"
		print "\tmovel\t%sp@+,%a6@(" 4 * 14 ")"
		print "\tmoveml\t%d0-%d7/%a0-%a5,%a6@"
	} else if (argbyte > 0) {
		# POP ARGS
		if (argbyte <= 8)
			print "\taddql\t#" argbyte ",%sp"
		else
			print "\tlea\t%sp@(" argbyte "),%sp"
	}

	if (svreg)	print "\tmoveml\t%sp@+,%d2-%d7/%a2-%a6"
	if (ptrval)	print "#ifdef __SVR4_ABI__\n\tmoveal\t%d0,%a0\n#endif"
	if (opt_e) {
		if (e_strict) {
			print "\tcmpil\t#0xffffff00,%d0"
			print "\tbcc\tCERROR"
		} else  {
			print "\ttstl\t%d0"
			if (super) {
#				print "\tbpls\tLnoerr"
				print "\tbpls\t5f"
				print "\tnegl\t%d0"
				print "\tmovel\t%d0,_C_LABEL(dos_errno)"
				print "\tnegl\t%d0"
#				print "Lnoerr:"
				print "5:"
			} else if (e_alloc) {
#				print "\tbpls\tLnoerr"
				print "\tbpls\t5f"
				print "\tmovel\t#" errno_nomem ",_C_LABEL(dos_errno)"
#				print "Lnoerr:"
				print "5:"
			} else if (e_proc) {
				print "\tbmi\tPRCERROR"
			} else
				print "\tbmi\tCERROR"
		}
	}
	if (super)
		print "\tjmp\t%a1@"
	else
		print "\trts"
}