add quick test_pysvp64dis.py of LD/ST data-dependent fail-first
[openpower-isa.git] / src / openpower / sv / sv_binutils_fptrans.py
1 import argparse as _argparse
2 import dataclasses as _dataclasses
3 import enum as _enum
4 import functools as _functools
5
6
7 from openpower.decoder.power_enums import (
8 FPTRANS_INSNS as _FPTRANS_INSNS,
9 find_wiki_dir as _find_wiki_dir,
10 )
11 from openpower.decoder.power_insn import (
12 Database as _Database,
13 StaticOperand as _StaticOperand,
14 WordInstruction as _WordInstruction,
15 )
16
17
18 def collect(db):
19 fptrans = tuple(_FPTRANS_INSNS)
20 fptrans_Rc = tuple(map(lambda name: f"{name}.", fptrans))
21
22 def fptrans_match(insn):
23 return ((insn.name in fptrans) or (insn.name in fptrans_Rc))
24
25 for record in filter(fptrans_match, db):
26 if len(record.opcodes) > 1:
27 raise NotImplementedError(record.opcodes)
28
29 yield record
30
31
32 def opcodes(entry):
33 operands = entry.dynamic_operands
34 operands = ", ".join(operand.name for operand in operands)
35 string = ",\t".join((
36 f"\"{entry.name}\"",
37 f"XRC({entry.PO},{entry.XO},{entry.Rc})",
38 "X_MASK",
39 "SVP64",
40 "PPCVLE",
41 f"{{{operands}}}",
42 ))
43 return f"{{{string}}},"
44
45
46 def asm(record, binutils=False, regex=False):
47 operands = tuple(record.dynamic_operands)
48 for (idx, operand) in enumerate(operands):
49 values = []
50 for each in operands:
51 if binutils and each.name in ("FRT", "FRA", "FRB"):
52 values.append("f0")
53 elif binutils and each.name in ("RT", "RA", "RB"):
54 values.append("r0")
55 else:
56 values.append("0")
57 value = str((1 << len(operand.span)) - 1)
58 if binutils and operand.name in ("FRT", "FRA", "FRB"):
59 value = f"f{value}"
60 elif binutils and operand.name in ("RT", "RA", "RB"):
61 value = f"r{value}"
62 values[idx] = value
63 sep = "\s+" if regex else " "
64 yield f"{record.name}{sep}{','.join(values)}"
65
66
67 def dis(record, binutils=True):
68 def objdump(byte):
69 return f"{byte:02x}"
70
71 asm_plain = tuple(asm(record, binutils=binutils, regex=False))
72 asm_regex = tuple(asm(record, binutils=binutils, regex=True))
73 for (idx, dynamic_operand) in enumerate(record.dynamic_operands):
74 insn = _WordInstruction.integer(value=0)
75 for static_operand in record.static_operands:
76 insn[static_operand.span] = static_operand.value
77 span = dynamic_operand.span
78 insn[span] = ((1 << len(span)) - 1)
79 if binutils:
80 big = " ".join(map(objdump, insn.bytes(byteorder="big")))
81 little = " ".join(map(objdump, insn.bytes(byteorder="little")))
82 yield f".*:\s+({big}|{little})\s+{asm_regex[idx]}"
83 else:
84 yield asm_plain[idx]
85
86
87 class Mode(_enum.Enum):
88 OPCODES = "opcodes"
89 ASM = "asm"
90 DIS = "dis"
91
92 def __str__(self):
93 return self.name.lower()
94
95
96 if __name__ == "__main__":
97 parser = _argparse.ArgumentParser()
98 parser.add_argument("mode", type=Mode, choices=Mode)
99 args = dict(vars(parser.parse_args()))
100
101 mode = args["mode"]
102 db = _Database(_find_wiki_dir())
103 entries = sorted(collect(db))
104
105 generator = {
106 Mode.OPCODES: opcodes,
107 Mode.ASM: asm,
108 Mode.DIS: dis,
109 }[mode]
110 if mode is Mode.DIS:
111 print("#as: -mlibresoc")
112 print("#objdump: -dr -Mlibresoc")
113 print("")
114 print(".*: file format .*")
115 print("")
116 print("")
117 print("Disassembly of section \\.text:")
118 print("0+ <\.text>:")
119
120 if mode in {Mode.ASM, Mode.DIS}:
121 for subgenerator in map(generator, entries):
122 for line in subgenerator:
123 print(line)
124 else:
125 for line in map(generator, entries):
126 print(line)