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()