#! /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" }