522d96501184bd9cb42b050253a5e39b4e638713
[openpower-isa.git] / src / openpower / insndb / db.py
1 import argparse
2 import contextlib
3 import os
4 import types
5
6 from openpower.decoder.power_enums import (
7 find_wiki_dir,
8 )
9 from openpower.insndb.core import (
10 Database,
11 Handler,
12 Matcher,
13 visit,
14 )
15
16
17 class Instruction(str):
18 def __new__(cls, string):
19 svp64 = False
20 if string.startswith("sv."):
21 string = string[len("sv."):]
22 svp64 = True
23 self = super().__new__(cls, string)
24 self.__svp64 = svp64
25 return self
26
27 @property
28 def svp64(self):
29 return self.__svp64
30
31
32 class SVP64Instruction(Instruction):
33 def __new__(cls, string):
34 self = super().__new__(cls, string)
35 if not self.svp64:
36 raise ValueError("illegal SVP64 instruction")
37 return self
38
39
40 class ListHandler(Handler):
41 @contextlib.contextmanager
42 def Record(self, node, depth):
43 print(node.name)
44 yield node
45
46
47 class InstructionMatcher(Matcher):
48 def Record(self, node, depth):
49 return (node.name == self["insn"])
50
51
52 class SVP64InstructionMatcher(InstructionMatcher):
53 pass
54
55
56 class OpcodesHandler(Handler):
57 @contextlib.contextmanager
58 def Record(self, node, depth):
59 for opcode in node.opcodes:
60 print(opcode)
61 yield node
62
63
64 class OperandsHandler(Handler):
65 @contextlib.contextmanager
66 def Record(self, node, depth):
67 for operand in node.dynamic_operands:
68 print(operand.name, ",".join(map(str, operand.span)))
69 for operand in node.static_operands:
70 if operand.name not in ("PO", "XO"):
71 desc = f"{operand.name}={operand.value}"
72 print(desc, ",".join(map(str, operand.span)))
73 yield node
74
75
76 class PCodeHandler(Handler):
77 @contextlib.contextmanager
78 def Record(self, node, depth):
79 for line in node.pcode:
80 print(line)
81 yield node
82
83
84 class ExtrasHandler(Handler):
85 @contextlib.contextmanager
86 def Extra(self, node, depth):
87 print(node.name)
88 print(" sel", node.sel)
89 print(" reg", node.reg)
90 print(" seltype", node.seltype)
91 print(" idx", node.idx)
92 yield node
93
94
95 def main():
96 commands = {
97 "list": (
98 ListHandler,
99 Matcher,
100 "list available instructions",
101 ),
102 "opcodes": (
103 OpcodesHandler,
104 InstructionMatcher,
105 "print instruction opcodes",
106 ),
107 "operands": (
108 OperandsHandler,
109 InstructionMatcher,
110 "print instruction operands",
111 ),
112 "pcode": (
113 PCodeHandler,
114 InstructionMatcher,
115 "print instruction pseudocode",
116 ),
117 "extras": (
118 ExtrasHandler,
119 InstructionMatcher,
120 "print instruction extras (SVP64)",
121 ),
122 }
123
124 main_parser = argparse.ArgumentParser()
125 main_parser.add_argument("-l", "--log",
126 help="activate logging",
127 action="store_true",
128 default=False)
129 main_subparser = main_parser.add_subparsers(dest="command", required=True)
130
131 for (command, (handler, matcher, help)) in commands.items():
132 parser = main_subparser.add_parser(command, help=help)
133 if issubclass(matcher, InstructionMatcher):
134 if issubclass(matcher, SVP64InstructionMatcher):
135 arg_cls = SVP64Instruction
136 else:
137 arg_cls = Instruction
138 parser.add_argument("insn", type=arg_cls,
139 metavar="INSN", help="instruction")
140
141 args = vars(main_parser.parse_args())
142 command = args.pop("command")
143 log = args.pop("log")
144 if not log:
145 os.environ["SILENCELOG"] = "true"
146 handler = commands[command][0](**args)
147 matcher = commands[command][1](**args)
148
149 db = Database(find_wiki_dir())
150 visit(handler=handler, matcher=matcher, node=db)
151
152
153 if __name__ == "__main__":
154 main()