2e63b7d25ec067cbb93ba1842fa1df3e0b4ede39
[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 def __init__(self, prefix, suffix, byteorder=ByteOrder.LITTLE):
89 if SVP64Instruction.Prefix(prefix).pid != 0b11:
90 raise SVP64Instruction.PrefixError(prefix)
91 return super().__init__(prefix, suffix, byteorder)
92
93 def __str__(self):
94 return (super().__str__() + " # sv")
95
96 @cached_property
97 def prefix(self):
98 return self.__class__.Prefix(super().prefix)
99
100
101 def load(ifile, byteorder, **_):
102 def load(ifile):
103 prefix = ifile.read(4)
104 length = len(prefix)
105 if length == 0:
106 return None
107 elif length < 4:
108 raise IOError(prefix)
109 prefix = Instruction(prefix, byteorder)
110 if prefix.major != 0x1:
111 return Instruction(prefix, byteorder)
112
113 suffix = ifile.read(4)
114 length = len(suffix)
115 if length == 0:
116 return prefix
117 elif length < 4:
118 raise IOError(suffix)
119 try:
120 return SVP64Instruction(prefix, suffix, byteorder)
121 except SVP64Instruction.PrefixError:
122 return PrefixedInstruction(prefix, suffix, byteorder)
123
124 while True:
125 insn = load(ifile)
126 if insn is None:
127 break
128 yield insn
129
130
131 def dump(insns, ofile, **_):
132 for insn in insns:
133 yield str(insn)
134
135
136 def main():
137 parser = _argparse.ArgumentParser()
138 parser.add_argument("ifile", nargs="?",
139 type=_argparse.FileType("rb"), default=_sys.stdin.buffer)
140 parser.add_argument("ofile", nargs="?",
141 type=_argparse.FileType("w"), default=_sys.stdout)
142 parser.add_argument("-b", "--byteorder",
143 type=ByteOrder, default=ByteOrder.LITTLE)
144
145 args = dict(vars(parser.parse_args()))
146 ifile = args["ifile"]
147 ofile = args["ofile"]
148 byteorder = args["byteorder"]
149
150 insns = load(ifile, byteorder)
151 for line in dump(insns, byteorder):
152 print(line, file=ofile)
153
154
155 if __name__ == "__main__":
156 main()