707bdaaf1f8c24c51b680048024cd97c95bfcab4
[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 SVP64Instruction(Instruction):
30 def __new__(cls, string):
31 self = super().__new__(cls, string)
32 if not self.svp64:
33 raise ValueError("illegal SVP64 instruction")
34 return self
35
36
37 class BaseVisitor(Visitor):
38 def __init__(self, **_):
39 pass
40
41
42 class ListVisitor(BaseVisitor):
43 @contextlib.contextmanager
44 def record(self, record):
45 print(record.name)
46 yield record
47
48
49 class InstructionVisitor(BaseVisitor):
50 def __init__(self, insn, **_):
51 self.__insn = insn
52 return super().__init__()
53
54 def concrete_record(self, record):
55 raise NotImplementedError
56
57 @contextlib.contextmanager
58 def record(self, record):
59 if record.name == self.__insn:
60 self.concrete_record(record=record)
61 yield record
62
63
64 class SVP64InstructionVisitor(InstructionVisitor):
65 pass
66
67
68 class OpcodesVisitor(InstructionVisitor):
69 def concrete_record(self, record):
70 for opcode in record.opcodes:
71 print(opcode)
72
73
74 class OperandsVisitor(InstructionVisitor):
75 def concrete_record(self, record):
76 for operand in record.dynamic_operands:
77 print(operand.name)
78 for operand in record.static_operands:
79 if operand.name not in ("PO", "XO"):
80 print(operand.name, operand.value, sep="=")
81
82
83 class PCodeVisitor(InstructionVisitor):
84 def concrete_record(self, record):
85 for line in record.pcode:
86 print(line)
87
88
89 class ExtrasVisitor(SVP64InstructionVisitor):
90 def concrete_record(self, record):
91 for (key, fields) in record.extras.items():
92 print(key)
93 for (field_key, field_value) in fields.items():
94 print(f" {field_key} {field_value}")
95
96
97 def main():
98 commands = {
99 "list": (
100 ListVisitor,
101 "list available instructions",
102 ),
103 "opcodes": (
104 OpcodesVisitor,
105 "print instruction opcodes",
106 ),
107 "operands": (
108 OperandsVisitor,
109 "print instruction operands",
110 ),
111 "pcode": (
112 PCodeVisitor,
113 "print instruction pseudocode",
114 ),
115 "extras": (
116 ExtrasVisitor,
117 "print instruction extras (SVP64)",
118 ),
119 }
120
121 main_parser = argparse.ArgumentParser()
122 main_parser.add_argument("-l", "--log",
123 help="activate logging",
124 action="store_true",
125 default=False)
126 main_subparser = main_parser.add_subparsers(dest="command", required=True)
127
128 for (command, (visitor, help)) in commands.items():
129 parser = main_subparser.add_parser(command, help=help)
130 if issubclass(visitor, InstructionVisitor):
131 if issubclass(visitor, SVP64InstructionVisitor):
132 arg_cls = SVP64Instruction
133 else:
134 arg_cls = Instruction
135 parser.add_argument("insn", type=arg_cls,
136 metavar="INSN", help="instruction")
137
138 args = vars(main_parser.parse_args())
139 command = args.pop("command")
140 log = args.pop("log")
141 if not log:
142 os.environ["SILENCELOG"] = "true"
143 visitor = commands[command][0](**args)
144
145 db = Database(find_wiki_dir())
146 db.visit(visitor=visitor)
147
148
149 if __name__ == "__main__":
150 main()