2 import argparse
as _argparse
3 import dataclasses
as _dataclasses
6 from openpower
.decoder
.power_enums
import (
12 CROutSel
as _CROutSel
,
18 from openpower
.consts
import SVP64MODE
as _SVP64MODE
19 from openpower
.decoder
.power_svp64
import SVP64RM
as _SVP64RM
24 " * this file is auto-generated, do not edit",
25 " * https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/sv/sv_binutils.py",
26 " * part of Libre-SOC, sponsored by NLnet",
32 return map(lambda string
: (" " + string
), strings
)
35 class CTypeMeta(type):
45 class CType(metaclass
=CTypeMeta
):
47 def c_value(self
, prefix
="", suffix
=""):
51 class EnumMeta(_enum
.EnumMeta
, CTypeMeta
):
52 def __call__(metacls
, name
, entries
, tag
=None, **kwargs
):
53 if isinstance(entries
, type) and issubclass(entries
, _enum
.Enum
):
54 entries
= dict(entries
.__members
__)
55 if isinstance(entries
, dict):
56 entries
= tuple(entries
.items())
58 tag
= f
"svp64_{name.lower()}"
60 cls
= super().__call
__(value
=name
, names
=entries
, **kwargs
)
69 class Enum(CType
, _enum
.Enum
, metaclass
=EnumMeta
):
72 yield f
"enum {cls.c_tag} {{"
74 yield from indent(item
.c_value(suffix
=","))
77 def c_value(self
, prefix
="", suffix
=""):
78 yield f
"{prefix}{self.__class__.c_tag.upper()}_{self.name.upper()}{suffix}"
82 yield f
"enum {cls.c_tag} {name}"
85 In1Sel
= Enum("In1Sel", _In1Sel
)
86 In2Sel
= Enum("In2Sel", _In2Sel
)
87 In3Sel
= Enum("In3Sel", _In3Sel
)
88 OutSel
= Enum("OutSel", _OutSel
)
89 CRInSel
= Enum("CRInSel", _CRInSel
)
90 CROutSel
= Enum("CROutSel", _CROutSel
)
91 SVPType
= Enum("SVPType", _SVPtype
)
92 SVEType
= Enum("SVEType", _SVEtype
)
93 SVEXTRA
= Enum("SVEXTRA", _SVEXTRA
)
96 class Constant(CType
, _enum
.Enum
, metaclass
=EnumMeta
):
99 yield f
"/* {cls.c_tag.upper()} constants */"
100 for (key
, item
) in cls
.__members
__.items():
101 key
= f
"{cls.c_tag.upper()}_{key.upper()}"
102 value
= f
"0x{item.value:08x}U"
103 yield f
"#define {key} {value}"
105 def c_value(self
, prefix
="", suffix
=""):
106 yield f
"{prefix}{self.__class__.c_tag.upper()}_{self.name.upper()}{suffix}"
109 Mode
= Constant("Mode", _SVP64MODE
)
112 class StructMeta(CTypeMeta
):
113 def __new__(metacls
, name
, bases
, attrs
, tag
=None):
115 tag
= f
"svp64_{name.lower()}"
117 cls
= super().__new
__(metacls
, name
, bases
, attrs
)
127 yield f
"struct {cls.c_tag} {{"
128 for field
in _dataclasses
.fields(cls
):
129 yield from indent(field
.type.c_var(name
=f
"{field.name};"))
132 def c_var(cls
, name
):
133 yield f
"struct {cls.c_tag} {name}"
136 @_dataclasses.dataclass(eq
=True, frozen
=True)
137 class Struct(CType
, metaclass
=StructMeta
):
138 def c_value(self
, prefix
="", suffix
=""):
140 for field
in _dataclasses
.fields(self
):
142 attr
= getattr(self
, name
)
143 yield from indent(attr
.c_value(prefix
=f
".{name} = ", suffix
=","))
147 class IntegerMeta(CTypeMeta
):
148 def __new__(metacls
, name
, bases
, attrs
, typedef
=None):
149 cls
= super().__new
__(metacls
, name
, bases
, attrs
)
150 cls
.__typedef
= typedef
159 yield "#include <stdint.h>"
161 def c_var(cls
, name
):
162 yield f
"{cls.c_typedef} {name}"
165 class Integer(CType
, int, metaclass
=IntegerMeta
):
166 def c_value(self
, prefix
="", suffix
=""):
167 yield f
"{prefix}{self}{suffix}"
171 def __init__(self
, value
, mask
, bits
):
176 return super().__init
__()
191 fmt
= f
"{{value:0{self.bits}b}}:{{mask:0{self.bits}b}}"
192 return fmt
.format(value
=self
.value
, mask
=self
.mask
)
194 def __lt__(self
, other
):
195 if not isinstance(other
, self
.__class
__):
196 return NotImplemented
198 return self
.__value
< other
.__value
202 yield f
"struct svp64_opcode {{"
209 def c_value(self
, prefix
="", suffix
=""):
212 f
".value = UINT32_C(0x{self.value:08X}),",
213 f
".mask = UINT32_C(0x{self.mask:08X}),",
218 def c_var(cls
, name
):
219 yield f
"struct svp64_opcode {name}"
222 class IntegerOpcode(Opcode
):
223 def __init__(self
, integer
):
224 value
= int(integer
, 0)
225 bits
= max(1, value
.bit_length())
226 mask
= int(("1" * bits
), 2)
228 return super().__init
__(value
=value
, mask
=mask
, bits
=bits
)
231 class PatternOpcode(Opcode
):
232 def __init__(self
, pattern
):
237 value |
= (bit
== "1")
244 return super().__init
__(value
=value
, mask
=mask
, bits
=bits
)
247 class Name(CType
, str):
249 escaped
= self
.replace("\"", "\\\"")
250 return f
"\"{escaped}\""
252 def c_value(self
, prefix
="", suffix
=""):
253 yield f
"{prefix}{self!r}{suffix}"
256 def c_var(cls
, name
):
257 yield f
"const char *{name}"
260 @_dataclasses.dataclass(eq
=True, frozen
=True)
261 class Record(Struct
):
282 yield f
"struct svp64_record {{"
283 for field
in _dataclasses
.fields(cls
):
284 bits
= len(field
.type).bit_length()
285 yield from indent([f
"uint64_t {field.name} : {bits};"])
287 bits_rsvd
= (64 - (bits_all
% 64))
289 yield from indent([f
"uint64_t : {bits_rsvd};"])
293 @_dataclasses.dataclass(eq
=True, frozen
=True)
298 def __lt__(self
, other
):
299 if not isinstance(other
, self
.__class
__):
300 return NotImplemented
302 return self
.name
< other
.name
305 class Codegen(_enum
.Enum
):
306 PPC_SVP64_H
= _enum
.auto()
307 PPC_SVP64_OPC_C
= _enum
.auto()
310 def _missing_(cls
, value
):
312 "ppc-svp64.h": Codegen
.PPC_SVP64_H
,
313 "ppc-svp64-opc.c": Codegen
.PPC_SVP64_OPC_C
,
318 Codegen
.PPC_SVP64_H
: "ppc-svp64.h",
319 Codegen
.PPC_SVP64_OPC_C
: "ppc-svp64-opc.c",
322 def generate(self
, entries
):
323 def ppc_svp64_h(entries
):
324 yield from DISCLAIMER
327 yield f
"#ifndef {self.name}"
328 yield f
"#define {self.name}"
331 yield "#include <stdint.h>"
334 yield "#ifdef __cplusplus"
335 yield "extern \"C\" {"
340 In1Sel
, In2Sel
, In3Sel
, OutSel
,
342 SVPType
, SVEType
, SVEXTRA
,
346 yield from enum
.c_decl()
349 yield from Record
.c_decl()
352 for name
in ("in1", "in2", "in3", "out", "out2", "cr_in", "cr_out"):
353 yield "unsigned char"
354 yield f
"svp64_record_{name}_opsel(const struct svp64_record *record);"
357 yield from Entry
.c_decl()
360 yield "extern const struct svp64_entry svp64_entries[];"
361 yield "extern const unsigned int svp64_num_entries;"
364 yield f
"#define SVP64_NAME_MAX {max(map(lambda entry: len(entry.name), entries))}"
367 yield "#ifdef __cplusplus"
372 yield f
"#endif /* {self.name} */"
375 def ppc_svp64_opc_c(entries
):
376 yield from DISCLAIMER
379 yield "#include \"opcode/ppc-svp64.h\""
382 def opsel(enum
, name
, table
):
383 sep
= (max(map(len, list(table
.values()) + ["UNUSED"])) + 1)
384 c_tag
= f
"svp64_{enum.__name__.lower()}"
385 yield "unsigned char"
386 yield f
"svp64_record_{name}_opsel(const struct svp64_record *record)"
388 yield from indent(["static const unsigned char table[] = {"])
390 value
= table
.get(key
, "UNUSED")
391 c_value
= f
"{c_tag.upper()}_{key.name.upper()}"
392 yield from indent(indent([f
"{value:{sep}}, /* {c_value} */"]))
393 yield from indent(["};"])
395 yield from indent([f
"return table[record->{name}];"])
399 yield from opsel(In1Sel
, "in1", {
401 In1Sel
.RA_OR_ZERO
: "RA",
407 yield from opsel(In2Sel
, "in2", {
413 yield from opsel(In3Sel
, "in3", {
421 for name
in ("out", "out2"):
422 yield from opsel(OutSel
, name
, {
426 OutSel
.RT_OR_ZERO
: "RT",
430 yield from opsel(CRInSel
, "cr_in", {
434 CRInSel
.WHOLE_REG
: "FXM",
436 yield from opsel(CROutSel
, "cr_out", {
439 CROutSel
.WHOLE_REG
: "FXM",
442 yield "const struct svp64_entry svp64_entries[] = {"
443 for (index
, entry
) in enumerate(entries
):
444 yield from indent(entry
.c_value(prefix
=f
"[{index}] = ", suffix
=","))
448 yield "const unsigned int svp64_num_entries = \\"
449 yield " sizeof (svp64_entries) / sizeof (svp64_entries[0]);"
453 Codegen
.PPC_SVP64_H
: ppc_svp64_h
,
454 Codegen
.PPC_SVP64_OPC_C
: ppc_svp64_opc_c
,
459 FIELDS
= {field
.name
:field
.type for field
in _dataclasses
.fields(Record
)}
460 FIELDS
.update({field
.name
:field
.type for field
in _dataclasses
.fields(Entry
)})
462 def parse(path
, opcode_cls
):
465 def name_filter(name
):
466 if name
.startswith("l") and name
.endswith("br"):
468 if name
in {"mcrxr", "mcrxrx", "darn"}:
470 if name
in {"bctar", "bcctr"}:
474 if name
in {"setvl"}:
483 def item_mapper(item
):
485 key
= key
.lower().replace(" ", "_")
486 cls
= FIELDS
.get(key
, object)
487 if not isinstance(value
, cls
):
488 if issubclass(cls
, _enum
.Enum
):
489 value
= {item
.name
:item
for item
in cls
}[value
]
494 def item_filter(item
):
496 return (key
in FIELDS
)
498 for record
in ISA
.get_svp64_csv(path
):
499 opcode
= opcode_cls(record
.pop("opcode"))
500 names
= record
.pop("comment").split("=")[-1].split("/")
501 names
= set(filter(name_filter
, names
))
503 rc
= _RC
[record
["rc"] if record
["rc"] else "NONE"]
505 names
.update({f
"{name}." for name
in names
})
506 record
= dict(filter(item_filter
, map(item_mapper
, record
.items())))
507 for name
in map(Name
, names
):
508 yield Entry(name
=name
, record
=Record(**record
))
514 "minor_19.csv": IntegerOpcode
,
515 "minor_30.csv": IntegerOpcode
,
516 "minor_31.csv": IntegerOpcode
,
517 "minor_58.csv": IntegerOpcode
,
518 "minor_62.csv": IntegerOpcode
,
519 "minor_22.csv": IntegerOpcode
,
520 "minor_5.csv": PatternOpcode
,
521 "minor_63.csv": PatternOpcode
,
522 "minor_59.csv": PatternOpcode
,
523 "major.csv": IntegerOpcode
,
524 "extra.csv": PatternOpcode
,
526 for (path
, opcode_cls
) in table
.items():
527 entries
.extend(parse(path
, opcode_cls
))
528 entries
= sorted(frozenset(entries
))
530 for line
in codegen
.generate(entries
):
534 if __name__
== "__main__":
535 parser
= _argparse
.ArgumentParser()
536 parser
.add_argument("codegen", type=Codegen
, choices
=Codegen
, help="code generator")
538 args
= vars(parser
.parse_args())