summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/m6502/m6502make.py
diff options
context:
space:
mode:
author Olivier Galibert <galibert@pobox.com>2012-12-06 19:08:40 +0000
committer Olivier Galibert <galibert@pobox.com>2012-12-06 19:08:40 +0000
commit627ac29a1af68634d3024573e38c7ea4f2157147 (patch)
treeec4ba5f8095da157d9ae9d3c7be108723f1bb28f /src/emu/cpu/m6502/m6502make.py
parentb4d0dde34a67c62d571a7a5eb0bc80a24783f607 (diff)
m6502,tms57002: Snakes in an emulator [Robert Muth, O. Galibert]
Diffstat (limited to 'src/emu/cpu/m6502/m6502make.py')
-rwxr-xr-x[-rw-r--r--]src/emu/cpu/m6502/m6502make.py273
1 files changed, 273 insertions, 0 deletions
diff --git a/src/emu/cpu/m6502/m6502make.py b/src/emu/cpu/m6502/m6502make.py
index e69de29bb2d..e6da2f2e992 100644..100755
--- a/src/emu/cpu/m6502/m6502make.py
+++ b/src/emu/cpu/m6502/m6502make.py
@@ -0,0 +1,273 @@
+#!/usr/bin/python
+
+USAGE = """
+Usage:
+%s device_name {opc.lst|-} disp.lst device.inc
+"""
+import sys
+import logging
+
+MAX_STATES = 0x101
+
+def load_opcodes(fname):
+ """Load opcodes from .lst file"""
+ opcodes = []
+ logging.info("load_opcodes: %s", fname)
+ try:
+ f = open(fname, "r")
+ except Exception, err:
+ logging.error("cannot read opcodes file %s [%s]", fname, err)
+ sys.exit(1)
+
+ for line in f:
+ if line.startswith("#"): continue
+ line = line.rstrip()
+ if not line: continue
+ if line.startswith(" ") or line.startswith("\t"):
+ # append instruction to last opcode
+ opcodes[-1][1].append(line)
+ else:
+ # add new opcode
+ opcodes.append((line, []))
+ return opcodes
+
+
+def load_disp(fname):
+ logging.info("load_disp: %s", fname)
+ states = []
+ try:
+ f = open(fname, "r")
+ except Exception, err:
+ logging.error("cannot read display file %s [%s]", fname, err)
+ sys.exit(1)
+ for line in f:
+ if line.startswith("#"): continue
+ line = line.strip()
+ if not line: continue
+ tokens = line.split()
+ states += tokens
+ return states
+
+def emit(f, text):
+ """write string to file"""
+ print >>f, text,
+
+FULL_PROLOG="""\
+void %(device)s::%(opcode)s_full()
+{
+"""
+
+FULL_EPILOG="""\
+}
+"""
+
+FULL_EAT_ALL="""\
+\ticount=0; inst_substate = %(substate)s; return;
+"""
+
+FULL_MEMORY="""\
+\tif(icount == 0) { inst_substate = %(substate)s; return; }
+%(ins)s
+\ticount--;
+"""
+
+FULL_NONE="""\
+%(ins)s
+"""
+
+PARTIAL_PROLOG="""\
+void %(device)s::%(opcode)s_partial()
+{
+switch(inst_substate) {
+case 0:
+"""
+
+PARTIAL_EPILOG="""\
+}
+\tinst_substate = 0;
+}
+
+"""
+
+PARTIAL_EAT_ALL="""\
+\ticount=0; inst_substate = %(substate)s; return;
+case %(substate)s:;
+"""
+
+PARTIAL_MEMORY="""\
+\tif(icount == 0) { inst_substate = %(substate)s; return; }
+case %(substate)s:
+%(ins)s
+\ticount--;
+"""
+
+PARTIAL_NONE="""\
+%(ins)s
+"""
+def identify_line_type(ins):
+ if "eat-all-cycles" in ins: return "EAT"
+ for s in ["read", "write", "prefetch(", "prefetch_noirq("]:
+ if s in ins:
+ return "MEMORY"
+ return "NONE"
+
+
+def save_opcodes(f, device, opcodes):
+ for name, instructions in opcodes:
+ d = { "device": device,
+ "opcode": name,
+ }
+
+ emit(f, FULL_PROLOG % d)
+ substate = 1
+ for ins in instructions:
+ d["substate"] = str(substate)
+ d["ins"] = ins
+ line_type = identify_line_type(ins)
+ if line_type == "EAT":
+ emit(f, FULL_EAT_ALL % d)
+ substate += 1
+ elif line_type == "MEMORY":
+ emit(f, FULL_MEMORY % d)
+ substate += 1
+ else:
+ emit(f, FULL_NONE %d)
+ emit(f, FULL_EPILOG % d)
+
+ emit(f, PARTIAL_PROLOG % d)
+ substate = 1
+ for ins in instructions:
+ d["substate"] = str(substate)
+ d["ins"] = ins
+ line_type = identify_line_type(ins)
+ if line_type == "EAT":
+ emit(f, PARTIAL_EAT_ALL % d)
+ substate += 1
+ elif line_type == "MEMORY":
+ emit(f, PARTIAL_MEMORY % d)
+ substate += 1
+ else:
+ emit(f, PARTIAL_NONE %d)
+ emit(f, PARTIAL_EPILOG % d)
+
+
+DO_EXEC_FULL_PROLOG="""\
+void %(device)s::do_exec_full()
+{
+\tswitch(inst_state) {
+"""
+
+DO_EXEC_FULL_EPILOG="""\
+\t}
+}
+"""
+
+DO_EXEC_PARTIAL_PROLOG="""\
+void %(device)s::do_exec_partial()
+{
+\tswitch(inst_state) {
+"""
+
+DO_EXEC_PARTIAL_EPILOG="""\
+\t}
+}
+"""
+
+DISASM_PROLOG="""\
+const %(device)s::disasm_entry %(device)s::disasm_entries[0x100] = {
+"""
+
+DISASM_EPILOG="""\
+};
+"""
+
+def save_tables(f, device, states):
+ d = { "device": device,
+ }
+
+ assert len(states) == MAX_STATES
+
+ emit(f, DO_EXEC_FULL_PROLOG % d)
+ for n, state in enumerate(states):
+ if state == ".": continue
+ if n < MAX_STATES - 1:
+ emit(f, "\tcase 0x%02x: %s_full(); break;\n" % (n, state))
+ else:
+ emit(f, "\tcase %s: %s_full(); break;\n" % ("STATE_RESET", state))
+ emit(f, DO_EXEC_FULL_EPILOG % d)
+
+ emit(f, DO_EXEC_PARTIAL_PROLOG % d)
+ for n, state in enumerate(states):
+ if state == ".": continue
+ if n < MAX_STATES - 1:
+ emit(f, "\tcase 0x%02x: %s_partial(); break;\n" % (n, state))
+ else:
+ emit(f, "\tcase %s: %s_partial(); break;\n" % ("STATE_RESET", state))
+ emit(f, DO_EXEC_PARTIAL_EPILOG % d)
+
+ emit(f, DISASM_PROLOG % d)
+ for n, state in enumerate(states):
+ if state == ".": continue
+ if n == MAX_STATES - 1: break
+ tokens = state.split("_")
+ opc = tokens[0]
+ mode = tokens[-1]
+ extra = "0"
+ if opc in ["jsr", "bsr"]:
+ extra = "DASMFLAG_STEP_OVER"
+ elif opc in ["rts", "rti", "rtn"]:
+ extra = "DASMFLAG_STEP_OUT"
+ emit(f, '\t{ "%s", DASM_%s, %s },\n' % (opc, mode, extra))
+ emit(f, DISASM_EPILOG % d)
+
+def save(fname, device, opcodes, states):
+ logging.info("saving: %s", fname)
+ try:
+ f = open(fname, "w")
+ except Exception, err:
+ logging.error("cannot write file %s [%s]", fname, err)
+ sys.exit(1)
+ save_opcodes(f,device, opcodes)
+ emit(f, "\n")
+ save_tables(f, device, states)
+ f.close()
+
+
+def main(argv):
+ debug = True
+ logformat=("%(levelname)s:"
+ "%(module)s:"
+ "%(lineno)d:"
+ "%(threadName)s:"
+ "%(message)s")
+ if debug:
+ logging.basicConfig(level=logging.INFO, format=logformat)
+ else:
+ logging.basicConfig(level=logging.WARNING, format=logformat)
+
+
+ if len(argv) != 5:
+ print USAGE % argv[0]
+ return 1
+
+ device_name = argv[1]
+
+ opcodes = []
+ if argv[2] != "-":
+ opcodes = load_opcodes(argv[2])
+ logging.info("found %d opcodes", len(opcodes))
+ else:
+ logging.info("skipping opcode reading")
+
+
+ states = load_disp(argv[3])
+ logging.info("loaded %s states", len(states))
+ assert len(states) == MAX_STATES
+
+ save(argv[4], device_name, opcodes, states)
+
+
+# ======================================================================
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
+