pysvp64db: fix traversal
[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
8
9 class ByteOrder(_enum.Enum):
10 LITTLE = "little"
11 BIG = "big"
12
13 def __str__(self):
14 return self.name.lower()
15
16
17 class Instruction(_SelectableInt):
18 def __init__(self, value, bits=32, byteorder=ByteOrder.LITTLE):
19 if isinstance(value, bytes):
20 value = int.from_bytes(value, byteorder=str(byteorder))
21 if not isinstance(value, (int, _SelectableInt)) or (value < 0):
22 raise ValueError(value)
23 return super().__init__(value=value, bits=bits)
24
25 def __repr__(self):
26 return f"{self.__class__.__name__}({str(self)})"
27
28 def __str__(self):
29 return f".long 0x{self.value:08x}"
30
31 @property
32 def major(self):
33 return self[0:6]
34
35
36 class PrefixedInstruction(Instruction):
37 def __init__(self, prefix, suffix, byteorder=ByteOrder.LITTLE):
38 insn = _functools.partial(Instruction, bits=64)
39 (prefix, suffix) = map(insn, (prefix, suffix))
40 value = ((prefix.value << 32) | suffix.value)
41 return super().__init__(value=value, bits=64)
42
43 def __str__(self):
44 return f".llong 0x{self.value:016x}"
45
46 @property
47 def prefix(self):
48 return self[32:64]
49
50 @property
51 def suffix(self):
52 return self[0:32]
53
54
55 def load(ifile, byteorder, **_):
56 def load(ifile):
57 prefix = ifile.read(4)
58 length = len(prefix)
59 if length == 0:
60 return None
61 elif length < 4:
62 raise IOError(prefix)
63 prefix = Instruction(prefix, byteorder=byteorder)
64 if prefix.major != 0x1:
65 return prefix
66
67 suffix = ifile.read(4)
68 length = len(suffix)
69 if length == 0:
70 return prefix
71 elif length < 4:
72 raise IOError(suffix)
73
74 return PrefixedInstruction(prefix, suffix, byteorder=byteorder)
75
76 while True:
77 insn = load(ifile)
78 if insn is None:
79 break
80 yield insn
81
82
83 def dump(insns, ofile, **_):
84 for insn in insns:
85 yield str(insn)
86
87
88 def main():
89 parser = _argparse.ArgumentParser()
90 parser.add_argument("ifile", nargs="?",
91 type=_argparse.FileType("rb"), default=_sys.stdin.buffer)
92 parser.add_argument("ofile", nargs="?",
93 type=_argparse.FileType("w"), default=_sys.stdout)
94 parser.add_argument("-b", "--byteorder",
95 type=ByteOrder, default=ByteOrder.LITTLE)
96 args = dict(vars(parser.parse_args()))
97
98 insns = load(**args)
99 for line in dump(insns, **args):
100 print(line)
101
102
103 if __name__ == "__main__":
104 main()