pysvp64db: fix traversal
[openpower-isa.git] / src / openpower / insndb / db.py
1 import argparse
2 import contextlib
3 import os
4
5 import mdis.dispatcher
6 import mdis.visitor
7 import mdis.walker
8
9 from openpower.decoder.power_enums import (
10 find_wiki_dir,
11 )
12 from openpower.insndb.core import (
13 Database,
14 PCode,
15 Operands,
16 Record,
17 Section,
18 SVP64Record,
19 Walker,
20 )
21 from openpower.decoder.power_enums import (
22 SVEType,
23 SVPType,
24 SVExtra,
25 In1Sel,
26 In2Sel,
27 In3Sel,
28 OutSel,
29 CRInSel,
30 CRIn2Sel,
31 CROutSel,
32 )
33
34
35 class Instruction(str):
36 def __new__(cls, string):
37 svp64 = False
38 if string.startswith("sv."):
39 string = string[len("sv."):]
40 svp64 = True
41 self = super().__new__(cls, string)
42 self.__svp64 = svp64
43 return self
44
45 @property
46 def svp64(self):
47 return self.__svp64
48
49
50 class SVP64Instruction(Instruction):
51 def __new__(cls, string):
52 self = super().__new__(cls, string)
53 if not self.svp64:
54 raise ValueError("illegal SVP64 instruction")
55 return self
56
57
58 class ListVisitor(mdis.visitor.ContextVisitor):
59 @mdis.dispatcher.Hook(Record)
60 @contextlib.contextmanager
61 def dispatch_record(self, node):
62 print(node.name)
63 yield node
64
65
66 # No use other than checking issubclass and adding an argument.
67 class InstructionVisitor(mdis.visitor.ContextVisitor):
68 pass
69
70 class SVP64InstructionVisitor(InstructionVisitor):
71 pass
72
73
74 class OpcodesVisitor(InstructionVisitor):
75 @mdis.dispatcher.Hook(Record)
76 @contextlib.contextmanager
77 def dispatch_record(self, node):
78 for opcode in node.opcodes:
79 print(opcode)
80 yield node
81
82
83 class OperandsVisitor(InstructionVisitor):
84 def __init__(self):
85 self.__record = None
86 return super().__init__()
87
88 @mdis.dispatcher.Hook(Record)
89 @contextlib.contextmanager
90 def dispatch_record(self, node):
91 self.__record = node
92 yield node
93
94 @mdis.dispatcher.Hook(Operands)
95 @contextlib.contextmanager
96 def dispatch_operands(self, node):
97 for (cls, kwargs) in node:
98 operand = cls(record=self.__record, **kwargs)
99 print(operand.name, ", ".join(map(str, operand.span)))
100 yield node
101
102
103 class PCodeVisitor(InstructionVisitor):
104 @mdis.dispatcher.Hook(PCode)
105 @contextlib.contextmanager
106 def dispatch_record(self, node):
107 for line in node:
108 print(line)
109 yield node
110
111
112 class SelectorsVisitor(InstructionVisitor):
113 @mdis.dispatcher.Hook(
114 In1Sel, In2Sel, In3Sel, CRInSel, CRIn2Sel,
115 OutSel, CROutSel,
116 )
117 @contextlib.contextmanager
118 def dispatch_selector(self, node):
119 typename = node.__class__.__name__
120 typename = typename.replace("CR", "CR_")
121 typename = typename.replace("Sel", "")
122 typename = typename.lower()
123 print(typename, node)
124 yield node
125
126
127 class ETypeVisitor(SVP64InstructionVisitor):
128 @mdis.dispatcher.Hook(SVEType)
129 @contextlib.contextmanager
130 def dispatch_ptype(self, node):
131 print(node)
132 yield node
133
134
135 class PTypeVisitor(SVP64InstructionVisitor):
136 @mdis.dispatcher.Hook(SVPType)
137 @contextlib.contextmanager
138 def dispatch_ptype(self, node):
139 print(node)
140 yield node
141
142
143 class SectionVisitor(InstructionVisitor):
144 @mdis.dispatcher.Hook(Section.Path)
145 @contextlib.contextmanager
146 def dispatch_path(self, node):
147 print("path", node)
148 yield node
149
150 @mdis.dispatcher.Hook(Section.BitSel)
151 @contextlib.contextmanager
152 def dispatch_bitsel(self, node):
153 print("bitsel", node)
154 yield node
155
156 @mdis.dispatcher.Hook(Section.Suffix)
157 @contextlib.contextmanager
158 def dispatch_suffix(self, node):
159 print("suffix", node)
160 yield node
161
162 @mdis.dispatcher.Hook(Section.Mode)
163 @contextlib.contextmanager
164 def dispatch_mode(self, node):
165 print("mode", node)
166 yield node
167
168 @mdis.dispatcher.Hook(Section.Opcode)
169 @contextlib.contextmanager
170 def dispatch_opcode(self, node):
171 print("opcode", int(node))
172 yield node
173
174 @mdis.dispatcher.Hook(Section.Priority)
175 @contextlib.contextmanager
176 def dispatch_priority(self, node):
177 print("priority", node)
178 yield node
179
180
181 class ExtrasVisitor(SVP64InstructionVisitor, SelectorsVisitor):
182 @mdis.dispatcher.Hook(SVP64Record.ExtraMap)
183 @contextlib.contextmanager
184 def dispatch_extramap(self, node):
185 self.__index = 0
186 yield node
187
188 @mdis.dispatcher.Hook(SVP64Record.ExtraMap.Extra)
189 @contextlib.contextmanager
190 def dispatch_extramap_extra(self, node):
191 yield node
192 self.__index += 1
193
194 @mdis.dispatcher.Hook(SVP64Record.ExtraMap.Extra.Entry)
195 @contextlib.contextmanager
196 def dispatch_extramap_extra_entry(self, node):
197 idxmap = (
198 SVExtra.Idx0,
199 SVExtra.Idx1,
200 SVExtra.Idx2,
201 SVExtra.Idx3,
202 )
203 print(idxmap[self.__index], node)
204 yield node
205
206
207 def main():
208 commands = {
209 "list": (
210 ListVisitor,
211 "list available instructions",
212 ),
213 "opcodes": (
214 OpcodesVisitor,
215 "print instruction opcodes",
216 ),
217 "operands": (
218 OperandsVisitor,
219 "print instruction operands",
220 ),
221 "pcode": (
222 PCodeVisitor,
223 "print instruction pseudocode",
224 ),
225 "selectors": (
226 SelectorsVisitor,
227 "print instruction selectors",
228 ),
229 "etype": (
230 ETypeVisitor,
231 "print instruction etype",
232 ),
233 "ptype": (
234 PTypeVisitor,
235 "print instruction ptype",
236 ),
237 "section": (
238 SectionVisitor,
239 "print instruction section",
240 ),
241 "extras": (
242 ExtrasVisitor,
243 "print instruction extras (SVP64)",
244 ),
245 }
246
247 main_parser = argparse.ArgumentParser()
248 main_parser.add_argument("-l", "--log",
249 help="activate logging",
250 action="store_true",
251 default=False)
252 main_subparser = main_parser.add_subparsers(dest="command", required=True)
253
254 for (command, (visitor, helper)) in commands.items():
255 parser = main_subparser.add_parser(command, help=helper)
256 if issubclass(visitor, InstructionVisitor):
257 if issubclass(visitor, SVP64InstructionVisitor):
258 arg_cls = SVP64Instruction
259 else:
260 arg_cls = Instruction
261 parser.add_argument("insn", type=arg_cls,
262 metavar="INSN", help="instruction")
263
264 args = vars(main_parser.parse_args())
265 command = args.pop("command")
266 log = args.pop("log")
267 if not log:
268 os.environ["SILENCELOG"] = "true"
269 visitor = commands[command][0]()
270
271 db = Database(find_wiki_dir())
272 if not isinstance(visitor, InstructionVisitor):
273 root = db
274 else:
275 root = db[args.pop("insn")]
276
277 def traverse(root, visitor, walker):
278 with visitor(root):
279 for node in walker(root):
280 traverse(root=node, visitor=visitor, walker=walker)
281
282 traverse(root=root, visitor=visitor, walker=Walker())
283
284
285 if __name__ == "__main__":
286 main()