diff options
author | Juan J. MartÃnez <jjm@usebox.net> | 2019-07-26 21:34:22 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-26 21:34:22 +0100 |
commit | 539ae1bb1c9bfcc3891531cf99d5e8d5a501aa8c (patch) | |
tree | 50c60cd06b9dfb5db0abc3c71a62a2cb35cd1e6d /z80count.py | |
parent | fe518ecdf05f526fc3fe104dfa89dd54c3d15886 (diff) | |
parent | 9747ffb9dd71dbd7179052d9f4f6c80e45b36ec5 (diff) | |
download | z80count-539ae1bb1c9bfcc3891531cf99d5e8d5a501aa8c.tar.gz z80count-539ae1bb1c9bfcc3891531cf99d5e8d5a501aa8c.zip |
Merge pull request #2 from patxoca/master
Optimize opcode lookup
Diffstat (limited to 'z80count.py')
-rwxr-xr-x | z80count.py | 150 |
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) |