#! /usr/bin/awk -f
#
# create IOCS call interface from iocs.h
#
# written by ITOH Yasufumi
# public domain
#
# $NetBSD: makeiocscalls.awk,v 1.3 2011/02/21 02:31:59 itohy Exp $
BEGIN {
argsiz["l"] = 4; argsiz["w"] = 2
argsiz["lb31"] = 4; argsiz["wb8"] = 2
for (i = 0; i < 16; i++) {
reg = substr("d0d1d2d3d4d5d6d7a0a1a2a3a4a5a6a7", i*2+1, 2)
regno[reg] = i
}
print "#include <machine/asm.h>"
}
$1 == "/*" && ($2 ~ /^[0-9a-f][0-9a-f]$/ || $2 == "(none)") {
funcnam=""
iocsno=$2
ptrval=0
narg=0
retd2=0
err_d0=0
noret=0
c_md=0
b_super=0
sp_regst=0
b_curmod = 0
b_curpat = 0
b_scroll = 0
iocs_trap15=0
for (i = 3; i <= NF && $i != "*/" && $i != ";"; i++) {
arg[narg] = $i
narg++
}
if ($i == ";") {
# process opts
for (i++; i <= NF && $i != "*/"; i++) {
if ($i == "retd2")
retd2 = 1
else if ($i == "err_d0")
err_d0 = 1
else if ($i == "noret")
noret = 1
else if ($i == "c_md")
c_md = 1
else if ($i == "b_super")
b_super = 1
else if ($i == "sp_regst")
sp_regst = 1
else if ($i == "b_curmod")
b_curmod = 1
else if ($i == "b_curpat")
b_curpat = 1
else if ($i == "b_scroll")
b_scroll = 1
else if ($i == "trap15")
iocs_trap15 = 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 ~ /^\**IOCS_[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 ")"
# SAVE REGISTERS
for (i = 0; i < 16; i++) {
savereg[i] = 0
}
for (i = 0; i < narg; i++) {
r = arg[i]
if (r ~ /^o[ad][0-7]$/)
r = substr(r, 2, 2)
else if (r ~ /^d[0-7]=/)
r = substr(r, 1, 2)
if (r != "d0" && !regno[r]) {
print FILENAME ":" NR ": unknown arg type:", arg[i]
exit(1)
}
if (r !~ /^[da][01]$/) # may not be saved
savereg[regno[r]] = r
}
# count reg to save
nsave = 0
for (i = 0; i < 16; i++) {
if (savereg[i])
nsave++
}
if (iocs_trap15) {
print "\tmoveml\t%d2-%d7/%a2-%a6,%sp@-"
nsave = 11
} else if (nsave == 1 || nsave == 2){
# use movel
for (i = 0; i < 16; i++) {
if (savereg[i])
print "\tmovel\t%" savereg[i] ",%sp@-"
}
} else if (nsave > 2) {
# use moveml
saveregs = ""
for (i = 0; i < 16; i++) {
if (savereg[i])
saveregs = saveregs "/%" savereg[i]
}
saveregs = substr(saveregs, 2, length(saveregs) - 1)
print "\tmoveml\t" saveregs ",%sp@-"
}
# LOAD ARGS
# XXX this should be more intelligent
argoff = nsave * 4 + 4
# input arguments for IOCS call
iarg = ""
iargreglist = ""
niarg = 0
iarg_incorder = 1
immarg = ""
nimmarg = 0
for (i = 0; i < narg && arg[i] ~ /^[ad]/; i++) {
a = arg[i]
if (a ~ /^d[1-7]=[0-9][0-9]*$/) {
immarg = immarg " " a
nimmarg++
} else {
if (iarg) {
if (regno[a1] >= regno[a])
iarg_incorder = 0
}
a1 = a
iarg = iarg "/" a
iargreglist = iargreglist "/%" a
niarg++
}
}
oarg = ""
noarg = 0
for ( ; i < narg; i++) {
if (arg[i] ~ /^[o]d[0-7]/) {
oarg = oarg " " arg[i]
noarg++
} else {
print "unknown arg:", arg[i]
exit(1)
}
}
# remove leading char
iarg = substr(iarg, 2, length(iarg) - 1);
iargreglist = substr(iargreglist, 2, length(iargreglist) - 1);
immarg = substr(immarg, 2, length(immarg) - 1);
oarg = substr(oarg, 2, length(oarg) - 1);
# load input args
if (niarg == 0)
;
else if (niarg == 1 && iarg !~ /\=/) {
print "\tmovel\t%sp@(" argoff "),%" iarg "\t| 1arg"
} else if (iarg_incorder && iarg !~ /\=/) {
print "\tmoveml\t%sp@(" argoff ")," iargreglist "\t| inc order"
} else if (iarg == "a1/d1") {
print "\tmoveal\t%sp@(" argoff "),%a1"
print "\tmovel\t%sp@(" argoff + 4 "),%d1"
} else if (iarg == "d1/a1/d2") {
print "\tmoveml\t%sp@(" argoff "),%d1-%d2/%a1"
print "\texg\t%d2,%a1"
} else if (iarg == "a1/a2/d1") {
print "\tmoveml\t%sp@(" argoff "),%a1/%a2"
print "\tmovel\t%sp@(" argoff + 8 "),%d1"
} else if (iarg == "a1/a2/d1/d2") {
print "\tmoveml\t%sp@(" argoff "),%d1-%d2/%a1-%a2"
print "\texg\t%d1,%a1"
print "\texg\t%d2,%a2"
} else if (iarg == "a1/d1/d2") {
print "\tmoveml\t%sp@(" argoff "),%d0-%d2"
print "\tmovel\t%d0,%a1"
} else if (iarg == "d1=bb") {
print "\tmoveq\t#0,%d1"
print "\tmoveb\t%sp@(" argoff + 3 "),%d1"
print "\tlslw\t#8,%d1"
print "\tmoveb\t%sp@(" argoff + 7 "),%d1"
niarg = 2
} else if (iarg == "d1=ww") {
print "\tmovew\t%sp@(" argoff + 2 "),%d1"
print "\tswap\t%d1"
print "\tmovew\t%sp@(" argoff + 6 "),%d1"
niarg = 2
} else if (iarg == "d1=hsv") {
print "\tmoveb\t%sp@(" argoff + 3 "),%d1"
print "\tswap\t%d1"
print "\tmoveb\t%sp@(" argoff + 7 "),%d1"
print "\tlslw\t#8,%d1"
print "\tmoveb\t%sp@(" argoff + 11 "),%d1"
print "\tandl\t#0x00ff1f1f,%d1"
niarg = 3
} else if (iarg == "a1/d1=bb") {
print "\tmoveal\t%sp@(" argoff "),%a1"
print "\tmoveq\t#0,%d1"
print "\tmoveb\t%sp@(" argoff + 7 "),%d1"
print "\tlslw\t#8,%d1"
print "\tmoveb %sp@(" argoff + 11 "),%d1"
niarg = 3
} else if (iarg == "d1/d2=ww") {
print "\tmovel\t%sp@(" argoff "),%d1"
print "\tmovew\t%sp@(" argoff + 6 "),%d2"
print "\tswap\t%d2"
print "\tmovew\t%sp@(" argoff + 10 "),%d2"
niarg = 3
} else if (iarg == "d1=ww/a1") {
print "\tmoveml\t%sp@(" argoff "),%d0-%d1/%a1"
print "\tswap\t%d1"
print "\tmovew\t%d0,%d1"
print "\tswap\t%d1"
niarg = 3
} else if (iarg == "d1=ww/d2=ww") {
print "\tmoveml\t%sp@(" argoff "),%d1-%d2"
print "\tswap\t%d1"
print "\tmovew\t%d2,%d1"
print "\tmovew\t%sp@(" argoff + 10 "),%d2"
print "\tswap\t%d2"
print "\tmovew\t%sp@(" argoff + 14 "),%d2"
niarg = 4
} else {
print "unsupported iarg:", iarg
exit(1)
}
argoff += niarg * 4
if (sp_regst) {
print "\tandl\t#0x80000000,%d1"
print "\tmoveb\t%d0,%d1"
}
if (b_curmod) {
print "\tmoveq\t#1,%d0"
print "\tcmpl\t%d1,%d0"
# print "\tbcss\tLerr"
print "\tbcss\t6f"
}
if (b_curpat) {
print "\ttstw\t%d2"
# print "\tbeqs\tLerr"
print "\tbeqs\t6f"
}
if (b_super) {
print "\tmoval\t%sp@+,%a0"
print "\tmoval\t%sp@,%a1"
}
# load imm args
if (nimmarg) {
for (i = 0; i < narg && arg[i] ~ /^[ad]/; i++) {
a = arg[i]
if (a ~ /^d[1-7]=[0-9][0-9]*$/) {
r = substr(a, 1, 2)
v = substr(a, 4, length(a)-3)
print "\tmoveq\t#" v ",%" r
}
}
}
if (c_md) {
# -1: flush(3), -2: set default(2), other: set by the value(4)
print "\tmovel\t%d2,%d0"
print "\taddql\t#1,%d0"
print "\tbeqs\tLcachemd"
print "\tmoveq\t#2,%d1"
print "\taddql\t#1,%d0"
print "\tbnes\tLcachemd"
print "\tmoveq\t#4,%d1"
print "Lcachemd:"
}
if (b_scroll) {
# d1 has 16
print "\tcmpl\t%d1,%d2"
print "\tbcss\tLscriocs"
print "\tmovel\t%d2,%d1"
print "Lscriocs:"
}
if (iocs_trap15) {
print "\tmoveal\t%sp@(" argoff "),%a0 | inregs"
print "\tmoveml\t%a0@,%d0-%d7/%a1-%a6"
argoff += 4
}
if (iocsno != "(none)") {
if (iocsno ~ /^[89abcdef]./)
iocsno = "ffffff" iocsno
print "\tmoveq\t#0x" iocsno ",%d0"
}
print "\ttrap\t#15"
if (iocs_trap15) {
print "\tmoveal\t%sp@(" argoff "),%a0 | outregs"
print "\tmoveml\t%d0-%d7/%a1-%a6,%a0@"
}
if (err_d0 && noarg) {
print "\ttstl\t%d0"
# print "\tbnes\tLerr"
print "\tbnes\t6f"
}
# SAVERESULTS
# XXX this should be more intelligent
if (noarg == 0)
;
else if (oarg == "od2") {
print "\tmoveal\t%sp@(" argoff "),%a0"
argoff += 4
print "\tmovel\t%d2,%a0@"
} else if (oarg == "od1 od2 od0") {
print "\tmoveml\t%sp@(" argoff "),%a0/%a1"
argoff += 8
print "\tmovel\t%d1,%a0@"
print "\tmovel\t%d2,%a1@"
print "\tmoveal\t%sp@(" argoff "),%a0"
argoff += 4
print "\tmovel\t%d0,%a0@"
} else if (oarg == "od2 od3") {
print "\tmoveml\t%sp@(" argoff "),%a0/%a1"
argoff += 8
print "\tmovel\t%d2,%a0@"
print "\tmovel\t%d3,%a1@"
} else if (oarg == "od2 od3 od4 od5") {
print "\tmoveml\t%sp@(" argoff "),%a0/%a1"
argoff += 8
print "\tmovel\t%d2,%a0@"
print "\tmovel\t%d3,%a1@"
print "\tmoveml\t%sp@(" argoff "),%a0/%a1"
argoff += 8
print "\tmovel\t%d4,%a0@"
print "\tmovel\t%d5,%a1@"
} else {
print "unsupported oarg:", oarg
exit(1)
}
if ((err_d0 && noarg) || b_curmod || b_curpat)
# print "Lerr:"
print "6:"
# return value
if (retd2)
print "\tmovel\t%d2,%d0"
# RESTORE REGISTERS
if (iocs_trap15) {
print "\tmoveml\t%sp@+,%d2-%d7/%a2-%a6"
} else if (nsave == 1 || nsave == 2){
# use movel
for (i = 16 - 1; i >= 0; i--) {
if (savereg[i])
print "\tmovel\t%sp@+,%" savereg[i]
}
} else if (nsave > 2) {
# use moveml
print "\tmoveml\t%sp@+," saveregs
}
if (b_super)
print "\tjmp\t%a0@"
else if (!noret) {
if (ptrval)
print "#ifdef __SVR4_ABI__\n\tmoveal\t%d0,%a0\n#endif"
print "\trts"
}
}