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
):
85 def span(self
, record
):
86 return tuple(range(0, 6))
88 @_dataclasses.dataclass(eq
=True, frozen
=True)
89 class XOStaticOperand(_StaticOperand
):
90 def span(self
, record
):
91 return tuple(record
.section
.bitsel
)
93 static_operands
= [(POStaticOperand
, {
95 "value": (PO
.value
& PO
.mask
)
98 static_operands
.append((XOStaticOperand
, {
100 "value": (XO
.value
& XO
.mask
)
103 static_operands
.extend(record
.mdwn
.operands
.static
)
104 dynamic_operands
= record
.mdwn
.operands
.dynamic
106 def static_operand(operand
):
107 (cls
, kwargs
) = operand
108 operand
= cls(record
=record
, **kwargs
)
109 return StaticOperand(name
=operand
.name
,
110 value
=operand
.value
, span
=operand
.span(record
=record
))
112 def dynamic_operand(operand
):
113 (cls
, kwargs
) = operand
114 operand
= cls(record
=record
, **kwargs
)
115 return DynamicOperand(name
=operand
.name
,
116 span
=operand
.span(record
=record
))
118 static_operands
= tuple(map(static_operand
, static_operands
))
119 dynamic_operands
= tuple(map(dynamic_operand
, dynamic_operands
))
121 yield Entry(name
=record
.name
,
122 static_operands
=static_operands
,
123 dynamic_operands
=dynamic_operands
)
127 operands
= entry
.dynamic_operands
128 operands
= ", ".join(operand
.name
for operand
in operands
)
129 string
= ",\t".join((
131 f
"XRC({entry.PO},{entry.XO},{entry.Rc})",
137 return f
"{{{string}}},"
140 def asm(entry
, binutils
=False, regex
=False):
141 operands
= tuple(entry
.dynamic_operands
)
142 for (idx
, operand
) in enumerate(operands
):
144 for each
in operands
:
145 if binutils
and each
.name
in ("FRT", "FRA", "FRB"):
147 elif binutils
and each
.name
in ("RT", "RA", "RB"):
151 value
= str((1 << len(operand
.span
)) - 1)
152 if binutils
and operand
.name
in ("FRT", "FRA", "FRB"):
154 elif binutils
and operand
.name
in ("RT", "RA", "RB"):
157 sep
= "\s+" if regex
else " "
158 yield f
"{entry.name}{sep}{','.join(values)}"
161 def dis(entry
, binutils
=True):
165 asm_plain
= tuple(asm(entry
, binutils
=binutils
, regex
=False))
166 asm_regex
= tuple(asm(entry
, binutils
=binutils
, regex
=True))
167 for (idx
, dynamic_operand
) in enumerate(entry
.dynamic_operands
):
168 insn
= _WordInstruction
.integer(value
=0)
169 for static_operand
in entry
.static_operands
:
170 span
= static_operand
.span
171 insn
[span
] = static_operand
.value
172 span
= dynamic_operand
.span
173 insn
[span
] = ((1 << len(span
)) - 1)
175 big
= " ".join(map(objdump
, insn
.bytes(byteorder
="big")))
176 little
= " ".join(map(objdump
, insn
.bytes(byteorder
="little")))
177 yield f
".*:\s+({big}|{little})\s+{asm_regex[idx]}"
182 class Mode(_enum
.Enum
):
188 return self
.name
.lower()
191 if __name__
== "__main__":
192 parser
= _argparse
.ArgumentParser()
193 parser
.add_argument("mode", type=Mode
, choices
=Mode
)
194 args
= dict(vars(parser
.parse_args()))
197 db
= _Database(_find_wiki_dir())
198 entries
= sorted(collect(db
))
201 Mode
.OPCODES
: opcodes
,
206 print("#as: -mlibresoc")
207 print("#objdump: -dr -Mlibresoc")
209 print(".*: file format .*")
212 print("Disassembly of section \\.text:")
213 print("0+ <\.text>:")
215 if mode
in {Mode
.ASM
, Mode
.DIS
}:
216 for subgenerator
in map(generator
, entries
):
217 for line
in subgenerator
:
220 for line
in map(generator
, entries
):