chipty5/ch8dis.py

144 lines
4.9 KiB
Python
Executable File

#!/usr/bin/env python3
import struct
OP = [
# Mnemonic, mask, value, xmask, ymask, kmask, klabel
('CLS', '',
0xffff, 0x00e0, 0x0000, 0x0000, 0x0000, False),
('RET', '',
0xffff, 0x00ee, 0x0000, 0x0000, 0x0000, False),
('SYS', '{k}',
0xf000, 0x0000, 0x0000, 0x0000, 0x0fff, True),
('JP', '{k}',
0xf000, 0x1000, 0x0000, 0x0000, 0x0fff, True),
('CALL', '{k}',
0xf000, 0x2000, 0x0000, 0x0000, 0x0fff, True),
('SE', 'V{x:01x}, {k:02x}',
0xf000, 0x3000, 0x0f00, 0x0000, 0x00ff, False),
('SNE', 'V{x:01x}, {k:02x}',
0xf000, 0x4000, 0x0f00, 0x0000, 0x00ff, False),
('SE', 'V{x:01x}, V{y:01x}',
0xf00f, 0x5000, 0x0f00, 0x00f0, 0x0000, False),
('LD', 'V{x:01x}, {k:02x}',
0xf000, 0x6000, 0x0f00, 0x0000, 0x00ff, False),
('ADD', 'V{x:01x}, {k:02x}',
0xf000, 0x7000, 0x0f00, 0x0000, 0x00ff, False),
('LD', 'V{x:01x}, V{y:01x}',
0xf00f, 0x8000, 0x0f00, 0x00f0, 0x0000, False),
('OR', 'V{x:01x}, V{y:01x}',
0xf00f, 0x8001, 0x0f00, 0x00f0, 0x0000, False),
('AND', 'V{x:01x}, V{y:01x}',
0xf00f, 0x8002, 0x0f00, 0x00f0, 0x0000, False),
('XOR', 'V{x:01x}, V{y:01x}',
0xf00f, 0x8003, 0x0f00, 0x00f0, 0x0000, False),
('ADD', 'V{x:01x}, V{y:01x}',
0xf00f, 0x8004, 0x0f00, 0x00f0, 0x0000, False),
('SUB', 'V{x:01x}, V{y:01x}',
0xf00f, 0x8005, 0x0f00, 0x00f0, 0x0000, False),
('SHR', 'V{x:01x}, V{y:01x}',
0xf00f, 0x8006, 0x0f00, 0x00f0, 0x0000, False),
('SHL', 'V{x:01x}, V{y:01x}',
0xf00f, 0x800e, 0x0f00, 0x00f0, 0x0000, False),
('SNE', 'V{x:01x}, V{y:01x}',
0xf00f, 0x9000, 0x0f00, 0x00f0, 0x0000, False),
('LD', 'I, {k}',
0xf000, 0xa000, 0x0000, 0x0000, 0x0fff, True),
('JP', 'V0, {k}',
0xf000, 0xb000, 0x0000, 0x0000, 0x0fff, True),
('RND', 'V{x:01x}, {k:02x}',
0xf000, 0xc000, 0x0f00, 0x0000, 0x00ff, False),
('DRW', 'V{x:01x}, V{y:01x}, {k:02x}',
0xf000, 0xd000, 0x0f00, 0x00f0, 0x000f, False),
('SKP', 'V{x:01x}',
0xf0ff, 0xe09e, 0x0f00, 0x0000, 0x0000, False),
('SKNP', 'V{x:01x}',
0xf0ff, 0xe0a1, 0x0f00, 0x0000, 0x0000, False),
('LD', 'V{x:01x}, DT',
0xf0ff, 0xf007, 0x0f00, 0x0000, 0x0000, False),
('LD', 'V{x:01x}, K',
0xf0ff, 0xf00a, 0x0f00, 0x0000, 0x0000, False),
('LD', 'DT, V{x:01x}',
0xf0ff, 0xf015, 0x0f00, 0x0000, 0x0000, False),
('LD', 'ST, V{x:01x}',
0xf0ff, 0xf018, 0x0f00, 0x0000, 0x0000, False),
('ADD', 'I, V{x:01x}',
0xf0ff, 0xf01e, 0x0f00, 0x0000, 0x0000, False),
('LD', 'F, V{x:01x}',
0xf0ff, 0xf029, 0x0f00, 0x0000, 0x0000, False),
('LD', 'B, V{x:01x}',
0xf0ff, 0xf033, 0x0f00, 0x0000, 0x0000, False),
('LD', '[I], V{x:01x}',
0xf0ff, 0xf055, 0x0f00, 0x0000, 0x0000, False),
('LD', 'V{x:01x}, [I]',
0xf0ff, 0xf065, 0x0f00, 0x0000, 0x0000, False),
('DATA', '{k:04x}',
0x0000, 0x0000, 0x0000, 0x0000, 0xffff, False)
]
def c8decode(ins):
def _unmask(v, m):
if m == 0:
return None
r = v & m
while (m & 1) == 0:
m >>= 1
r >>= 1
return r
for mn, fmt, mask, value, xmask, ymask, kmask, klabel in OP:
if (ins & mask) == value:
xo = _unmask(ins, xmask)
yo = _unmask(ins, ymask)
ko = _unmask(ins, kmask)
return (mn, fmt, xo, yo, ko, klabel)
def disasm(filename, org=0x200):
pc = org
targets = set()
listing = []
with open(filename, 'rb') as f:
while True:
w = f.read(2)
if len(w) != 2:
break
instr = struct.unpack('>H', w)[0]
mn, fmt, xo, yo, ko, klabel = c8decode(instr)
if klabel:
targets.add(ko)
listing.append((pc, instr, mn, fmt, xo, yo, ko, klabel))
pc += 2
end = pc
print(f""";
; {filename}
; start={org:03x} end={end:03x} size={end-org}(dec)
;
""")
for pc, instr, mn, fmt, xo, yo, ko, klabel in listing:
if pc in targets:
label = "l%03x" % (pc,)
else:
label = ""
if klabel:
if org <= ko <= end:
ko = f"l{ko:03x}"
else:
ko = f"{ko:03x}"
o = fmt.format(x=xo, y=yo, k=ko)
print(f"{label:8s} {mn:5s} {o:12s} ; {pc:03x}: {instr:04x}")
if __name__ == '__main__':
import sys
for fn in sys.argv[1:]:
disasm(fn)