#!/usr/bin/python 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-2012 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", # 0 "Immediate", # 1 "Immediate.W", # 2 "Zero Page", # 3 "Zero Page, X", # 4 "Zero Page, Y", # 5 "Absolute", # 6 "Absolute, X", # 7 "Absolute, Y", # 8 "(Absolute)", # 9 "(Absolute, X)", # 10 "(Absolute), Y", # 11 "(Zero Page)", # 12 "(Zero Page, X)", # 13 "(Zero Page), Y", # 14 "(Zero Page, SP), Y", # 15 "(Zero Page), Z", # 16 "Relative", # 17 "RelativeLong", # 18 "Zero Page, Relative"] # 19 # Lengths of the argument lengths = [0, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2,2] """ # These values should match the ones in the prologue string. modes = ["Implied", # 0 "Immediate", # 1 "Immediate.W", # 2 "Zero Page", # 3 "Zero Page, X", # 4 "Zero Page, Y", # 5 "Absolute", # 6 "Absolute, X", # 7 "Absolute, Y", # 8 "(Absolute)", # 9 "(Absolute, X)", # 10 "(Absolute), Y", # 11 "(Zero Page)", # 12 "(Zero Page, X)", # 13 "(Zero Page), Y", # 14 "(Zero Page, SP), Y", # 15 "(Zero Page), Z", # 16 "Relative", # 17 "RelativeLong", # 18 "Zero Page, Relative"] # 19 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 file(fname).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(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 = 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))