pysvp64dis: refactor classes; use fields helpers
[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.selectable_int import SelectableInt as _SelectableInt
7 from openpower.decoder.isa.caller import SVP64PrefixFields as _SVP64PrefixFields
8 from openpower.decoder.isa.caller import SVP64RMFields as _SVP64RMFields
9
10 try:
11 from functools import cached_property
12 except ImportError:
13 from cached_property import cached_property
14
15
16 class ByteOrder(_enum.Enum):
17 LITTLE = "little"
18 BIG = "big"
19
20 def __str__(self):
21 return self.name.lower()
22
23
24 class Instruction(_SelectableInt):
25 def __init__(self, value, byteorder=ByteOrder.LITTLE):
26 if isinstance(value, bytes):
27 value = int.from_bytes(value, byteorder=str(byteorder))
28 if not isinstance(value, int) or (value < 0) or (value > ((1 << 32) - 1)):
29 raise ValueError(value)
30 return super().__init__(value=value, bits=32)
31
32 def __repr__(self):
33 return f"{self.__class__.__name__}({self.value:08x})"
34
35 def __str__(self):
36 return f".long 0x{self.value:08x}"
37
38
39 class PrefixedInstruction(_SelectableInt):
40 def __init__(self, prefix, suffix, byteorder=ByteOrder.LITTLE):
41 insn = _functools.partial(Instruction, byteorder=byteorder)
42 (prefix, suffix) = map(insn, (prefix, suffix))
43 value = ((prefix.value << 32) | suffix.value)
44 return super().__init__(value=value, bits=64)
45
46 def __repr__(self):
47 return f"{self.__class__.__name__}({self.value:016x})"
48
49 def __str__(self):
50 return f".llong 0x{self.value:016x}"
51
52 @property
53 def prefix(self):
54 return self[0:32]
55
56 @property
57 def suffix(self):
58 return self[32:64]
59
60
61 class SVP64Instruction(PrefixedInstruction):
62 @cached_property
63 def prefix(self):
64 return _SVP64PrefixFields(super().prefix)
65
66 @cached_property
67 def rm(self):
68 return _SVP64RMFields(self.prefix.rm)
69
70
71 def load(ifile, byteorder, **_):
72 def load(ifile):
73 prefix = ifile.read(4)
74 length = len(prefix)
75 if length == 0:
76 return None
77 elif length < 4:
78 raise IOError(prefix)
79 sv_prefix = _SVP64PrefixFields(int.from_bytes(prefix, byteorder=str(byteorder)))
80 if sv_prefix.major != 0x1:
81 return Instruction(prefix, byteorder)
82
83 suffix = ifile.read(4)
84 length = len(suffix)
85 if length == 0:
86 return prefix
87 elif length < 4:
88 raise IOError(suffix)
89 if sv_prefix.pid == 0b11:
90 return SVP64Instruction(prefix, suffix, byteorder)
91 else:
92 return PrefixedInstruction(prefix, suffix, byteorder)
93
94 while True:
95 insn = load(ifile)
96 if insn is None:
97 break
98 yield insn
99
100
101 def dump(insns, ofile, **_):
102 for insn in insns:
103 yield str(insn)
104
105
106 def main():
107 parser = _argparse.ArgumentParser()
108 parser.add_argument("ifile", nargs="?",
109 type=_argparse.FileType("rb"), default=_sys.stdin.buffer)
110 parser.add_argument("ofile", nargs="?",
111 type=_argparse.FileType("w"), default=_sys.stdout)
112 parser.add_argument("-b", "--byteorder",
113 type=ByteOrder, default=ByteOrder.LITTLE)
114 args = dict(vars(parser.parse_args()))
115
116 insns = load(**args)
117 for line in dump(insns, **args):
118 print(line)
119
120
121 if __name__ == "__main__":
122 main()