pysvp64asm: clean import directives
[openpower-isa.git] / src / openpower / sv / trans / pysvp64dis.py
1 import argparse as _argparse
2 import enum as _enum
3 import functools as _functools
4 import sys as _sys
5
6 from openpower.decoder.power_enums import find_wiki_dir as _find_wiki_dir
7 from openpower.decoder.power_insn import Database as _Database
8 from openpower.decoder.selectable_int import SelectableInt as _SelectableInt
9 from openpower.decoder.isa.caller import (
10 SVP64PrefixFields as _SVP64PrefixFields,
11 SVP64RMFields as _SVP64RMFields,
12 )
13
14
15 class ByteOrder(_enum.Enum):
16 LITTLE = "little"
17 BIG = "big"
18
19 def __str__(self):
20 return self.name.lower()
21
22
23 DATABASE = _Database(_find_wiki_dir())
24
25
26 class Instruction(_SelectableInt):
27 def __init__(self, value, byteorder=ByteOrder.LITTLE, bits=32):
28 if isinstance(value, _SelectableInt):
29 value = value.value
30 elif isinstance(value, bytes):
31 value = int.from_bytes(value, byteorder=str(byteorder))
32
33 if not isinstance(value, int):
34 raise ValueError(value)
35 if not isinstance(bits, int) or (bits not in {32, 64}):
36 raise ValueError(bits)
37
38 return super().__init__(value=value, bits=bits)
39
40 def __repr__(self):
41 return f"{self.__class__.__name__}({self.value:08x})"
42
43 def disassemble(self):
44 if self.dbrecord is None:
45 yield f".long 0x{self.value:08x}"
46 else:
47 yield f".long 0x{self.value:08x} # {self.dbrecord.name}"
48
49 @property
50 def major(self):
51 return self[0:6]
52
53 @property
54 def dbrecord(self):
55 try:
56 return DATABASE[int(self)]
57 except KeyError:
58 return None
59
60
61 class PrefixedInstruction(Instruction):
62 def __init__(self, prefix, suffix, byteorder=ByteOrder.LITTLE):
63 insn = _functools.partial(Instruction, byteorder=byteorder)
64 (prefix, suffix) = map(insn, (prefix, suffix))
65 value = ((prefix.value << 32) | suffix.value)
66 return super().__init__(value=value, bits=64)
67
68 def __repr__(self):
69 return f"{self.__class__.__name__}({self.value:016x})"
70
71 def disassemble(self):
72 if self.dbrecord is None:
73 yield f".llong 0x{self.value:08x}"
74 else:
75 yield f".llong 0x{self.value:08x} # {self.dbrecord.name}"
76
77 @property
78 def prefix(self):
79 return Instruction(self[0:32])
80
81 @property
82 def suffix(self):
83 return Instruction(self[32:64])
84
85 @property
86 def major(self):
87 return self.suffix.major
88
89 @property
90 def dbrecord(self):
91 return self.suffix.dbrecord
92
93
94 class SVP64Instruction(PrefixedInstruction):
95 class PrefixError(ValueError):
96 pass
97
98 class Prefix(_SVP64PrefixFields, Instruction):
99 class RM(_SVP64RMFields):
100 @property
101 def sv_mode(self):
102 return (self.mode & 0b11)
103
104 @property
105 def rm(self):
106 return self.__class__.RM(super().rm)
107
108 class Suffix(Instruction):
109 pass
110
111 def __init__(self, prefix, suffix, byteorder=ByteOrder.LITTLE):
112 if SVP64Instruction.Prefix(prefix).pid != 0b11:
113 raise SVP64Instruction.PrefixError(prefix)
114 return super().__init__(prefix, suffix, byteorder)
115
116 def disassemble(self):
117 if self.dbrecord is None:
118 yield f".llong 0x{self.value:08x}"
119 else:
120 yield f".llong 0x{self.value:08x} # sv.{self.dbrecord.name}"
121
122 @property
123 def prefix(self):
124 return self.__class__.Prefix(super().prefix)
125
126 @property
127 def suffix(self):
128 return self.__class__.Suffix(super().suffix)
129
130
131 def load(ifile, byteorder, **_):
132 def load(ifile):
133 prefix = ifile.read(4)
134 length = len(prefix)
135 if length == 0:
136 return None
137 elif length < 4:
138 raise IOError(prefix)
139 prefix = Instruction(prefix, byteorder)
140 if prefix.major != 0x1:
141 return Instruction(prefix, byteorder)
142
143 suffix = ifile.read(4)
144 length = len(suffix)
145 if length == 0:
146 return prefix
147 elif length < 4:
148 raise IOError(suffix)
149 try:
150 return SVP64Instruction(prefix, suffix, byteorder)
151 except SVP64Instruction.PrefixError:
152 return PrefixedInstruction(prefix, suffix, byteorder)
153
154 while True:
155 insn = load(ifile)
156 if insn is None:
157 break
158 yield insn
159
160
161 def dump(insns, ofile, **_):
162 for insn in insns:
163 yield from insn.disassemble()
164
165
166 def main():
167 parser = _argparse.ArgumentParser()
168 parser.add_argument("ifile", nargs="?",
169 type=_argparse.FileType("rb"), default=_sys.stdin.buffer)
170 parser.add_argument("ofile", nargs="?",
171 type=_argparse.FileType("w"), default=_sys.stdout)
172 parser.add_argument("-b", "--byteorder",
173 type=ByteOrder, default=ByteOrder.LITTLE)
174
175 args = dict(vars(parser.parse_args()))
176 ifile = args["ifile"]
177 ofile = args["ofile"]
178 byteorder = args["byteorder"]
179
180 insns = load(ifile, byteorder)
181 for line in dump(insns, byteorder):
182 print(line, file=ofile)
183
184
185 if __name__ == "__main__":
186 main()