2 import argparse
as _argparse
3 import dataclasses
as _dataclasses
7 from openpower
.decoder
.power_enums
import (
13 CROutSel
as _CROutSel
,
18 from openpower
.decoder
.power_svp64
import SVP64RM
as _SVP64RM
23 " * this file is auto-generated, do not edit",
24 " * https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/sv/sv_binutils.py",
25 " * part of Libre-SOC, sponsored by NLnet",
31 return map(lambda string
: (" " + string
), strings
)
37 def c_decl(self
, name
):
41 def c_value(self
, prefix
="", suffix
=""):
46 def c_var(self
, name
):
50 class Enum(CType
, _enum
.Enum
):
53 c_tag
= f
"svp64_{cls.__name__.lower()}"
54 yield f
"enum {c_tag} {{"
56 yield from indent(item
.c_value(suffix
=","))
59 def c_value(self
, prefix
="", suffix
=""):
60 c_tag
= f
"svp64_{self.__class__.__name__.lower()}"
61 yield f
"{prefix}{c_tag.upper()}_{self.name.upper()}{suffix}"
65 c_tag
= f
"svp64_{cls.__name__.lower()}"
66 yield f
"enum {c_tag} {name}"
69 # Python forbids inheriting from enum unless it's empty.
70 In1Sel
= Enum("In1Sel", {item
.name
:item
.value
for item
in _In1Sel
})
71 In2Sel
= Enum("In2Sel", {item
.name
:item
.value
for item
in _In2Sel
})
72 In3Sel
= Enum("In3Sel", {item
.name
:item
.value
for item
in _In3Sel
})
73 OutSel
= Enum("OutSel", {item
.name
:item
.value
for item
in _OutSel
})
74 CRInSel
= Enum("CRInSel", {item
.name
:item
.value
for item
in _CRInSel
})
75 CROutSel
= Enum("CROutSel", {item
.name
:item
.value
for item
in _CROutSel
})
76 SVPType
= Enum("SVPType", {item
.name
:item
.value
for item
in _SVPtype
})
77 SVEType
= Enum("SVEType", {item
.name
:item
.value
for item
in _SVEtype
})
78 SVEXTRA
= Enum("SVEXTRA", {item
.name
:item
.value
for item
in _SVEXTRA
})
82 def __init__(self
, value
, mask
, bits
):
87 return super().__init
__()
102 fmt
= f
"{{value:0{self.bits}b}}:{{mask:0{self.bits}b}}"
103 return fmt
.format(value
=self
.value
, mask
=self
.mask
)
107 yield f
"struct svp64_opcode {{"
114 def c_value(self
, prefix
="", suffix
=""):
117 f
".value = UINT32_C(0x{self.value:08X}),",
118 f
".mask = UINT32_C(0x{self.mask:08X}),",
123 def c_var(cls
, name
):
124 yield f
"struct svp64_opcode {name}"
127 class IntegerOpcode(Opcode
):
128 def __init__(self
, integer
):
129 value
= int(integer
, 0)
130 bits
= max(1, value
.bit_length())
131 mask
= int(("1" * bits
), 2)
133 return super().__init
__(value
=value
, mask
=mask
, bits
=bits
)
136 class PatternOpcode(Opcode
):
137 def __init__(self
, pattern
):
142 value |
= (bit
== "1")
149 return super().__init
__(value
=value
, mask
=mask
, bits
=bits
)
152 class Name(CType
, str):
154 escaped
= self
.replace("\"", "\\\"")
155 return f
"\"{escaped}\""
157 def c_value(self
, prefix
="", suffix
=""):
158 yield f
"{prefix}{self!r}{suffix}"
161 def c_var(cls
, name
):
162 yield f
"const char *{name}"
165 @_dataclasses.dataclass(eq
=True, frozen
=True)
186 def __lt__(self
, other
):
187 if not isinstance(other
, self
.__class
__):
188 return NotImplemented
189 return self
.name
< other
.name
194 yield f
"struct svp64_entry {{"
195 for field
in _dataclasses
.fields(cls
):
196 if issubclass(field
.type, Enum
):
197 bits
= len(field
.type).bit_length()
198 yield from indent([f
"uint64_t {field.name} : {bits};"])
201 yield from indent(field
.type.c_var(name
=f
"{field.name};"))
202 bits_rsvd
= (64 - (bits_all
% 64))
204 yield from indent([f
"uint64_t : {bits_rsvd};"])
207 def c_value(self
, prefix
="", suffix
=""):
209 for field
in _dataclasses
.fields(self
):
211 attr
= getattr(self
, name
)
212 yield from indent(attr
.c_value(prefix
=f
".{name} = ", suffix
=","))
216 def c_var(cls
, name
):
217 yield f
"struct svp64_entry {name}"
220 class Codegen(_enum
.Enum
):
221 PPC_SVP64_H
= _enum
.auto()
222 PPC_SVP64_OPC_C
= _enum
.auto()
225 def _missing_(cls
, value
):
227 "ppc-svp64.h": Codegen
.PPC_SVP64_H
,
228 "ppc-svp64-opc.c": Codegen
.PPC_SVP64_OPC_C
,
233 Codegen
.PPC_SVP64_H
: "ppc-svp64.h",
234 Codegen
.PPC_SVP64_OPC_C
: "ppc-svp64-opc.c",
237 def generate(self
, entries
):
238 def ppc_svp64_h(entries
):
239 yield from DISCLAIMER
242 yield f
"#ifndef {self.name}"
243 yield f
"#define {self.name}"
246 yield "#include <stdint.h>"
249 yield "#ifdef __cplusplus"
250 yield "extern \"C\" {"
254 yield from Opcode
.c_decl()
258 In1Sel
, In2Sel
, In3Sel
, OutSel
,
260 SVPType
, SVEType
, SVEXTRA
,
263 yield from enum
.c_decl()
266 yield from Entry
.c_decl()
269 yield "extern const struct svp64_entry svp64_entries[];"
270 yield "extern const unsigned int svp64_num_entries;"
273 yield "#ifdef __cplusplus"
278 yield f
"#endif /* {self.name} */"
281 def ppc_svp64_opc_c(entries
):
282 yield from DISCLAIMER
285 yield "#include \"opcode/ppc-svp64.h\""
288 yield "const struct svp64_entry svp64_entries[] = {"
289 for (index
, entry
) in enumerate(entries
):
290 yield from indent(entry
.c_value(prefix
=f
"[{index}] = ", suffix
=","))
294 yield "const unsigned int svp64_num_entries = \\"
295 yield " sizeof (svp64_entries) / sizeof (svp64_entries[0]);"
299 Codegen
.PPC_SVP64_H
: ppc_svp64_h
,
300 Codegen
.PPC_SVP64_OPC_C
: ppc_svp64_opc_c
,
304 def regex_enum(enum
):
305 assert issubclass(enum
, _enum
.Enum
)
306 return "|".join(item
.name
for item
in enum
)
309 PATTERN_VHDL_BINARY
= r
"(?:2#[01]+#)"
310 PATTERN_DECIMAL
= r
"(?:[0-9]+)"
311 PATTERN_PARTIAL_BINARY
= r
"(?:[01-]+)"
313 # Examples of the entries to be caught by the pattern below:
314 # 2 => (P2, EXTRA3, RA_OR_ZERO, NONE, NONE, RT, NONE, NONE, NONE, Idx1, NONE, NONE, Idx0, NONE, NONE, NONE), -- lwz
315 # -----10110 => (P2, EXTRA3, NONE, FRB, NONE, FRT, NONE, NONE, CR1, NONE, Idx1, NONE, Idx0, NONE, NONE, Idx0), -- fsqrts
316 # 2#0000000000# => (P2, EXTRA3, NONE, NONE, NONE, NONE, NONE, BFA, BF, NONE, NONE, NONE, NONE, NONE, Idx1, Idx0), -- mcrf
319 rf
"(?P<opcode>{PATTERN_VHDL_BINARY}|{PATTERN_DECIMAL}|{PATTERN_PARTIAL_BINARY})",
323 rf
"(?P<ptype>{regex_enum(_SVPtype)})",
324 rf
"(?P<etype>{regex_enum(_SVEtype)})",
325 rf
"(?P<in1>{regex_enum(_In1Sel)})",
326 rf
"(?P<in2>{regex_enum(_In2Sel)})",
327 rf
"(?P<in3>{regex_enum(_In3Sel)})",
328 rf
"(?P<out>{regex_enum(_OutSel)})",
329 rf
"(?P<out2>{regex_enum(_OutSel)})",
330 rf
"(?P<cr_in>{regex_enum(_CRInSel)})",
331 rf
"(?P<cr_out>{regex_enum(_CROutSel)})",
332 rf
"(?P<sv_in1>{regex_enum(_SVEXTRA)})",
333 rf
"(?P<sv_in2>{regex_enum(_SVEXTRA)})",
334 rf
"(?P<sv_in3>{regex_enum(_SVEXTRA)})",
335 rf
"(?P<sv_out>{regex_enum(_SVEXTRA)})",
336 rf
"(?P<sv_out2>{regex_enum(_SVEXTRA)})",
337 rf
"(?P<sv_cr_in>{regex_enum(_SVEXTRA)})",
338 rf
"(?P<sv_cr_out>{regex_enum(_SVEXTRA)})",
343 r
"(?P<name>[A-Za-z0-9_\./]+)",
346 REGEX
= _re
.compile(PATTERN
)
350 FIELDS
= {field
.name
:field
for field
in _dataclasses
.fields(Entry
)}
351 def parse(path
, opcode_cls
):
352 for entry
in ISA
.get_svp64_csv(path
):
353 # skip instructions that are not suitable
354 name
= entry
["name"] = entry
.pop("comment").split("=")[-1]
355 if name
.startswith("l") and name
.endswith("br"):
357 if name
in {"mcrxr", "mcrxrx", "darn"}:
359 if name
in {"bctar", "bcctr"}:
363 if name
in {"setvl"}:
366 entry
= {key
.lower().replace(" ", "_"):value
for (key
, value
) in entry
.items()}
367 for (key
, value
) in tuple(entry
.items()):
368 key
= key
.lower().replace(" ", "_")
369 if key
not in FIELDS
:
373 if issubclass(field
.type, _enum
.Enum
):
374 value
= {item
.name
:item
for item
in field
.type}[value
]
375 elif issubclass(field
.type, Opcode
):
376 value
= opcode_cls(value
)
378 value
= field
.type(value
)
387 "minor_19.csv": IntegerOpcode
,
388 "minor_30.csv": IntegerOpcode
,
389 "minor_31.csv": IntegerOpcode
,
390 "minor_58.csv": IntegerOpcode
,
391 "minor_62.csv": IntegerOpcode
,
392 "minor_22.csv": IntegerOpcode
,
393 "minor_5.csv": PatternOpcode
,
394 "minor_63.csv": PatternOpcode
,
395 "minor_59.csv": PatternOpcode
,
396 "major.csv": IntegerOpcode
,
397 "extra.csv": PatternOpcode
,
399 for (path
, opcode_cls
) in table
.items():
400 entries
.extend(parse(path
, opcode_cls
))
401 entries
= sorted(frozenset(entries
))
403 for line
in codegen
.generate(entries
):
407 if __name__
== "__main__":
408 parser
= _argparse
.ArgumentParser()
409 parser
.add_argument("codegen", type=Codegen
, choices
=Codegen
, help="code generator")
411 args
= vars(parser
.parse_args())