insndb/db: support extras command
[openpower-isa.git] / src / openpower / insndb / db.py
1 import argparse
2 import contextlib
3 import os
4
5 from openpower.decoder.power_enums import (
6 find_wiki_dir,
7 )
8 from openpower.insndb.core import (
9 Database,
10 Visitor,
11 )
12
13
14 class Instruction(str):
15 def __new__(cls, string):
16 svp64 = False
17 if string.startswith("sv."):
18 string = string[len("sv."):]
19 svp64 = True
20 self = super().__new__(cls, string)
21 self.__svp64 = svp64
22 return self
23
24 @property
25 def svp64(self):
26 return self.__svp64
27
28
29 class BaseVisitor(Visitor):
30 def __init__(self, **_):
31 pass
32
33
34 class ListVisitor(BaseVisitor):
35 @contextlib.contextmanager
36 def record(self, record):
37 print(record.name)
38 yield record
39
40
41 class InstructionVisitor(BaseVisitor):
42 def __init__(self, insn, **_):
43 self.__insn = insn
44 return super().__init__()
45
46 def concrete_record(self, record):
47 raise NotImplementedError
48
49 @contextlib.contextmanager
50 def record(self, record):
51 if record.name == self.__insn:
52 self.concrete_record(record=record)
53 yield record
54
55
56 class OpcodesVisitor(InstructionVisitor):
57 def concrete_record(self, record):
58 for opcode in record.opcodes:
59 print(opcode)
60
61
62 class OperandsVisitor(InstructionVisitor):
63 def concrete_record(self, record):
64 for operand in record.dynamic_operands:
65 print(operand.name)
66 for operand in record.static_operands:
67 if operand.name not in ("PO", "XO"):
68 print(operand.name, operand.value, sep="=")
69
70
71 class PCodeVisitor(InstructionVisitor):
72 def concrete_record(self, record):
73 for line in record.pcode:
74 print(line)
75
76
77 class ExtrasVisitor(InstructionVisitor):
78 def concrete_record(self, record):
79 for (key, fields) in record.extras.items():
80 print(key)
81 for (field_key, field_value) in fields.items():
82 print(f" {field_key} {field_value}")
83
84
85 def main():
86 commands = {
87 "list": (
88 ListVisitor,
89 "list available instructions",
90 ),
91 "opcodes": (
92 OpcodesVisitor,
93 "print instruction opcodes",
94 ),
95 "operands": (
96 OperandsVisitor,
97 "print instruction operands",
98 ),
99 "pcode": (
100 PCodeVisitor,
101 "print instruction pseudocode",
102 ),
103 "extras": (
104 ExtrasVisitor,
105 "print instruction extras (SVP64)",
106 ),
107 }
108
109 main_parser = argparse.ArgumentParser()
110 main_parser.add_argument("-l", "--log",
111 help="activate logging",
112 action="store_true",
113 default=False)
114 main_subparser = main_parser.add_subparsers(dest="command", required=True)
115
116 for (command, (visitor, help)) in commands.items():
117 parser = main_subparser.add_parser(command, help=help)
118 if issubclass(visitor, InstructionVisitor):
119 parser.add_argument("insn", type=Instruction,
120 metavar="INSN", help="instruction")
121
122 args = vars(main_parser.parse_args())
123 command = args.pop("command")
124 log = args.pop("log")
125 if not log:
126 os.environ["SILENCELOG"] = "true"
127 visitor = commands[command][0](**args)
128
129 db = Database(find_wiki_dir())
130 db.visit(visitor=visitor)
131
132
133 if __name__ == "__main__":
134 main()