1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-12-01 03:18:05 +11:00
collapseos/tests/zasm/geninstrs.py
2019-12-31 13:07:05 -05:00

165 lines
4.1 KiB
Python
Executable File

#!/usr/bin/env python3
# Generate almost all possible combination for instructions from instruction
# tables
# When zasm supported instructions change, use this script to update
# allinstrs.asm
import sys
argspecTbl = {
'A': "A",
'B': "B",
'C': "C",
'k': "(C)",
'D': "D",
'E': "E",
'H': "H",
'L': "L",
'I': "I",
'R': "R",
'h': "HL",
'l': "(HL)",
'd': "DE",
'e': "(DE)",
'b': "BC",
'c': "(BC)",
'a': "AF",
'f': "AF'",
'X': "IX",
'x': "(IX)",
'Y': "IY",
'y': "(IY)",
's': "SP",
'p': "(SP)",
'Z': "Z",
'z': "NZ",
'=': "NC",
'+': "P",
'-': "M",
'1': "PO",
'2': "PE",
}
argGrpTbl = {
chr(0x01): "bdha",
chr(0x02): "ZzC=",
chr(0x03): "bdhs",
chr(0x04): "bdXs",
chr(0x05): "bdYs",
chr(0x0a): "ZzC=+-12",
chr(0x0b): "BCDEHLA",
}
# whenever we encounter the "(HL)" version of these instructions, spit IX/IY
# too.
instrsWithIXY = {
'ADD', 'AND', 'BIT', 'CP', 'DEC', 'INC', 'OR', 'RES', 'RL', 'RR', 'SET',
'SRL'}
def cleanupLine(line):
line = line.strip()
idx = line.rfind(';')
if idx >= 0:
line = line[:idx]
return line
def getDbLines(fp, tblname):
lookingFor = f"{tblname}:"
line = fp.readline()
while line:
line = cleanupLine(line)
if line == lookingFor:
break
line = fp.readline()
else:
raise Exception(f"{tblname} not found")
result = []
line = fp.readline()
while line:
line = cleanupLine(line)
if line == '.db 0xff':
break
# skip index labels lines
if line.startswith('.db'):
result.append([s.strip() for s in line[4:].split(',')])
line = fp.readline()
return result
def genargs(argspec):
if not argspec:
return ''
if not isinstance(argspec, str):
argspec = chr(argspec)
if argspec in 'nmNM':
bits = 16 if argspec in 'NM' else 8
nbs = [str(1 << i) for i in range(bits)]
if argspec in 'mM':
nbs = [f"({n})" for n in nbs]
return nbs
if argspec in 'xy':
# IX/IY displacement is special
base = argspecTbl[argspec]
result = [base]
argspec = argspec.upper()
for n in [1, 10, 100, 127]:
result.append(f"(I{argspec}+{n})")
result.append(f"(I{argspec}-{n})")
return result
if argspec in argspecTbl:
return [argspecTbl[argspec]]
if argspec == chr(0xc): # special BIT "b" group
return ['0', '3', '7']
grp = argGrpTbl[argspec]
return [argspecTbl[a] for a in grp]
# process a 'n' arg into an 'e' one
def eargs(args):
newargs = ['$+'+s for s in args[:-1]]
return newargs + ['$-'+s for s in args[:-1]]
def main():
asmfile = sys.argv[1]
with open(asmfile, 'rt') as fp:
instrTbl = getDbLines(fp, 'instrTBl')
for row in instrTbl:
n = row[0][2:] # remove I_
# we need to adjust for zero-char name filling
a1 = eval(row[1])
a2 = eval(row[2])
args1 = genargs(a1)
# special case handling
if n in instrsWithIXY and a1 == 'l':
args1 += genargs('x')
args1 += genargs('y')
if n == 'JP' and isinstance(a1, str) and a1 in 'xy':
# we don't test the displacements for IX/IY because there can't be
# any.
args1 = args1[:1]
if n in {'JR', 'DJNZ'} and a1 == 'n':
args1 = eargs(args1)
if n == 'IM':
args1 = [0, 1, 2]
if n == 'RST':
args1 = [i*8 for i in range(8)]
if args1:
for arg1 in args1:
args2 = genargs(a2)
if n in instrsWithIXY and a2 == 'l':
args2 += genargs('x')
args2 += genargs('y')
if args2:
if n in {'JR', 'DJNZ'} and a2 == 'n':
args2 = eargs(args2)
for arg2 in args2:
print(f"{n} {arg1}, {arg2}")
else:
print(f"{n} {arg1}")
else:
print(n)
pass
if __name__ == '__main__':
main()