pysvp64dis: introduce Prefix and RM classes
[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 class Prefix(_SVP64PrefixFields):
63 class RM(_SVP64RMFields):
64 @cached_property
65 def sv_mode(self):
66 return (self.mode & 0b11)
67
68 @property
69 def rm(self):
70 return self.__class__.RM(super().rm)
71
72 @cached_property
73 def prefix(self):
74 return self.__class__.Prefix(super().prefix)
75
76
77 def load(ifile, byteorder, **_):
78 def load(ifile):
79 prefix = ifile.read(4)
80 length = len(prefix)
81 if length == 0:
82 return None
83 elif length < 4:
84 raise IOError(prefix)
85 sv_prefix = _SVP64PrefixFields(int.from_bytes(prefix, byteorder=str(byteorder)))
86 if sv_prefix.major != 0x1:
87 return Instruction(prefix, byteorder)
88
89 suffix = ifile.read(4)
90 length = len(suffix)
91 if length == 0:
92 return prefix
93 elif length < 4:
94 raise IOError(suffix)
95 if sv_prefix.pid == 0b11:
96 return SVP64Instruction(prefix, suffix, byteorder)
97 else:
98 return PrefixedInstruction(prefix, suffix, byteorder)
99
100 while True:
101 insn = load(ifile)
102 if insn is None:
103 break
104 yield insn
105
106
107 def dump(insns, ofile, **_):
108 for insn in insns:
109 yield str(insn)
110
111
112 def main():
113 parser = _argparse.ArgumentParser()
114 parser.add_argument("ifile", nargs="?",
115 type=_argparse.FileType("rb"), default=_sys.stdin.buffer)
116 parser.add_argument("ofile", nargs="?",
117 type=_argparse.FileType("w"), default=_sys.stdout)
118 parser.add_argument("-b", "--byteorder",
119 type=ByteOrder, default=ByteOrder.LITTLE)
120
121 args = dict(vars(parser.parse_args()))
122 ifile = args["ifile"]
123 ofile = args["ofile"]
124 byteorder = args["byteorder"]
125
126 insns = load(ifile, byteorder)
127 for line in dump(insns, byteorder):
128 print(line, file=ofile)
129
130
131 if __name__ == "__main__":
132 main()