mame/src/emu/cpu/h8/h8make.py
Olivier Galibert bb221d260a h8_sci: Implement sync-start [O. Galibert]
h8: Fix problem in the sleep instruction [O. Galibert]
at45dbxx: Fix communications [O. Galibert]
2014-04-26 10:31:13 +00:00

470 lines
17 KiB
Python

#!/usr/bin/python
USAGE = """
Usage:
%s h8.lst <type> h8.inc (type = o/h/s20/s26)
"""
import sys
def name_to_type(name):
if(name == "o"):
return 0
if(name == "h"):
return 1
if(name == "s20"):
return 2
if(name == "s26"):
return 3
print "Unknown chip type name %s" % name
sys.exit(1)
def type_to_device(dtype):
if(dtype == 0):
return "h8_device"
if(dtype == 1):
return "h8h_device"
if(dtype == 2):
return "h8s2000_device"
return "h8s2600_device"
def hexsplit(str):
res = []
for i in range(0, len(str), 2):
res.append(int(str[i:i+2], 16))
return res
def has_memory(ins):
for s in ["read", "write", "sp_push", "sp_pop", "sp32_push", "sp32_pop", "fetch(", "prefetch_start(", "prefetch(", "prefetch_noirq("]:
if s in ins:
return True
return False
def has_eat(ins):
if "eat-all-cycles" in ins:
return True
return False
def save_full_one(f, t, name, source):
print >>f, "void %s::%s_full()" % (t, name)
print >>f, "{"
substate = 1
for line in source:
if has_memory(line):
print >>f, "\tif(icount <= bcount) { inst_substate = %d; return; }" % substate
print >>f, line
substate = substate + 1
elif has_eat(line):
print >>f, "\tif(icount) icount = bcount; inst_substate = %d; return;" % substate
substate = substate + 1
else:
print >>f, line
print >>f, "}"
print >>f
def save_partial_one(f, t, name, source):
print >>f, "void %s::%s_partial()" % (t, name)
print >>f, "{"
print >>f, "switch(inst_substate) {"
print >>f, "case 0:"
substate = 1
for line in source:
if has_memory(line):
print >>f, "\tif(icount <= bcount) { inst_substate = %d; return; }" % substate
print >>f, "case %d:;" % substate
print >>f, line
substate = substate + 1
elif has_eat(line):
print >>f, "\tif(icount) icount = bcount; inst_substate = %d; return;" % substate
print >>f, "case %d:;" % substate
substate = substate + 1
else:
print >>f, line
print >>f, "\tbreak;"
print >>f, "}"
print >>f, "\tinst_substate = 0;"
print >>f, "}"
print >>f
class Hash:
def __init__(self, premask):
self.mask = 0x00
self.enabled = False
self.premask = premask
self.d = {}
def get(self, val, premask):
if val in self.d:
h = self.d[val]
if h.premask != premask:
print "Premask conflict"
sys.exit(1)
return h
h = Hash(premask)
self.d[val] = h
return h
def set(self, val, opc):
if val in self.d:
print "Collision on %s" % opc.description()
sys.exit(1)
self.d[val] = opc
class Opcode:
def __init__(self, val, mask, skip, name, am1, am2, otype, dtype):
self.name = name
self.val = hexsplit(val)
self.mask = hexsplit(mask)
self.skip = int(skip)
self.am1 = am1
self.am2 = am2
self.source = []
self.otype = otype
self.enabled = otype == -1 or (otype == 0 and dtype == 0) or (otype != 0 and dtype >= otype)
self.needed = self.enabled and (otype == dtype or (otype == -1 and dtype == 0))
if dtype == 0 and (am1 == "r16l" or am2 == "r16l"):
self.mask[len(self.mask)-1] = self.mask[len(self.mask)-1] | 0x08
if dtype == 0 and (am1 == "r16h" or am2 == "r16h"):
self.mask[len(self.mask)-1] = self.mask[len(self.mask)-1] | 0x80
extra_words = 0
if (am1 == "abs16" or am2 == "abs16" or am1 == "abs16e" or am1 == "abs24e") and self.skip == 0:
extra_words = extra_words + 1
if (am1 == "abs32" or am2 == "abs32") and self.skip == 0:
extra_words = extra_words + 2
if am1 == "imm16" or am1 == "rel16" or am1 == "r16d16h" or am2 == "r16d16h" or am1 == "r32d16h" or am2 == "r32d16h":
extra_words = extra_words + 1
if am1 == "imm32" or am1 == "r32d32hh" or am2 == "r32d32hh":
extra_words = extra_words + 2
self.extra_words = extra_words
base_offset = len(self.val)/2 + self.skip
for i in range(0, extra_words):
self.source.append("\tfetch(%d);\n" % (i+base_offset));
def description():
return "%s %s %s" % (self.name, self.am1, self.am2)
def add_source_line(self, line):
self.source.append(line)
def is_dispatch(self):
return False
def function_name(self):
n = self.name.replace(".", "_")
if self.am1 != "-":
n = n + "_" + self.am1
if self.am2 != "-":
n = n + "_" + self.am2
return n
def save_dasm(self, f):
if len(self.mask) == 2:
mask = (self.mask[0] << 8) | self.mask[1]
val = (self.val[0] << 8) | self.val[1]
mask2 = 0
val2 = 0
slot = 0
elif len(self.mask) == 4:
mask = (self.mask[0] << 24) | (self.mask[1] << 16) | (self.mask[2] << 8) | self.mask[3]
val = (self.val[0] << 24) | (self.val[1] << 16) | (self.val[2] << 8) | self.val[3]
mask2 = 0
val2 = 0
slot = self.skip + 1
else:
mask = (self.mask[2] << 24) | (self.mask[3] << 16) | (self.mask[4] << 8) | self.mask[5]
val = (self.val[2] << 24) | (self.val[3] << 16) | (self.val[4] << 8) | self.val[5]
mask2 = (self.mask[0] << 8) | self.mask[1]
val2 = (self.val[0] << 8) | self.val[1]
slot = 4
size = len(self.val) + 2*self.skip + 2*self.extra_words
if self.name == "jsr" or self.name == "bsr":
flags = "%d | DASMFLAG_STEP_OVER" % size
elif self.name == "rts" or self.name == "rte":
flags = "%d | DASMFLAG_STEP_OUT" % size
else:
flags = "%d" % size
print >>f, "\t{ %d, 0x%08x, 0x%08x, 0x%04x, 0x%04x, \"%s\", DASM_%s, DASM_%s, %s }, // %s" % ( slot, val, mask, val2, mask2, self.name, self.am1 if self.am1 != "-" else "none", self.am2 if self.am2 != "-" else "none", flags, "needed" if self.needed else "inherited")
class Special:
def __init__(self, val, name, otype, dtype):
self.name = name
self.val = int(val, 16)
self.enabled = otype == -1 or (otype == 0 and dtype == 0) or (otype != 0 and dtype >= otype)
self.needed = otype == dtype or (otype == -1 and dtype == 0)
self.source = []
def add_source_line(self, line):
self.source.append(line)
class Macro:
def __init__(self, tokens):
self.name = tokens[1]
self.params = []
for i in range(2, len(tokens)):
self.params.append(tokens[i])
self.source = []
def add_source_line(self, line):
self.source.append(line)
def apply(self, target, tokens):
values = []
if len(self.params) > 1:
for i in range(0, len(self.params)-1):
values.append(tokens[i+1])
lval = ""
for i in range(len(self.params)-1, len(tokens)-1):
if lval != "":
lval = lval + " "
lval = lval + tokens[i+1]
values.append(lval)
for i in range(0, len(self.source)):
line = self.source[i]
for i in range(0, len(self.params)):
line = line.replace(self.params[i], values[i])
target.add_source_line(line)
class DispatchStep:
def __init__(self, id, pos, opc):
self.id = id
self.pos = pos
self.name = ""
self.enabled = False
self.mask = opc.mask[pos-1]
for i in range(0, pos):
self.name = self.name + ("%02x" % opc.val[i])
if pos == 2:
self.skip = opc.skip
else:
self.skip = 0
def is_dispatch(self):
return True
def source(self):
start = self.pos / 2
end = start + self.skip
s = []
for i in range(start, end+1):
s.append("\tIR[%d] = fetch();" % i)
s.append("\tinst_state = 0x%x0000 | IR[%d];" % (self.id, end))
return s;
class OpcodeList:
def __init__(self, fname, dtype):
self.opcode_info = []
self.dispatch_info = []
self.states_info = []
self.dispatch = {}
self.macros = {}
try:
f = open(fname, "r")
except Exception, err:
print "Cannot read opcodes file %s [%s]" % (fname, err)
sys.exit(1)
opc = None
for line in f:
if line.startswith("#"):
continue
line = line.rstrip()
if not line:
continue
if line.startswith(" ") or line.startswith("\t"):
if inf != None:
# append instruction to last opcode, maybe expand a macro
tokens = line.split()
if tokens[0] in self.macros:
self.macros[tokens[0]].apply(inf, tokens)
else:
inf.add_source_line(line)
else:
# New opcode
tokens = line.split()
if tokens[0] == "macro":
inf = Macro(tokens)
self.macros[inf.name] = inf
elif len(tokens) == 2 or len(tokens) == 3:
if len(tokens) >= 3:
otype = name_to_type(tokens[2])
else:
otype = -1
inf = Special(tokens[0], tokens[1], otype, dtype)
self.states_info.append(inf)
else:
if len(tokens) >= 7:
otype = name_to_type(tokens[6])
else:
otype = -1
if otype == -1 or dtype == 0 or (otype != 0 and dtype != 0):
inf = Opcode(tokens[0], tokens[1], tokens[2], tokens[3], tokens[4], tokens[5], otype, dtype)
self.opcode_info.append(inf)
else:
inf = None
def get(self, i):
if i in self.dispatch:
return self.dispatch[i]
h = Hash(0)
self.dispatch[i] = h
return h
def build_dispatch(self):
for opc in self.opcode_info:
for i in range(0, len(opc.val)):
v = opc.val[i]
if i == 0:
h = self.get(0)
if opc.enabled:
h.mask = h.mask | opc.mask[i]
h.enabled = True
if (i & 1) == 0:
h = h.get(v, opc.mask[i])
elif i == len(opc.val)-1:
if opc.enabled:
h.set(v, opc)
else:
if v in h.d:
d = h.d[v]
if not d.is_dispatch():
print "Collision on %s" % opc.description()
sys.exit(1)
if opc.enabled:
d.enabled = True
h = self.get(d.id)
else:
d = DispatchStep(len(self.dispatch_info)+2, i+1, opc)
self.dispatch_info.append(d)
if opc.enabled:
d.enabled = True
h.set(v, d)
h = self.get(d.id)
def save_dasm(self, f, dname):
print >>f, "const %s::disasm_entry %s::disasm_entries[] = {" % (dname, dname)
for opc in self.opcode_info:
if opc.enabled:
opc.save_dasm(f)
print >>f, "\t{ 0, 0, 0, 0, 0, \"illegal\", 0, 0, 2 },"
print >>f, "};"
print >>f
def save_opcodes(self, f, t):
for opc in self.opcode_info:
if opc.needed:
save_full_one(f, t, opc.function_name(), opc.source)
save_partial_one(f, t, opc.function_name(), opc.source)
for sta in self.states_info:
if sta.needed:
save_full_one(f, t, "state_" + sta.name, sta.source)
save_partial_one(f, t, "state_" + sta.name, sta.source)
def save_dispatch(self, f, t):
for dsp in self.dispatch_info:
save_full_one(f, t, "dispatch_" + dsp.name, dsp.source())
save_partial_one(f, t, "dispatch_" + dsp.name, dsp.source())
def save_exec(self, f, t, dtype, v):
print >>f, "void %s::do_exec_%s()" % (t, v)
print >>f, "{"
print >>f, "\tswitch(inst_state >> 16) {"
for i in range(0, len(self.dispatch_info)+2):
if i == 1:
print >>f, "\tcase 0x01: {"
print >>f, "\t\tswitch(inst_state & 0xffff) {"
for sta in self.states_info:
if sta.enabled:
print >>f, "\t\tcase 0x%02x: state_%s_%s(); break;" % (sta.val & 0xffff, sta.name, v)
print >>f, "\t\t}"
print >>f, "\t\tbreak;"
print >>f, "\t}"
else:
if i == 0 or self.dispatch_info[i-2].enabled:
print >>f, "\tcase 0x%02x: {" % i
h = self.get(i)
print >>f, "\t\tswitch((inst_state >> 8) & 0x%02x) {" % h.mask
for val, h2 in sorted(h.d.items()):
if h2.enabled:
fmask = h2.premask | (h.mask ^ 0xff)
c = ""
s = 0
while(s < 0x100):
c = c + "case 0x%02x: " % (val | s)
s = s + 1
while(s & fmask):
s = s + (s & fmask)
print >>f, "\t\t%s{" % c
if h2.mask == 0x00:
n = h2.d[0]
if n.is_dispatch():
print >>f, "\t\t\tdispatch_%s_%s();" % (n.name, v)
else:
print >>f, "\t\t\t%s_%s();" % (n.function_name(), v)
print >>f, "\t\t\tbreak;"
else:
print >>f, "\t\t\tswitch(inst_state & 0x%02x) {" % h2.mask
if i == 0:
mpos = 1
else:
mpos = self.dispatch_info[i-2].pos + 1
for val2, n in sorted(h2.d.items()):
if n.enabled:
fmask = h2.mask ^ 0xff
if n.is_dispatch():
fmask = fmask | n.mask
else:
fmask = fmask | n.mask[mpos]
c = ""
s = 0
while(s < 0x100):
c = c + "case 0x%02x: " % (val2 | s)
s = s + 1
while(s & fmask):
s = s + (s & fmask)
if n.is_dispatch():
print >>f, "\t\t\t%sdispatch_%s_%s(); break;" % (c, n.name, v)
else:
print >>f, "\t\t\t%s%s_%s(); break;" % (c, n.function_name(), v)
print >>f, "\t\t\tdefault: illegal(); break;"
print >>f, "\t\t\t}"
print >>f, "\t\t\tbreak;"
print >>f, "\t\t}"
print >>f, "\t\tdefault: illegal(); break;"
print >>f, "\t\t}"
print >>f, "\t\tbreak;"
print >>f, "\t}"
print >>f, "\t}"
print >>f, "}"
def main(argv):
if len(argv) != 4:
print USAGE % argv[0]
return 1
dtype = name_to_type(argv[2])
dname = type_to_device(dtype)
opcodes = OpcodeList(argv[1], dtype)
try:
f = open(argv[3], "w")
except Exception, err:
logging.error("cannot write file %s [%s]", fname, err)
sys.exit(1)
opcodes.build_dispatch()
opcodes.save_dasm(f, dname)
opcodes.save_opcodes(f, dname)
if dtype == 0:
opcodes.save_dispatch(f, dname)
opcodes.save_exec(f, dname, dtype, "full")
opcodes.save_exec(f, dname, dtype, "partial")
f.close()
# ======================================================================
if __name__ == "__main__":
sys.exit(main(sys.argv))