183 lines
5.3 KiB
Python
Executable File
183 lines
5.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import sys
|
|
|
|
verbose = 0
|
|
|
|
prologue = '"""' + """Opcodes file.
|
|
|
|
Tables for the assembly of 6502-family instructions, mapping
|
|
opcodes and addressing modes to binary instructions.""" + '"""' + """
|
|
|
|
# Copyright 2002-2014 Michael C. Martin and additional contributors.
|
|
# You may use, modify, and distribute this file under the MIT
|
|
# license: See README for details.
|
|
|
|
# DO NOT EDIT THIS FILE DIRECTLY.
|
|
# This file was automatically generated by gensets.py based on the
|
|
# the tables in tools/opcodes. Edit those tables, not these.
|
|
|
|
# Names of addressing modes
|
|
modes = ["Implied",
|
|
"Immediate",
|
|
"ImmediateLong",
|
|
"Zero Page",
|
|
"Zero Page, X",
|
|
"Zero Page, Y",
|
|
"Absolute",
|
|
"Absolute, X",
|
|
"Absolute, Y",
|
|
"(Absolute)",
|
|
"(Absolute, X)",
|
|
"(Absolute), Y",
|
|
"(Absolute), Z",
|
|
"(Zero Page)",
|
|
"(Zero Page, X)",
|
|
"(Zero Page), Y",
|
|
"(Zero Page, SP), Y",
|
|
"(Zero Page), Z",
|
|
"Relative",
|
|
"RelativeLong",
|
|
"Zero Page, Relative"]
|
|
|
|
|
|
# Lengths of the argument
|
|
lengths = [0, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2]
|
|
"""
|
|
|
|
# These values should match the ones in the prologue string.
|
|
modes = ["Implied",
|
|
"Immediate",
|
|
"Immediate.W",
|
|
"Zero Page",
|
|
"Zero Page, X",
|
|
"Zero Page, Y",
|
|
"Absolute",
|
|
"Absolute, X",
|
|
"Absolute, Y",
|
|
"(Absolute)",
|
|
"(Absolute, X)",
|
|
"(Absolute), Y",
|
|
"(Absolute), Z",
|
|
"(Zero Page)",
|
|
"(Zero Page, X)",
|
|
"(Zero Page), Y",
|
|
"(Zero Page, SP), Y",
|
|
"(Zero Page), Z",
|
|
"Relative",
|
|
"RelativeLong",
|
|
"Zero Page, Relative"]
|
|
|
|
|
|
flatmodes = [x.lower() for x in modes]
|
|
|
|
|
|
# WARNING: This decommenter assumes that # never appears anywhere else
|
|
# in a line.
|
|
def decomment(l):
|
|
if '#' in l:
|
|
l = l[:l.index('#')]
|
|
return l.strip()
|
|
|
|
|
|
def decomment_readlines(fname):
|
|
result = [decomment(x) for x in open(fname, "rt").readlines()]
|
|
return [x for x in result if len(x) > 0]
|
|
|
|
|
|
def parse_chipset_file(fname):
|
|
result = [None] * 256
|
|
ls = [[x.strip() for x in y]
|
|
for y in [z.split(':', 1) for z in decomment_readlines(fname)]]
|
|
for l in ls:
|
|
if len(l) == 2:
|
|
try:
|
|
op = int(l[0], 16)
|
|
syns = l[1].split(';')
|
|
for s in syns:
|
|
s_p = s.split('-')
|
|
if len(s_p) == 2:
|
|
mnem = s_p[0].lower().strip()
|
|
mode = s_p[1].lower().strip()
|
|
if mode in flatmodes:
|
|
if result[op] is None:
|
|
result[op] = []
|
|
result[op].append((mnem, flatmodes.index(mode)))
|
|
else:
|
|
print("Unknown mode '%s'" % s_p[1])
|
|
except ValueError:
|
|
print("Illegal opcode '%s'" % l[0])
|
|
return result
|
|
|
|
|
|
def collate_chipset_map(cs_list, base):
|
|
result = {}
|
|
for (opcode, insts) in zip(list(range(256)), cs_list):
|
|
if insts is not None:
|
|
for inst in insts:
|
|
(mnem, mode) = inst
|
|
if mnem not in result:
|
|
result[mnem] = [None] * len(modes)
|
|
if result[mnem][mode] is not None:
|
|
print("Warning: Reassigning %s - %s" % (mnem, modes[mode]))
|
|
result[mnem][mode] = opcode
|
|
if base is not None:
|
|
todel = []
|
|
for x in result:
|
|
if x in base:
|
|
if result[x] == base[x]:
|
|
todel.append(x)
|
|
elif verbose != 0:
|
|
print("# Opcode %s changed" % x)
|
|
elif verbose != 0:
|
|
print("# Opcode %s added" % x)
|
|
for x in todel:
|
|
del result[x]
|
|
return result
|
|
|
|
|
|
def mapval(x):
|
|
if x is None:
|
|
return "None"
|
|
else:
|
|
return "0x%02X" % x
|
|
|
|
|
|
def dump_map(m, prologue=''):
|
|
mnems = list(m.keys())
|
|
mnems.sort()
|
|
for mnem in mnems:
|
|
codes = [mapval(x) for x in m[mnem]]
|
|
print("%s'%s': [%s,\n%s %s]," % (prologue, mnem,
|
|
', '.join(codes[:8]),
|
|
prologue + " " * len(mnem),
|
|
', '.join(codes[8:])))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
if len(sys.argv) > 1:
|
|
chipsets = sys.argv[1:]
|
|
else:
|
|
chipsets = ['chipsets.txt']
|
|
archs = []
|
|
for x in chipsets:
|
|
try:
|
|
ls = [[x.strip() for x in y]
|
|
for y in [z.split(':', 1) for z in decomment_readlines(x)]]
|
|
for l in ls:
|
|
if len(l) != 2:
|
|
print("Could not parse the chipset line '%s'" % ":".join(l))
|
|
else:
|
|
archs.append((l[0], l[1]))
|
|
except IOError:
|
|
print("Could not read file %s" % x)
|
|
print(prologue)
|
|
baseset = None
|
|
for (field, fname) in archs:
|
|
chipset_list = parse_chipset_file(fname)
|
|
instruction_map = collate_chipset_map(chipset_list, baseset)
|
|
if baseset is None:
|
|
baseset = instruction_map
|
|
print("%s = {" % field)
|
|
dump_map(instruction_map, ' ' * (len(field) + 4))
|
|
print("%s}" % (' ' * (len(field) + 3)))
|