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 __init__(self
, PO
):
86 value
= (PO
.value
& PO
.mask
)
87 return super().__init
__(name
="PO", value
=value
)
89 def span(self
, record
):
90 return tuple(range(0, 6))
92 @_dataclasses.dataclass(eq
=True, frozen
=True)
93 class XOStaticOperand(_StaticOperand
):
94 def __init__(self
, XO
):
95 value
= (XO
.value
& XO
.mask
)
96 return super().__init
__(name
="XO", value
=value
)
98 def span(self
, record
):
99 return tuple(record
.section
.bitsel
)
101 static_operands
= [POStaticOperand(PO
=PO
)]
103 static_operands
.append(XOStaticOperand(XO
=XO
))
104 static_operands
.extend(record
.mdwn
.operands
.static
)
105 dynamic_operands
= record
.mdwn
.operands
.dynamic
107 def static_operand(operand
):
108 return StaticOperand(name
=operand
.name
,
109 value
=operand
.value
, span
=operand
.span(record
=record
))
111 def dynamic_operand(operand
):
112 return DynamicOperand(name
=operand
.name
,
113 span
=operand
.span(record
=record
))
115 static_operands
= tuple(map(static_operand
, static_operands
))
116 dynamic_operands
= tuple(map(dynamic_operand
, dynamic_operands
))
118 yield Entry(name
=record
.name
,
119 static_operands
=static_operands
,
120 dynamic_operands
=dynamic_operands
)
124 operands
= entry
.dynamic_operands
125 operands
= ", ".join(operand
.name
for operand
in operands
)
126 string
= ",\t".join((
128 f
"XRC({entry.PO},{entry.XO},{entry.Rc})",
134 return f
"{{{string}}},"
137 def asm(entry
, binutils
=False, regex
=False):
138 operands
= tuple(entry
.dynamic_operands
)
139 for (idx
, operand
) in enumerate(operands
):
141 for each
in operands
:
142 if binutils
and each
.name
in ("FRT", "FRA", "FRB"):
144 elif binutils
and each
.name
in ("RT", "RA", "RB"):
148 value
= str((1 << len(operand
.span
)) - 1)
149 if binutils
and operand
.name
in ("FRT", "FRA", "FRB"):
151 elif binutils
and operand
.name
in ("RT", "RA", "RB"):
154 sep
= "\s+" if regex
else " "
155 yield f
"{entry.name}{sep}{','.join(values)}"
158 def dis(entry
, binutils
=True):
162 asm_plain
= tuple(asm(entry
, binutils
=binutils
, regex
=False))
163 asm_regex
= tuple(asm(entry
, binutils
=binutils
, regex
=True))
164 for (idx
, dynamic_operand
) in enumerate(entry
.dynamic_operands
):
165 insn
= _WordInstruction
.integer(value
=0)
166 for static_operand
in entry
.static_operands
:
167 span
= static_operand
.span
168 insn
[span
] = static_operand
.value
169 span
= dynamic_operand
.span
170 insn
[span
] = ((1 << len(span
)) - 1)
172 big
= " ".join(map(objdump
, insn
.bytes(byteorder
="big")))
173 little
= " ".join(map(objdump
, insn
.bytes(byteorder
="little")))
174 yield f
".*:\s+({big}|{little})\s+{asm_regex[idx]}"
179 class Mode(_enum
.Enum
):
185 return self
.name
.lower()
188 if __name__
== "__main__":
189 parser
= _argparse
.ArgumentParser()
190 parser
.add_argument("mode", type=Mode
, choices
=Mode
)
191 args
= dict(vars(parser
.parse_args()))
194 db
= _Database(_find_wiki_dir())
195 entries
= sorted(collect(db
))
198 Mode
.OPCODES
: opcodes
,
203 print("#as: -mlibresoc")
204 print("#objdump: -dr -Mlibresoc")
206 print(".*: file format .*")
209 print("Disassembly of section \\.text:")
210 print("0+ <\.text>:")
212 if mode
in {Mode
.ASM
, Mode
.DIS
}:
213 for subgenerator
in map(generator
, entries
):
214 for line
in subgenerator
:
217 for line
in map(generator
, entries
):