1#! /usr/bin/awk -f
2#
3#	create DOS call interface from dos.h
4#
5#	written by Yasha (ITOH Yasufumi)
6#	public domain
7#
8#	$NetBSD: makedoscalls.awk,v 1.3 2000/06/19 03:43:12 itohy Exp $
9
10BEGIN {
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