2 import argparse
as _argparse
3 import dataclasses
as _dataclasses
6 from openpower
.decoder
.power_enums
import (
12 CROutSel
as _CROutSel
,
17 from openpower
.decoder
.power_svp64
import SVP64RM
as _SVP64RM
22 " * this file is auto-generated, do not edit",
23 " * https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/sv/sv_binutils.py",
24 " * part of Libre-SOC, sponsored by NLnet",
30 return map(lambda string
: (" " + string
), strings
)
36 def c_decl(self
, name
):
40 def c_value(self
, prefix
="", suffix
=""):
45 def c_var(self
, name
):
49 class Enum(CType
, _enum
.Enum
):
52 c_tag
= f
"svp64_{cls.__name__.lower()}"
53 yield f
"enum {c_tag} {{"
55 yield from indent(item
.c_value(suffix
=","))
58 def c_value(self
, prefix
="", suffix
=""):
59 c_tag
= f
"svp64_{self.__class__.__name__.lower()}"
60 yield f
"{prefix}{c_tag.upper()}_{self.name.upper()}{suffix}"
64 c_tag
= f
"svp64_{cls.__name__.lower()}"
65 yield f
"enum {c_tag} {name}"
68 # Python forbids inheriting from enum unless it's empty.
69 In1Sel
= Enum("In1Sel", {item
.name
:item
.value
for item
in _In1Sel
})
70 In2Sel
= Enum("In2Sel", {item
.name
:item
.value
for item
in _In2Sel
})
71 In3Sel
= Enum("In3Sel", {item
.name
:item
.value
for item
in _In3Sel
})
72 OutSel
= Enum("OutSel", {item
.name
:item
.value
for item
in _OutSel
})
73 CRInSel
= Enum("CRInSel", {item
.name
:item
.value
for item
in _CRInSel
})
74 CROutSel
= Enum("CROutSel", {item
.name
:item
.value
for item
in _CROutSel
})
75 SVPType
= Enum("SVPType", {item
.name
:item
.value
for item
in _SVPtype
})
76 SVEType
= Enum("SVEType", {item
.name
:item
.value
for item
in _SVEtype
})
77 SVEXTRA
= Enum("SVEXTRA", {item
.name
:item
.value
for item
in _SVEXTRA
})
81 def __init__(self
, value
, mask
, bits
):
86 return super().__init
__()
101 fmt
= f
"{{value:0{self.bits}b}}:{{mask:0{self.bits}b}}"
102 return fmt
.format(value
=self
.value
, mask
=self
.mask
)
104 def __lt__(self
, other
):
105 if not isinstance(other
, self
.__class
__):
106 return NotImplemented
108 return self
.__value
< other
.__value
112 yield f
"struct svp64_opcode {{"
119 def c_value(self
, prefix
="", suffix
=""):
122 f
".value = UINT32_C(0x{self.value:08X}),",
123 f
".mask = UINT32_C(0x{self.mask:08X}),",
128 def c_var(cls
, name
):
129 yield f
"struct svp64_opcode {name}"
132 class IntegerOpcode(Opcode
):
133 def __init__(self
, integer
):
134 value
= int(integer
, 0)
135 bits
= max(1, value
.bit_length())
136 mask
= int(("1" * bits
), 2)
138 return super().__init
__(value
=value
, mask
=mask
, bits
=bits
)
141 class PatternOpcode(Opcode
):
142 def __init__(self
, pattern
):
147 value |
= (bit
== "1")
154 return super().__init
__(value
=value
, mask
=mask
, bits
=bits
)
157 class Name(CType
, str):
159 escaped
= self
.replace("\"", "\\\"")
160 return f
"\"{escaped}\""
162 def c_value(self
, prefix
="", suffix
=""):
163 yield f
"{prefix}{self!r}{suffix}"
166 def c_var(cls
, name
):
167 yield f
"const char *{name}"
170 @_dataclasses.dataclass(eq
=True, frozen
=True)
192 yield f
"struct svp64_record {{"
193 for field
in _dataclasses
.fields(cls
):
194 bits
= len(field
.type).bit_length()
195 yield from indent([f
"uint64_t {field.name} : {bits};"])
197 bits_rsvd
= (64 - (bits_all
% 64))
199 yield from indent([f
"uint64_t : {bits_rsvd};"])
202 def c_value(self
, prefix
="", suffix
=""):
204 for field
in _dataclasses
.fields(self
):
206 attr
= getattr(self
, name
)
207 yield from indent(attr
.c_value(prefix
=f
".{name} = ", suffix
=","))
211 def c_var(cls
, name
):
212 yield f
"struct svp64_record {name}"
215 @_dataclasses.dataclass(eq
=True, frozen
=True)
220 def __lt__(self
, other
):
221 if not isinstance(other
, self
.__class
__):
222 return NotImplemented
224 return self
.name
< other
.name
228 yield f
"struct svp64_entry {{"
229 for field
in _dataclasses
.fields(cls
):
230 yield from indent(field
.type.c_var(name
=f
"{field.name};"))
233 def c_value(self
, prefix
="", suffix
=""):
235 for field
in _dataclasses
.fields(self
):
237 attr
= getattr(self
, name
)
238 yield from indent(attr
.c_value(prefix
=f
".{name} = ", suffix
=","))
242 def c_var(cls
, name
):
243 yield f
"struct svp64_entry {name}"
246 class Codegen(_enum
.Enum
):
247 PPC_SVP64_H
= _enum
.auto()
248 PPC_SVP64_OPC_C
= _enum
.auto()
251 def _missing_(cls
, value
):
253 "ppc-svp64.h": Codegen
.PPC_SVP64_H
,
254 "ppc-svp64-opc.c": Codegen
.PPC_SVP64_OPC_C
,
259 Codegen
.PPC_SVP64_H
: "ppc-svp64.h",
260 Codegen
.PPC_SVP64_OPC_C
: "ppc-svp64-opc.c",
263 def generate(self
, entries
):
264 def ppc_svp64_h(entries
):
265 yield from DISCLAIMER
268 yield f
"#ifndef {self.name}"
269 yield f
"#define {self.name}"
272 yield "#include <stdint.h>"
275 yield "#ifdef __cplusplus"
276 yield "extern \"C\" {"
281 In1Sel
, In2Sel
, In3Sel
, OutSel
,
283 SVPType
, SVEType
, SVEXTRA
,
286 yield from enum
.c_decl()
289 yield from Record
.c_decl()
292 yield from Entry
.c_decl()
295 yield "extern const struct svp64_entry svp64_entries[];"
296 yield "extern const unsigned int svp64_num_entries;"
299 yield f
"#define SVP64_NAME_MAX {max(map(lambda entry: len(entry.name), entries))}"
302 yield "#ifdef __cplusplus"
307 yield f
"#endif /* {self.name} */"
310 def ppc_svp64_opc_c(entries
):
311 yield from DISCLAIMER
314 yield "#include \"opcode/ppc-svp64.h\""
317 yield "const struct svp64_entry svp64_entries[] = {"
318 for (index
, entry
) in enumerate(entries
):
319 yield from indent(entry
.c_value(prefix
=f
"[{index}] = ", suffix
=","))
323 yield "const unsigned int svp64_num_entries = \\"
324 yield " sizeof (svp64_entries) / sizeof (svp64_entries[0]);"
328 Codegen
.PPC_SVP64_H
: ppc_svp64_h
,
329 Codegen
.PPC_SVP64_OPC_C
: ppc_svp64_opc_c
,
334 FIELDS
= {field
.name
:field
for field
in _dataclasses
.fields(Record
)}
335 FIELDS
.update({field
.name
:field
for field
in _dataclasses
.fields(Entry
)})
336 def parse(path
, opcode_cls
):
338 for record
in ISA
.get_svp64_csv(path
):
339 opcode
= opcode_cls(record
.pop("opcode"))
340 names
= record
.pop("comment").split("=")[-1]
341 for name
in map(Name
, names
.split("/")):
342 if name
.startswith("l") and name
.endswith("br"):
344 if name
in {"mcrxr", "mcrxrx", "darn"}:
346 if name
in {"bctar", "bcctr"}:
350 if name
in {"setvl"}:
353 record
= {key
.lower().replace(" ", "_"):value
for (key
, value
) in record
.items()}
354 for (key
, value
) in tuple(record
.items()):
355 key
= key
.lower().replace(" ", "_")
356 if key
not in FIELDS
:
361 if not isinstance(value
, field
.type):
362 if issubclass(field
.type, _enum
.Enum
):
363 value
= {item
.name
:item
for item
in field
.type}[value
]
365 value
= field
.type(value
)
369 if name
not in visited
:
370 yield Entry(name
=name
, record
=Record(**record
))
378 "minor_19.csv": IntegerOpcode
,
379 "minor_30.csv": IntegerOpcode
,
380 "minor_31.csv": IntegerOpcode
,
381 "minor_58.csv": IntegerOpcode
,
382 "minor_62.csv": IntegerOpcode
,
383 "minor_22.csv": IntegerOpcode
,
384 "minor_5.csv": PatternOpcode
,
385 "minor_63.csv": PatternOpcode
,
386 "minor_59.csv": PatternOpcode
,
387 "major.csv": IntegerOpcode
,
388 "extra.csv": PatternOpcode
,
390 for (path
, opcode_cls
) in table
.items():
391 entries
.extend(parse(path
, opcode_cls
))
392 entries
= sorted(frozenset(entries
))
394 for line
in codegen
.generate(entries
):
398 if __name__
== "__main__":
399 parser
= _argparse
.ArgumentParser()
400 parser
.add_argument("codegen", type=Codegen
, choices
=Codegen
, help="code generator")
402 args
= vars(parser
.parse_args())