X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fopenpower%2Finsndb%2Fdb.py;h=a5210f087c85f63ead87622ac161fec19554ffd2;hb=61cc08f2d11fce0989db4fb4d502e14efc56d80a;hp=753ab626ab00e48ae5cd828f15bce7e1355d8d92;hpb=d403ecea8eca44b2a2a8df36ce4c5ffae3ac3b84;p=openpower-isa.git diff --git a/src/openpower/insndb/db.py b/src/openpower/insndb/db.py index 753ab626..a5210f08 100644 --- a/src/openpower/insndb/db.py +++ b/src/openpower/insndb/db.py @@ -1,56 +1,154 @@ import argparse import contextlib -import sys +import os +import types from openpower.decoder.power_enums import ( find_wiki_dir, ) -from openpower.insndb.types import ( +from openpower.insndb.core import ( Database, + Extra, + Record, + Records, Visitor, + visit, + visitormethod, ) +class Instruction(str): + def __new__(cls, string): + svp64 = False + if string.startswith("sv."): + string = string[len("sv."):] + svp64 = True + self = super().__new__(cls, string) + self.__svp64 = svp64 + return self + + @property + def svp64(self): + return self.__svp64 + + +class SVP64Instruction(Instruction): + def __new__(cls, string): + self = super().__new__(cls, string) + if not self.svp64: + raise ValueError("illegal SVP64 instruction") + return self + + +class ListVisitor(Visitor): + @visitormethod(Record) + def Record(self, node): + print(node.name) + yield node + + +class OpcodesVisitor(Visitor): + @visitormethod(Record) + def Record(self, node): + for opcode in node.opcodes: + print(opcode) + yield node + + +class OperandsVisitor(Visitor): + @visitormethod(Record) + def Record(self, node): + if isinstance(node, Record): + for operand in node.dynamic_operands: + print(operand.name, ",".join(map(str, operand.span))) + for operand in node.static_operands: + if operand.name not in ("PO", "XO"): + desc = f"{operand.name}={operand.value}" + print(desc, ",".join(map(str, operand.span))) + yield node + + +class PCodeVisitor(Visitor): + @visitormethod(Record) + def Record(self, node): + if isinstance(node, Record): + for line in node.pcode: + print(line) + yield node + + +class ExtrasVisitor(Visitor): + @visitormethod(Record) + def Record(self, node): + for (name, extra) in node.extras.items(): + print(name) + print(" sel", extra["sel"]) + print(" reg", extra["reg"]) + print(" seltype", extra["seltype"]) + print(" idx", extra["idx"]) + yield node + + def main(): - class GenericVisitor(Visitor): - def __init__(self, **_): - pass - - class ListVisitor(GenericVisitor): - @contextlib.contextmanager - def record(self, record): - print(record.name) - yield record - - class OpcodesVisitor(GenericVisitor): - def __init__(self, insn, **_): - self.__insn = insn - return super().__init__() - - @contextlib.contextmanager - def record(self, record): - if record.name == self.__insn: - for opcode in record.opcodes: - print(opcode) - yield record - - visitors = { - "list": ListVisitor, - "opcodes": OpcodesVisitor, + commands = { + "list": ( + ListVisitor, + "list available instructions", + ), + "opcodes": ( + OpcodesVisitor, + "print instruction opcodes", + ), + "operands": ( + OperandsVisitor, + "print instruction operands", + ), + "pcode": ( + PCodeVisitor, + "print instruction pseudocode", + ), + "extras": ( + ExtrasVisitor, + "print instruction extras (SVP64)", + ), } - parser = argparse.ArgumentParser() - subparser = parser.add_subparsers(dest="command", required=True) - parser_list = subparser.add_parser("list", - help="list all instructions") - parser_opcodes = subparser.add_parser("opcodes", - help="print instruction opcodes") - parser_opcodes.add_argument("insn", - metavar="INSN", - help="instruction") - - args = vars(parser.parse_args()) + + main_parser = argparse.ArgumentParser() + main_parser.add_argument("-l", "--log", + help="activate logging", + action="store_true", + default=False) + main_subparser = main_parser.add_subparsers(dest="command", required=True) + + for (command, (visitor, helper)) in commands.items(): + parser = main_subparser.add_parser(command, help=helper) + if command not in ("list",): + if command in ("extras",): + arg_cls = SVP64Instruction + else: + arg_cls = Instruction + parser.add_argument("insn", type=arg_cls, + metavar="INSN", help="instruction") + + args = vars(main_parser.parse_args()) command = args.pop("command") - visitor = visitors[command](**args) + log = args.pop("log") + if not log: + os.environ["SILENCELOG"] = "true" + visitor = commands[command][0]() db = Database(find_wiki_dir()) - db.visit(visitor=visitor) + records = next(db.walk(match=lambda node: isinstance(node, Records))) + if command in ("list",): + match = None + else: + insn = args.pop("insn") + def match(record): + return (isinstance(record, Record) and (record.name == insn)) + + for node in records.walk(match=match): + visit(visitor=visitor, node=node) + + +if __name__ == "__main__": + main()