2019-07-20 04:24:35 +10:00
|
|
|
#!/usr/bin/env python3
|
2019-04-18 11:03:20 +10:00
|
|
|
# Generate almost all possible combination for instructions from instruction
|
|
|
|
# tables
|
2019-07-21 07:13:57 +10:00
|
|
|
# When zasm supported instructions change, use this script to update
|
|
|
|
# allinstrs.asm
|
2019-04-18 11:03:20 +10:00
|
|
|
|
2019-04-21 12:37:38 +10:00
|
|
|
import sys
|
|
|
|
|
2019-04-18 11:03:20 +10:00
|
|
|
argspecTbl = {
|
|
|
|
'A': "A",
|
|
|
|
'B': "B",
|
|
|
|
'C': "C",
|
2019-04-22 03:58:13 +10:00
|
|
|
'k': "(C)",
|
2019-04-18 11:03:20 +10:00
|
|
|
'D': "D",
|
|
|
|
'E': "E",
|
|
|
|
'H': "H",
|
|
|
|
'L': "L",
|
2019-04-22 04:49:33 +10:00
|
|
|
'I': "I",
|
|
|
|
'R': "R",
|
2019-04-18 11:03:20 +10:00
|
|
|
'h': "HL",
|
|
|
|
'l': "(HL)",
|
|
|
|
'd': "DE",
|
|
|
|
'e': "(DE)",
|
|
|
|
'b': "BC",
|
|
|
|
'c': "(BC)",
|
|
|
|
'a': "AF",
|
|
|
|
'f': "AF'",
|
2019-04-21 12:56:22 +10:00
|
|
|
'X': "IX",
|
2019-04-18 11:03:20 +10:00
|
|
|
'x': "(IX)",
|
2019-04-21 12:56:22 +10:00
|
|
|
'Y': "IY",
|
2019-04-18 11:03:20 +10:00
|
|
|
'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",
|
2019-04-21 12:56:22 +10:00
|
|
|
chr(0x04): "bdXs",
|
|
|
|
chr(0x05): "bdYs",
|
2019-04-18 11:03:20 +10:00
|
|
|
chr(0x0a): "ZzC=+-12",
|
|
|
|
chr(0x0b): "BCDEHLA",
|
|
|
|
}
|
|
|
|
|
2019-11-11 14:03:18 +11:00
|
|
|
# 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'}
|
|
|
|
|
2019-04-21 12:37:38 +10:00
|
|
|
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)
|
2019-11-13 06:07:45 +11:00
|
|
|
if line == '.db 0xff':
|
|
|
|
break
|
|
|
|
# skip index labels lines
|
|
|
|
if line.startswith('.db'):
|
2019-04-21 12:37:38 +10:00
|
|
|
result.append([s.strip() for s in line[4:].split(',')])
|
|
|
|
line = fp.readline()
|
|
|
|
return result
|
2019-04-18 11:03:20 +10:00
|
|
|
|
|
|
|
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
|
2019-04-22 00:55:47 +10:00
|
|
|
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})")
|
2019-10-18 06:38:11 +11:00
|
|
|
result.append(f"(I{argspec}-{n})")
|
2019-04-22 00:55:47 +10:00
|
|
|
return result
|
2019-04-18 11:03:20 +10:00
|
|
|
if argspec in argspecTbl:
|
|
|
|
return [argspecTbl[argspec]]
|
2019-11-11 14:03:18 +11:00
|
|
|
if argspec == chr(0xc): # special BIT "b" group
|
|
|
|
return ['0', '3', '7']
|
2019-04-18 11:03:20 +10:00
|
|
|
grp = argGrpTbl[argspec]
|
|
|
|
return [argspecTbl[a] for a in grp]
|
|
|
|
|
2019-07-21 07:13:57 +10:00
|
|
|
# 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]]
|
|
|
|
|
2019-04-18 11:03:20 +10:00
|
|
|
def main():
|
2019-04-21 12:37:38 +10:00
|
|
|
asmfile = sys.argv[1]
|
|
|
|
with open(asmfile, 'rt') as fp:
|
|
|
|
instrTbl = getDbLines(fp, 'instrTBl')
|
|
|
|
for row in instrTbl:
|
2019-05-01 10:25:38 +10:00
|
|
|
n = row[0][2:] # remove I_
|
2019-04-21 12:37:38 +10:00
|
|
|
# we need to adjust for zero-char name filling
|
2019-05-01 10:25:38 +10:00
|
|
|
a1 = eval(row[1])
|
|
|
|
a2 = eval(row[2])
|
2019-04-18 11:03:20 +10:00
|
|
|
args1 = genargs(a1)
|
2019-04-22 02:58:28 +10:00
|
|
|
# special case handling
|
2019-11-11 14:03:18 +11:00
|
|
|
if n in instrsWithIXY and a1 == 'l':
|
|
|
|
args1 += genargs('x')
|
|
|
|
args1 += genargs('y')
|
|
|
|
|
2019-04-22 02:58:28 +10:00
|
|
|
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]
|
2019-07-21 07:13:57 +10:00
|
|
|
if n in {'JR', 'DJNZ'} and a1 == 'n':
|
|
|
|
args1 = eargs(args1)
|
2019-04-22 03:58:13 +10:00
|
|
|
if n == 'IM':
|
|
|
|
args1 = [0, 1, 2]
|
2019-11-13 06:07:45 +11:00
|
|
|
if n == 'RST':
|
|
|
|
args1 = [i*8 for i in range(8)]
|
2019-04-18 11:03:20 +10:00
|
|
|
if args1:
|
|
|
|
for arg1 in args1:
|
|
|
|
args2 = genargs(a2)
|
2019-11-11 14:03:18 +11:00
|
|
|
if n in instrsWithIXY and a2 == 'l':
|
|
|
|
args2 += genargs('x')
|
|
|
|
args2 += genargs('y')
|
2019-04-18 11:03:20 +10:00
|
|
|
if args2:
|
2019-07-21 07:13:57 +10:00
|
|
|
if n in {'JR', 'DJNZ'} and a2 == 'n':
|
|
|
|
args2 = eargs(args2)
|
2019-04-18 11:03:20 +10:00
|
|
|
for arg2 in args2:
|
2019-11-13 12:47:09 +11:00
|
|
|
print(f"{n} {arg1}, {arg2}")
|
2019-04-18 11:03:20 +10:00
|
|
|
else:
|
2019-11-13 12:47:09 +11:00
|
|
|
print(f"{n} {arg1}")
|
2019-04-18 11:03:20 +10:00
|
|
|
else:
|
2019-11-13 12:47:09 +11:00
|
|
|
print(n)
|
2019-04-18 11:03:20 +10:00
|
|
|
pass
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|