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