2 import argparse
as _argparse
3 import codecs
as _codecs
5 import dataclasses
as _dataclasses
7 import pathlib
as _pathlib
11 from openpower
.decoder
.power_enums
import (
17 CROutSel
as _CROutSel
,
22 from openpower
.decoder
.power_svp64
import SVP64RM
as _SVP64RM
27 " * this file is auto-generated, do not edit",
28 " * http://libre-soc.org/openpower/sv_binutiks.py",
29 " * part of Libre-SOC, sponsored by NLnet",
35 return map(lambda string
: (" " + string
), strings
)
41 def c_decl(self
, name
):
45 def c_value(self
, prefix
="", suffix
=""):
50 def c_var(self
, name
):
54 class Enum(Field
, _enum
.Enum
):
57 c_tag
= f
"svp64_{cls.__name__.lower()}"
58 yield f
"enum {c_tag} {{"
60 yield from indent(item
.c_value(suffix
=","))
63 def c_value(self
, prefix
="", suffix
=""):
64 c_tag
= f
"svp64_{self.__class__.__name__.lower()}"
65 yield f
"{prefix}{c_tag.upper()}_{self.name.upper()}{suffix}"
69 c_tag
= f
"svp64_{cls.__name__.lower()}"
70 yield f
"enum {c_tag} {name};"
73 # Python forbids inheriting from enum unless it's empty.
74 In1Sel
= Enum("In1Sel", {item
.name
:item
.value
for item
in _In1Sel
})
75 In2Sel
= Enum("In2Sel", {item
.name
:item
.value
for item
in _In2Sel
})
76 In3Sel
= Enum("In3Sel", {item
.name
:item
.value
for item
in _In3Sel
})
77 OutSel
= Enum("OutSel", {item
.name
:item
.value
for item
in _OutSel
})
78 CRInSel
= Enum("CRInSel", {item
.name
:item
.value
for item
in _CRInSel
})
79 CROutSel
= Enum("CROutSel", {item
.name
:item
.value
for item
in _CROutSel
})
80 SVPType
= Enum("SVPType", {item
.name
:item
.value
for item
in _SVPtype
})
81 SVEType
= Enum("SVEType", {item
.name
:item
.value
for item
in _SVEtype
})
82 SVEXTRA
= Enum("SVEXTRA", {item
.name
:item
.value
for item
in _SVEXTRA
})
86 def __init__(self
, value
, mask
, bits
):
91 return super().__init
__()
106 fmt
= f
"{{value:0{self.bits}b}}:{{mask:0{self.bits}b}}"
107 return fmt
.format(value
=self
.value
, mask
=self
.mask
)
111 yield f
"struct svp64_opcode {{"
118 def c_value(self
, prefix
="", suffix
=""):
121 f
".value = UINT32_C(0x{self.value:08X}),",
122 f
".mask = UINT32_C(0x{self.mask:08X}),",
127 def c_var(cls
, name
):
128 yield f
"struct svp64_opcode {name};"
131 class IntegerOpcode(Opcode
):
132 def __init__(self
, integer
):
133 value
= int(integer
, 0)
134 bits
= max(1, value
.bit_length())
135 mask
= int(("1" * bits
), 2)
137 return super().__init
__(value
=value
, mask
=mask
, bits
=bits
)
140 class PatternOpcode(Opcode
):
141 def __init__(self
, pattern
):
146 value |
= (bit
== "1")
153 return super().__init
__(value
=value
, mask
=mask
, bits
=bits
)
156 class Name(Field
, str):
158 escaped
= self
.replace("\"", "\\\"")
159 return f
"\"{escaped}\""
161 def c_value(self
, prefix
="", suffix
=""):
162 yield f
"{prefix}{self!r}{suffix}"
165 def c_var(cls
, name
):
166 yield f
"const char *{name};"
169 @_dataclasses.dataclass(eq
=True, frozen
=True)
192 yield f
"struct svp64_entry {{"
193 for field
in _dataclasses
.fields(cls
):
194 if issubclass(field
.type, Enum
):
195 bits
= len(field
.type).bit_length()
196 yield from indent([f
"uint64_t {field.name} : {bits};"])
198 yield from indent(field
.type.c_var(name
=field
.name
))
201 def c_value(self
, prefix
="", suffix
=""):
203 for field
in _dataclasses
.fields(self
):
205 attr
= getattr(self
, name
)
206 yield from indent(attr
.c_value(prefix
=f
".{name} = ", suffix
=","))
210 def c_var(cls
, name
):
211 yield f
"struct svp64_entry {name};"
214 class Codegen(_enum
.Enum
):
215 PPC_OPC_SVP64_H
= _enum
.auto()
216 PPC_OPC_SVP64_C
= _enum
.auto()
219 def _missing_(cls
, value
):
221 "ppc-opc-svp64.h": Codegen
.PPC_OPC_SVP64_H
,
222 "ppc-opc-svp64.c": Codegen
.PPC_OPC_SVP64_C
,
227 Codegen
.PPC_OPC_SVP64_H
: "ppc-opc-svp64.h",
228 Codegen
.PPC_OPC_SVP64_C
: "ppc-opc-svp64.c",
231 def generate(self
, entries
):
232 def ppc_opc_svp64_h(entries
):
233 yield from DISCLAIMER
236 yield f
"#ifndef {self.name}"
237 yield f
"#define {self.name}"
242 In1Sel
, In2Sel
, In3Sel
, OutSel
,
247 yield from enum
.c_decl()
250 yield from Opcode
.c_decl()
253 yield from Entry
.c_decl()
256 yield f
"#endif /* {self.name} */"
259 def ppc_opc_svp64_c(entries
):
263 Codegen
.PPC_OPC_SVP64_H
: ppc_opc_svp64_h
,
264 Codegen
.PPC_OPC_SVP64_C
: ppc_opc_svp64_c
,
268 def regex_enum(enum
):
269 assert issubclass(enum
, _enum
.Enum
)
270 return "|".join(item
.name
for item
in enum
)
273 PATTERN_VHDL_BINARY
= r
"(?:2#[01]+#)"
274 PATTERN_DECIMAL
= r
"(?:[0-9]+)"
275 PATTERN_PARTIAL_BINARY
= r
"(?:[01-]+)"
277 # Examples of the entries to be caught by the pattern below:
278 # 2 => (P2, EXTRA3, RA_OR_ZERO, NONE, NONE, RT, NONE, NONE, NONE, Idx1, NONE, NONE, Idx0, NONE, NONE, NONE), -- lwz
279 # -----10110 => (P2, EXTRA3, NONE, FRB, NONE, FRT, NONE, NONE, CR1, NONE, Idx1, NONE, Idx0, NONE, NONE, Idx0), -- fsqrts
280 # 2#0000000000# => (P2, EXTRA3, NONE, NONE, NONE, NONE, NONE, BFA, BF, NONE, NONE, NONE, NONE, NONE, Idx1, Idx0), -- mcrf
283 rf
"(?P<opcode>{PATTERN_VHDL_BINARY}|{PATTERN_DECIMAL}|{PATTERN_PARTIAL_BINARY})",
287 rf
"(?P<ptype>{regex_enum(_SVPtype)})",
288 rf
"(?P<etype>{regex_enum(_SVEtype)})",
289 rf
"(?P<in1>{regex_enum(_In1Sel)})",
290 rf
"(?P<in2>{regex_enum(_In2Sel)})",
291 rf
"(?P<in3>{regex_enum(_In3Sel)})",
292 rf
"(?P<out>{regex_enum(_OutSel)})",
293 rf
"(?P<out2>{regex_enum(_OutSel)})",
294 rf
"(?P<cr_in>{regex_enum(_CRInSel)})",
295 rf
"(?P<cr_out>{regex_enum(_CROutSel)})",
296 rf
"(?P<sv_in1>{regex_enum(_SVEXTRA)})",
297 rf
"(?P<sv_in2>{regex_enum(_SVEXTRA)})",
298 rf
"(?P<sv_in3>{regex_enum(_SVEXTRA)})",
299 rf
"(?P<sv_out>{regex_enum(_SVEXTRA)})",
300 rf
"(?P<sv_out2>{regex_enum(_SVEXTRA)})",
301 rf
"(?P<sv_cr_in>{regex_enum(_SVEXTRA)})",
302 rf
"(?P<sv_cr_out>{regex_enum(_SVEXTRA)})",
307 r
"(?P<name>[A-Za-z0-9_\./]+)",
310 REGEX
= _re
.compile(PATTERN
)
314 FIELDS
= {field
.name
:field
for field
in _dataclasses
.fields(Entry
)}
315 def parse(path
, opcode_cls
):
316 for entry
in ISA
.get_svp64_csv(path
):
317 # skip instructions that are not suitable
318 name
= entry
["name"] = entry
.pop("comment")
319 if name
.startswith("l") and name
.endswith("br"):
321 if name
in {"mcrxr", "mcrxrx", "darn"}:
323 if name
in {"bctar", "bcctr"}:
327 if name
in {"setvl"}:
330 entry
= {key
.lower().replace(" ", "_"):value
for (key
, value
) in entry
.items()}
331 for (key
, value
) in tuple(entry
.items()):
332 key
= key
.lower().replace(" ", "_")
333 if key
not in FIELDS
:
337 if issubclass(field
.type, _enum
.Enum
):
338 value
= {item
.name
:item
for item
in field
.type}[value
]
339 elif issubclass(field
.type, Opcode
):
340 value
= opcode_cls(value
)
342 value
= field
.type(value
)
351 "minor_19.csv": IntegerOpcode
,
352 "minor_30.csv": IntegerOpcode
,
353 "minor_31.csv": IntegerOpcode
,
354 "minor_58.csv": IntegerOpcode
,
355 "minor_62.csv": IntegerOpcode
,
356 "minor_22.csv": IntegerOpcode
,
357 "minor_5.csv": PatternOpcode
,
358 "minor_63.csv": PatternOpcode
,
359 "minor_59.csv": PatternOpcode
,
360 "major.csv": IntegerOpcode
,
361 "extra.csv": PatternOpcode
,
363 for (path
, opcode_cls
) in table
.items():
364 entries
.extend(parse(path
, opcode_cls
))
366 for line
in codegen
.generate(entries
):
370 if __name__
== "__main__":
371 parser
= _argparse
.ArgumentParser()
372 parser
.add_argument("codegen", type=Codegen
, choices
=Codegen
, help="code generator")
374 args
= vars(parser
.parse_args())