1 import argparse
as _argparse
2 import dataclasses
as _dataclasses
4 import functools
as _functools
7 from openpower
.decoder
.power_enums
import (
8 FPTRANS_INSNS
as _FPTRANS_INSNS
,
9 find_wiki_dir
as _find_wiki_dir
,
11 from openpower
.decoder
.power_insn
import (
12 Database
as _Database
,
13 StaticOperand
as _StaticOperand
,
14 WordInstruction
as _WordInstruction
,
18 @_dataclasses.dataclass(eq
=True, frozen
=True)
25 @_dataclasses.dataclass(eq
=True, frozen
=True)
31 @_functools.total_ordering
32 @_dataclasses.dataclass(eq
=True, frozen
=True)
35 static_operands
: tuple
36 dynamic_operands
: tuple
38 def __lt__(self
, other
):
39 if not isinstance(other
, self
.__class
__):
41 return ((self
.PO
, self
.XO
, self
.Rc
) <
42 (other
.PO
, other
.XO
, other
.Rc
))
46 for operand
in self
.static_operands
:
47 if operand
.name
== "PO":
49 raise ValueError(self
)
53 for operand
in self
.static_operands
:
54 if operand
.name
== "XO":
56 raise ValueError(self
)
60 for operand
in self
.static_operands
:
61 if operand
.name
== "Rc":
63 raise ValueError(self
)
67 fptrans
= tuple(_FPTRANS_INSNS
)
68 fptrans_Rc
= tuple(map(lambda name
: f
"{name}.", fptrans
))
70 def fptrans_match(insn
):
71 return ((insn
.name
in fptrans
) or (insn
.name
in fptrans_Rc
))
73 for record
in filter(fptrans_match
, db
):
74 if len(record
.opcodes
) > 1:
75 raise NotImplementedError(record
.opcodes
)
76 PO
= record
.section
.opcode
78 PO
= tuple(record
.ppc
)[0].opcode
81 XO
= tuple(record
.ppc
)[0].opcode
83 @_dataclasses.dataclass(eq
=True, frozen
=True)
84 class POStaticOperand(_StaticOperand
):
87 return tuple(range(0, 6))
89 @_dataclasses.dataclass(eq
=True, frozen
=True)
90 class XOStaticOperand(_StaticOperand
):
93 return tuple(self
.record
.section
.bitsel
)
95 static_operands
= [(POStaticOperand
, {
97 "value": (PO
.value
& PO
.mask
)
100 static_operands
.append((XOStaticOperand
, {
102 "value": (XO
.value
& XO
.mask
)
105 static_operands
.extend(record
.mdwn
.operands
.static
)
106 dynamic_operands
= record
.mdwn
.operands
.dynamic
108 def static_operand(operand
):
109 (cls
, kwargs
) = operand
110 operand
= cls(record
=record
, **kwargs
)
111 return StaticOperand(name
=operand
.name
,
112 value
=operand
.value
, span
=operand
.span
)
114 def dynamic_operand(operand
):
115 (cls
, kwargs
) = operand
116 operand
= cls(record
=record
, **kwargs
)
117 return DynamicOperand(name
=operand
.name
,
120 static_operands
= tuple(map(static_operand
, static_operands
))
121 dynamic_operands
= tuple(map(dynamic_operand
, dynamic_operands
))
123 yield Entry(name
=record
.name
,
124 static_operands
=static_operands
,
125 dynamic_operands
=dynamic_operands
)
129 operands
= entry
.dynamic_operands
130 operands
= ", ".join(operand
.name
for operand
in operands
)
131 string
= ",\t".join((
133 f
"XRC({entry.PO},{entry.XO},{entry.Rc})",
139 return f
"{{{string}}},"
142 def asm(entry
, binutils
=False, regex
=False):
143 operands
= tuple(entry
.dynamic_operands
)
144 for (idx
, operand
) in enumerate(operands
):
146 for each
in operands
:
147 if binutils
and each
.name
in ("FRT", "FRA", "FRB"):
149 elif binutils
and each
.name
in ("RT", "RA", "RB"):
153 value
= str((1 << len(operand
.span
)) - 1)
154 if binutils
and operand
.name
in ("FRT", "FRA", "FRB"):
156 elif binutils
and operand
.name
in ("RT", "RA", "RB"):
159 sep
= "\s+" if regex
else " "
160 yield f
"{entry.name}{sep}{','.join(values)}"
163 def dis(entry
, binutils
=True):
167 asm_plain
= tuple(asm(entry
, binutils
=binutils
, regex
=False))
168 asm_regex
= tuple(asm(entry
, binutils
=binutils
, regex
=True))
169 for (idx
, dynamic_operand
) in enumerate(entry
.dynamic_operands
):
170 insn
= _WordInstruction
.integer(value
=0)
171 for static_operand
in entry
.static_operands
:
172 span
= static_operand
.span
173 insn
[span
] = static_operand
.value
174 span
= dynamic_operand
.span
175 insn
[span
] = ((1 << len(span
)) - 1)
177 big
= " ".join(map(objdump
, insn
.bytes(byteorder
="big")))
178 little
= " ".join(map(objdump
, insn
.bytes(byteorder
="little")))
179 yield f
".*:\s+({big}|{little})\s+{asm_regex[idx]}"
184 class Mode(_enum
.Enum
):
190 return self
.name
.lower()
193 if __name__
== "__main__":
194 parser
= _argparse
.ArgumentParser()
195 parser
.add_argument("mode", type=Mode
, choices
=Mode
)
196 args
= dict(vars(parser
.parse_args()))
199 db
= _Database(_find_wiki_dir())
200 entries
= sorted(collect(db
))
203 Mode
.OPCODES
: opcodes
,
208 print("#as: -mlibresoc")
209 print("#objdump: -dr -Mlibresoc")
211 print(".*: file format .*")
214 print("Disassembly of section \\.text:")
215 print("0+ <\.text>:")
217 if mode
in {Mode
.ASM
, Mode
.DIS
}:
218 for subgenerator
in map(generator
, entries
):
219 for line
in subgenerator
:
222 for line
in map(generator
, entries
):