summaryrefslogtreecommitdiff
path: root/z80count.py
diff options
context:
space:
mode:
authorJuan J. Martínez <jjm@usebox.net>2019-07-26 21:34:22 +0100
committerGitHub <noreply@github.com>2019-07-26 21:34:22 +0100
commit539ae1bb1c9bfcc3891531cf99d5e8d5a501aa8c (patch)
tree50c60cd06b9dfb5db0abc3c71a62a2cb35cd1e6d /z80count.py
parentfe518ecdf05f526fc3fe104dfa89dd54c3d15886 (diff)
parent9747ffb9dd71dbd7179052d9f4f6c80e45b36ec5 (diff)
downloadz80count-539ae1bb1c9bfcc3891531cf99d5e8d5a501aa8c.tar.gz
z80count-539ae1bb1c9bfcc3891531cf99d5e8d5a501aa8c.zip
Merge pull request #2 from patxoca/master
Optimize opcode lookup
Diffstat (limited to 'z80count.py')
-rwxr-xr-xz80count.py150
1 files changed, 91 insertions, 59 deletions
diff --git a/z80count.py b/z80count.py
index 6c569f7..a12143c 100755
--- a/z80count.py
+++ b/z80count.py
@@ -32,60 +32,47 @@ from os import path
OUR_COMMENT = re.compile(r"(\[[0-9.\s/]+\])")
-def z80count(line, table, total, total_cond, subt, update, tabstop=2, debug=False):
+def z80count(line, parser, total, total_cond, subt, update, tabstop=2, debug=False):
out = line.rstrip() + "\n"
- for entry in table:
- if entry["cregex"].search(line):
- cycles = entry["cycles"]
- if "/" in cycles:
- c = cycles.split("/")
- total += int(c[1])
- total_cond += total + int(c[0])
+ entry = parser.lookup(line)
+ if entry:
+ cycles = entry["cycles"]
+ if "/" in cycles:
+ c = cycles.split("/")
+ total += int(c[1])
+ total_cond += total + int(c[0])
+ else:
+ total += int(cycles)
+ total_cond = 0
+
+ line = line.rstrip().rsplit(";", 1)
+ comment = "; [%s" % cycles
+ if subt:
+ if total_cond:
+ comment += " .. %d/%d]" % (total_cond, total)
else:
- total += int(cycles)
- total_cond = 0
-
- line = line.rstrip().rsplit(";", 1)
- comment = "; [%s" % cycles
- if subt:
- if total_cond:
- comment += " .. %d/%d]" % (total_cond, total)
- else:
- comment += " .. %d]" % total
- else:
- comment += "]"
- if debug:
- comment += " case{%s}" % entry["case"]
-
- if len(line) == 1:
- comment = "\t" * tabstop + comment
- out = line[0] + comment
- if len(line) > 1:
- if update:
- m = OUR_COMMENT.search(line[1])
- if m:
- line[1] = line[1].replace(m.group(0), "")
- out += " "
- out += line[1].lstrip()
- out += "\n"
- found = True
- break
+ comment += " .. %d]" % total
+ else:
+ comment += "]"
+ if debug:
+ comment += " case{%s}" % entry["case"]
+
+ if len(line) == 1:
+ comment = "\t" * tabstop + comment
+ out = line[0] + comment
+ if len(line) > 1:
+ if update:
+ m = OUR_COMMENT.search(line[1])
+ if m:
+ line[1] = line[1].replace(m.group(0), "")
+ out += " "
+ out += line[1].lstrip()
+ out += "\n"
return (out, total, total_cond)
-def init_table(table_file="z80table.json"):
- table_file = path.join(
- path.dirname(path.realpath(__file__)), table_file)
- with open(table_file, "rt") as fd:
- table = json.load(fd)
-
- for i in range(len(table)):
- table[i]["cregex"] = re.compile(table[i]["regex"] + r"\s?(;.*)?", re.I)
-
- return sorted(table, key=lambda o: o["w"])
-
-def main():
+def parse_command_line():
parser = argparse.ArgumentParser(
description='Z80 Cycle Count', epilog="Copyright (C) 2019 Juan J Martinez <jjm@usebox.net>")
@@ -101,24 +88,69 @@ def main():
help="Number of tabs for new comments", default=2)
parser.add_argument(
"infile", nargs="?", type=argparse.FileType('r'), default=sys.stdin,
- help="Input file")
+ help="Input file")
parser.add_argument(
"outfile", nargs="?", type=argparse.FileType('w'), default=sys.stdout,
- help="Output file")
- args = parser.parse_args()
+ help="Output file")
+
+ return parser.parse_args()
+
+
+class Parser(object):
+ """Simple parser based on a table of regexes.
+
+ """
+
+ # [label:] OPERATOR [OPERANDS] [; comment]
+ _LINE_RE = re.compile(r"^([\w]+:)?\s*(?P<operator>\w+)(\s+.*)?$")
+ def __init__(self):
+ self._table = self._load_table()
+
+ def lookup(self, line):
+ mnemo = self._extract_mnemonic(line)
+ if mnemo is None or mnemo not in self._table:
+ return None
+ for entry in self._table[mnemo]:
+ if "cregex" not in entry:
+ entry["cregex"] = re.compile(r"^\s*" + entry["regex"] + r"\s*(;.*)?$", re.I)
+ if entry["cregex"].search(line):
+ return entry
+ return None
+
+ @classmethod
+ def _load_table(cls):
+ table_file = path.join(path.dirname(path.realpath(__file__)), "z80table.json")
+ with open(table_file, "rt") as fd:
+ table = json.load(fd)
+
+ table.sort(key=lambda o: o["w"])
+ res = {}
+ for i in table:
+ mnemo = cls._extract_mnemonic(i["case"])
+ assert mnemo is not None
+ if mnemo not in res:
+ res[mnemo] = []
+ res[mnemo].append(i)
+ return res
+
+ @classmethod
+ def _extract_mnemonic(cls, line):
+ match = cls._LINE_RE.match(line)
+ if match:
+ return match.group("operator").upper()
+ return None
+
+
+def main():
+ args = parse_command_line()
in_f = args.infile
out_f = args.outfile
-
- table = init_table()
+ parser = Parser()
total = total_cond = 0
- while True:
- line = in_f.readline()
- if not line:
- break
-
+ for line in in_f:
output, total, total_cond = z80count(
- line, table, total, total_cond, args.subt, args.update, args.tabstop, args.debug)
+ line, parser, total, total_cond, args.subt, args.update, args.tabstop, args.debug)
out_f.write(output)