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