1c0e4106f202fa85f2ef71379c98fda0ac63c42d
2 import argparse
as _argparse
3 import builtins
as _builtins
4 import dataclasses
as _dataclasses
7 from openpower
.decoder
.power_enums
import (
13 CROutSel
as _CROutSel
,
19 from openpower
.consts
import SVP64MODE
as _SVP64MODE
20 from openpower
.decoder
.power_svp64
import SVP64RM
as _SVP64RM
25 " * this file is auto-generated, do not edit",
26 " * https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/sv/sv_binutils.py",
27 " * part of Libre-SOC, sponsored by NLnet",
33 return map(lambda string
: (" " + string
), strings
)
36 class CTypeMeta(type):
37 def __new__(metacls
, name
, bases
, attrs
, typedef
=None):
38 cls
= super().__new
__(metacls
, name
, bases
, attrs
)
39 cls
.__typedef
= typedef
43 def __getitem__(cls
, size
):
44 name
= f
"{cls.__name__}[{'' if size is Ellipsis else size}]"
45 return type(name
, (Array
,), {}, type=cls
, size
=size
)
55 def c_var(cls
, name
, prefix
="", suffix
=""):
56 yield f
"{prefix}{cls.c_typedef} {name}{suffix}"
59 class ArrayMeta(CTypeMeta
):
60 def __new__(metacls
, name
, bases
, attrs
, type, size
):
61 cls
= super().__new
__(metacls
, name
, bases
, attrs
)
63 cls
.__ellipsis
= (size
is Ellipsis)
64 cls
.__size
= 0 if cls
.__ellipsis
else size
76 size
= "" if cls
.__ellipsis
else f
"{cls.__size}"
77 yield f
"{cls.c_type.c_typedef}[{size}]"
79 def c_var(cls
, name
, prefix
="", suffix
=""):
80 size
= "" if cls
.__ellipsis
else f
"{cls.__size}"
81 yield f
"{prefix}{cls.c_type.c_typedef} {name}[{size}]{suffix}"
84 class CType(metaclass
=CTypeMeta
):
86 def c_value(self
, prefix
="", suffix
=""):
90 class Array(CType
, tuple, metaclass
=ArrayMeta
, type=CType
, size
=0):
91 def c_value(self
, prefix
="", suffix
=""):
93 for (index
, item
) in enumerate(self
):
94 yield from indent(item
.c_value(prefix
=f
"[{index}] = ", suffix
=","))
98 class EnumMeta(_enum
.EnumMeta
, CTypeMeta
):
99 def __call__(metacls
, name
, entries
, tag
=None, **kwargs
):
100 if isinstance(entries
, type) and issubclass(entries
, _enum
.Enum
):
101 entries
= dict(entries
.__members
__)
102 if isinstance(entries
, dict):
103 entries
= tuple(entries
.items())
105 tag
= f
"svp64_{name.lower()}"
107 cls
= super().__call
__(value
=name
, names
=entries
, **kwargs
)
113 return f
"enum {cls.c_tag}"
119 def c_var(cls
, name
, prefix
="", suffix
=""):
120 yield f
"{prefix}{cls.c_typedef} {name}{suffix}"
123 class Enum(CType
, _enum
.Enum
, metaclass
=EnumMeta
):
126 yield f
"{cls.c_typedef} {{"
128 yield from indent(item
.c_value(suffix
=","))
131 def c_value(self
, prefix
="", suffix
=""):
132 yield f
"{prefix}{self.__class__.c_tag.upper()}_{self.name.upper()}{suffix}"
135 In1Sel
= Enum("In1Sel", _In1Sel
)
136 In2Sel
= Enum("In2Sel", _In2Sel
)
137 In3Sel
= Enum("In3Sel", _In3Sel
)
138 OutSel
= Enum("OutSel", _OutSel
)
139 CRInSel
= Enum("CRInSel", _CRInSel
)
140 CROutSel
= Enum("CROutSel", _CROutSel
)
141 SVPType
= Enum("SVPType", _SVPtype
)
142 SVEType
= Enum("SVEType", _SVEtype
)
143 SVEXTRA
= Enum("SVEXTRA", _SVEXTRA
)
146 class Constant(CType
, _enum
.Enum
, metaclass
=EnumMeta
):
149 yield f
"/* {cls.c_tag.upper()} constants */"
150 for (key
, item
) in cls
.__members
__.items():
151 key
= f
"{cls.c_tag.upper()}_{key.upper()}"
152 value
= f
"0x{item.value:08x}U"
153 yield f
"#define {key} {value}"
155 def c_value(self
, prefix
="", suffix
=""):
156 yield f
"{prefix}{self.__class__.c_tag.upper()}_{self.name.upper()}{suffix}"
159 Mode
= Constant("Mode", _SVP64MODE
)
162 class StructMeta(CTypeMeta
):
163 def __new__(metacls
, name
, bases
, attrs
, tag
=None, **kwargs
):
165 tag
= f
"svp64_{name.lower()}"
166 if "typedef" not in kwargs
:
167 kwargs
["typedef"] = f
"struct {tag}"
169 cls
= super().__new
__(metacls
, name
, bases
, attrs
, **kwargs
)
179 yield f
"{cls.c_typedef} {{"
180 for field
in _dataclasses
.fields(cls
):
181 yield from indent(field
.type.c_var(name
=f
"{field.name}", suffix
=";"))
185 @_dataclasses.dataclass(eq
=True, frozen
=True)
186 class Struct(CType
, metaclass
=StructMeta
):
187 def c_value(self
, prefix
="", suffix
=""):
189 for field
in _dataclasses
.fields(self
):
191 attr
= getattr(self
, name
)
192 yield from indent(attr
.c_value(prefix
=f
".{name} = ", suffix
=","))
196 class Integer(CType
, int):
197 def c_value(self
, prefix
="", suffix
=""):
198 yield f
"{prefix}{self}{suffix}"
201 class Byte(Integer
, typedef
="uint8_t"):
205 class Size(Integer
, typedef
="size_t"):
209 class Name(CType
, str):
211 escaped
= self
.replace("\"", "\\\"")
212 return f
"\"{escaped}\""
214 def c_value(self
, prefix
="", suffix
=""):
215 yield f
"{prefix}{self!r}{suffix}"
218 def c_var(cls
, name
, prefix
="", suffix
=""):
219 yield f
"{prefix}const char *{name}{suffix}"
222 @_dataclasses.dataclass(eq
=True, frozen
=True)
223 class Record(Struct
):
244 yield f
"struct svp64_record {{"
245 for field
in _dataclasses
.fields(cls
):
246 bits
= len(field
.type).bit_length()
247 yield from indent([f
"uint64_t {field.name} : {bits};"])
249 bits_rsvd
= (64 - (bits_all
% 64))
251 yield from indent([f
"uint64_t : {bits_rsvd};"])
255 @_dataclasses.dataclass(eq
=True, frozen
=True)
260 def __lt__(self
, other
):
261 if not isinstance(other
, self
.__class
__):
262 return NotImplemented
264 return self
.name
< other
.name
267 class Codegen(_enum
.Enum
):
268 PPC_SVP64_H
= _enum
.auto()
269 PPC_SVP64_OPC_C
= _enum
.auto()
272 def _missing_(cls
, value
):
274 "ppc-svp64.h": Codegen
.PPC_SVP64_H
,
275 "ppc-svp64-opc.c": Codegen
.PPC_SVP64_OPC_C
,
280 Codegen
.PPC_SVP64_H
: "ppc-svp64.h",
281 Codegen
.PPC_SVP64_OPC_C
: "ppc-svp64-opc.c",
284 def generate(self
, entries
):
285 def ppc_svp64_h(entries
):
286 yield from DISCLAIMER
289 yield f
"#ifndef {self.name}"
290 yield f
"#define {self.name}"
293 yield "#include <stdint.h>"
296 yield "#ifdef __cplusplus"
297 yield "extern \"C\" {"
302 In1Sel
, In2Sel
, In3Sel
, OutSel
,
304 SVPType
, SVEType
, SVEXTRA
,
308 yield from enum
.c_decl()
311 yield from Record
.c_decl()
314 for name
in ("in1", "in2", "in3", "out", "out2", "cr_in", "cr_out"):
315 yield "unsigned char"
316 yield f
"svp64_record_{name}_opsel(const struct svp64_record *record);"
319 yield from Entry
.c_decl()
322 yield "extern const struct svp64_entry svp64_entries[];"
323 yield "extern const unsigned int svp64_num_entries;"
326 yield f
"#define SVP64_NAME_MAX {max(map(lambda entry: len(entry.name), entries))}"
329 yield "#ifdef __cplusplus"
334 yield f
"#endif /* {self.name} */"
337 def ppc_svp64_opc_c(entries
):
338 yield from DISCLAIMER
341 yield "#include \"opcode/ppc-svp64.h\""
344 def opsel(enum
, name
, table
):
345 sep
= (max(map(len, list(table
.values()) + ["UNUSED"])) + 1)
346 c_tag
= f
"svp64_{enum.__name__.lower()}"
347 yield "unsigned char"
348 yield f
"svp64_record_{name}_opsel(const struct svp64_record *record)"
350 yield from indent(["static const unsigned char table[] = {"])
352 value
= table
.get(key
, "UNUSED")
353 c_value
= f
"{c_tag.upper()}_{key.name.upper()}"
354 yield from indent(indent([f
"{value:{sep}}, /* {c_value} */"]))
355 yield from indent(["};"])
357 yield from indent([f
"return table[record->{name}];"])
361 yield from opsel(In1Sel
, "in1", {
363 In1Sel
.RA_OR_ZERO
: "RA",
369 yield from opsel(In2Sel
, "in2", {
375 yield from opsel(In3Sel
, "in3", {
383 for name
in ("out", "out2"):
384 yield from opsel(OutSel
, name
, {
388 OutSel
.RT_OR_ZERO
: "RT",
392 yield from opsel(CRInSel
, "cr_in", {
396 CRInSel
.WHOLE_REG
: "FXM",
398 yield from opsel(CROutSel
, "cr_out", {
401 CROutSel
.WHOLE_REG
: "FXM",
404 yield "const struct svp64_entry svp64_entries[] = {"
405 for (index
, entry
) in enumerate(entries
):
406 yield from indent(entry
.c_value(prefix
=f
"[{index}] = ", suffix
=","))
410 yield "const unsigned int svp64_num_entries = \\"
411 yield " sizeof (svp64_entries) / sizeof (svp64_entries[0]);"
415 Codegen
.PPC_SVP64_H
: ppc_svp64_h
,
416 Codegen
.PPC_SVP64_OPC_C
: ppc_svp64_opc_c
,
421 FIELDS
= {field
.name
:field
.type for field
in _dataclasses
.fields(Record
)}
422 FIELDS
.update({field
.name
:field
.type for field
in _dataclasses
.fields(Entry
)})
427 def name_filter(name
):
428 if name
.startswith("l") and name
.endswith("br"):
430 if name
in {"mcrxr", "mcrxrx", "darn"}:
432 if name
in {"bctar", "bcctr"}:
436 if name
in {"setvl"}:
445 def item_mapper(item
):
447 key
= key
.lower().replace(" ", "_")
448 cls
= FIELDS
.get(key
, object)
449 if not isinstance(value
, cls
):
450 if issubclass(cls
, _enum
.Enum
):
451 value
= {item
.name
:item
for item
in cls
}[value
]
456 def item_filter(item
):
458 return (key
in FIELDS
)
460 for record
in ISA
.get_svp64_csv(path
):
461 names
= record
.pop("comment").split("=")[-1].split("/")
462 names
= set(filter(name_filter
, names
))
464 rc
= _RC
[record
["rc"] if record
["rc"] else "NONE"]
466 names
.update({f
"{name}." for name
in names
})
467 record
= dict(filter(item_filter
, map(item_mapper
, record
.items())))
468 for name
in map(Name
, names
):
469 yield Entry(name
=name
, record
=Record(**record
))
488 entries
.extend(parse(path
))
489 entries
= sorted(frozenset(entries
))
491 for line
in codegen
.generate(entries
):
495 if __name__
== "__main__":
496 parser
= _argparse
.ArgumentParser()
497 parser
.add_argument("codegen", type=Codegen
, choices
=Codegen
, help="code generator")
499 args
= vars(parser
.parse_args())