mame/src/emu/cpu/m6502/m6502make.py
2015-07-30 11:44:43 +02:00

281 lines
6.4 KiB
Python
Executable File

#!/usr/bin/python
from __future__ import print_function
USAGE = """
Usage:
%s device_name {opc.lst|-} disp.lst device.inc
"""
import sys
import logging
MAX_STATES = 0
def load_opcodes(fname):
"""Load opcodes from .lst file"""
opcodes = []
logging.info("load_opcodes: %s", fname)
try:
f = open(fname, "rU")
except Exception:
err = sys.exc_info()[1]
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, "rU")
except Exception:
err = sys.exc_info()[1]
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(text, file=f)
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[0x%(disasm_count)x] = {
"""
DISASM_EPILOG="""\
};
"""
def save_tables(f, device, states):
total_states = len(states)
d = { "device": device,
"disasm_count": total_states-1
}
emit(f, DO_EXEC_FULL_PROLOG % d)
for n, state in enumerate(states):
if state == ".": continue
if n < total_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 < total_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 == total_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 = sys.exc_info()[1]
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 = False
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) & 0xff) == 1
save(argv[4], device_name, opcodes, states)
# ======================================================================
if __name__ == "__main__":
sys.exit(main(sys.argv))