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
20 from openpower
.decoder
.isa
.caller
import SVP64RMFields
as _SVP64RMFields
21 from openpower
.decoder
.isa
.caller
import SVP64PrefixFields
as _SVP64PrefixFields
22 from openpower
.decoder
.selectable_int
import SelectableIntMapping
27 " * this file is auto-generated, do not edit",
28 " * https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/sv/sv_binutils.py",
29 " * part of Libre-SOC, sponsored by NLnet",
35 return map(lambda string
: (" " + string
), strings
)
38 class CTypeMeta(type):
39 def __new__(metacls
, name
, bases
, attrs
, typedef
=None):
40 cls
= super().__new
__(metacls
, name
, bases
, attrs
)
41 cls
.__typedef
= typedef
45 def __getitem__(cls
, size
):
46 name
= f
"{cls.__name__}[{'' if size is Ellipsis else size}]"
47 return type(name
, (Array
,), {}, type=cls
, size
=size
)
57 def c_var(cls
, name
, prefix
="", suffix
=""):
58 yield f
"{prefix}{cls.c_typedef} {name}{suffix}"
61 class ArrayMeta(CTypeMeta
):
62 def __new__(metacls
, name
, bases
, attrs
, type, size
, **kwargs
):
63 cls
= super().__new
__(metacls
, name
, bases
, attrs
, **kwargs
)
65 cls
.__ellipsis
= (size
is Ellipsis)
66 cls
.__size
= 0 if cls
.__ellipsis
else size
74 size
= "" if cls
.__ellipsis
else f
"{cls.__size}"
75 yield f
"{cls.__type.c_typedef}[{size}]"
77 def c_var(cls
, name
, prefix
="", suffix
=""):
78 size
= "" if cls
.__ellipsis
else f
"{cls.__size}"
79 yield f
"{prefix}{cls.__type.c_typedef} {name}[{size}]{suffix}"
82 class BitmapMeta(CTypeMeta
):
83 def __new__(metacls
, name
, bases
, attrs
, typedef
="uint64_t", bits
=0, **kwargs
):
84 cls
= super().__new
__(metacls
, name
, bases
, attrs
, typedef
=typedef
, **kwargs
)
91 def c_var(cls
, name
, prefix
="", suffix
=""):
92 yield f
"{prefix}{cls.c_typedef} {name} : {cls.__bits}{suffix}"
95 class CType(metaclass
=CTypeMeta
):
97 def c_value(self
, prefix
="", suffix
=""):
101 class Array(CType
, tuple, metaclass
=ArrayMeta
, type=CType
, size
=...):
102 def c_value(self
, prefix
="", suffix
=""):
104 for (index
, item
) in enumerate(self
):
105 yield from indent(item
.c_value(prefix
=f
"[{index}] = ", suffix
=","))
109 class Bitmap(metaclass
=BitmapMeta
):
113 class EnumMeta(_enum
.EnumMeta
, CTypeMeta
):
114 def __call__(metacls
, name
, entries
, tag
=None, **kwargs
):
115 if isinstance(entries
, type) and issubclass(entries
, _enum
.Enum
):
116 entries
= dict(entries
.__members
__)
117 if isinstance(entries
, dict):
118 entries
= tuple(entries
.items())
120 tag
= f
"svp64_{name.lower()}"
122 cls
= super().__call
__(value
=name
, names
=entries
, **kwargs
)
128 return f
"enum {cls.c_tag}"
134 def c_var(cls
, name
, prefix
="", suffix
=""):
135 yield f
"{prefix}{cls.c_typedef} {name}{suffix}"
138 class Enum(CType
, _enum
.Enum
, metaclass
=EnumMeta
):
141 return f
"{self.__class__.c_tag.upper()}_{self.name.upper()}"
145 yield f
"{cls.c_typedef} {{"
147 yield from indent(item
.c_value(suffix
=","))
150 def c_value(self
, prefix
="", suffix
=""):
151 yield f
"{prefix}{self.c_name}{suffix}"
154 In1Sel
= Enum("In1Sel", _In1Sel
)
155 In2Sel
= Enum("In2Sel", _In2Sel
)
156 In3Sel
= Enum("In3Sel", _In3Sel
)
157 OutSel
= Enum("OutSel", _OutSel
)
158 CRInSel
= Enum("CRInSel", _CRInSel
)
159 CROutSel
= Enum("CROutSel", _CROutSel
)
160 SVPType
= Enum("SVPType", _SVPtype
)
161 SVEType
= Enum("SVEType", _SVEtype
)
162 SVEXTRA
= Enum("SVEXTRA", _SVEXTRA
)
165 class Constant(CType
, _enum
.Enum
, metaclass
=EnumMeta
):
168 yield f
"/* {cls.c_tag.upper()} constants */"
169 for (key
, item
) in cls
.__members
__.items():
170 key
= f
"{cls.c_tag.upper()}_{key.upper()}"
171 value
= f
"0x{item.value:08x}U"
172 yield f
"#define {key} {value}"
174 def c_value(self
, prefix
="", suffix
=""):
175 yield f
"{prefix}{self.__class__.c_tag.upper()}_{self.name.upper()}{suffix}"
178 Mode
= Constant("Mode", _SVP64MODE
)
181 class StructMeta(CTypeMeta
):
182 def __new__(metacls
, name
, bases
, attrs
, tag
=None, **kwargs
):
184 tag
= f
"svp64_{name.lower()}"
185 if "typedef" not in kwargs
:
186 kwargs
["typedef"] = f
"struct {tag}"
188 cls
= super().__new
__(metacls
, name
, bases
, attrs
, **kwargs
)
198 yield f
"{cls.c_typedef} {{"
199 for field
in _dataclasses
.fields(cls
):
200 yield from indent(field
.type.c_var(name
=f
"{field.name}", suffix
=";"))
204 @_dataclasses.dataclass(eq
=True, frozen
=True)
205 class Struct(CType
, metaclass
=StructMeta
):
206 def c_value(self
, prefix
="", suffix
=""):
208 for field
in _dataclasses
.fields(self
):
210 attr
= getattr(self
, name
)
211 yield from indent(attr
.c_value(prefix
=f
".{name} = ", suffix
=","))
215 class Integer(CType
, str):
216 def c_value(self
, prefix
="", suffix
=""):
217 yield f
"{prefix}{self}{suffix}"
220 class Byte(Integer
, typedef
="uint8_t"):
224 class Size(Integer
, typedef
="size_t"):
228 class Name(CType
, str):
230 escaped
= self
.replace("\"", "\\\"")
231 return f
"\"{escaped}\""
233 def c_value(self
, prefix
="", suffix
=""):
234 yield f
"{prefix}{self!r}{suffix}"
237 def c_var(cls
, name
, prefix
="", suffix
=""):
238 yield f
"{prefix}const char *{name}{suffix}"
241 @_dataclasses.dataclass(eq
=True, frozen
=True)
242 class Record(Struct
):
263 yield f
"struct svp64_record {{"
264 for field
in _dataclasses
.fields(cls
):
265 bits
= len(field
.type).bit_length()
266 yield from indent([f
"uint64_t {field.name} : {bits};"])
268 bits_rsvd
= (64 - (bits_all
% 64))
270 yield from indent([f
"uint64_t : {bits_rsvd};"])
274 @_dataclasses.dataclass(eq
=True, frozen
=True)
279 def __lt__(self
, other
):
280 if not isinstance(other
, self
.__class
__):
281 return NotImplemented
283 return self
.name
< other
.name
286 @_dataclasses.dataclass(eq
=True, frozen
=True)
293 class FieldsMeta(CTypeMeta
):
294 def __new__(metacls
, name
, bases
, attrs
, base
=SelectableIntMapping
):
295 def flatten(mapping
, parent
=""):
296 for (key
, value
) in mapping
.items():
297 key
= f
"{parent}_{key}" if parent
else key
298 if isinstance(value
, dict):
299 yield from flatten(mapping
=value
, parent
=key
)
301 yield (key
.upper(), value
)
304 fields
= dict(flatten(mapping
=mapping
))
305 keys
= ((key
, index
) for (index
, key
) in enumerate(fields
))
306 enum_cls
= Enum(name
, entries
=keys
, tag
=f
"svp64_{name.lower()}_type")
310 length
= Size(len(value
))
311 mapping
= Byte
[32](map(lambda bit
: Byte((base
.bits
- 1) - bit
), reversed(value
)))
312 return (key
, Field(length
=length
, mapping
=mapping
))
314 typedef
= mapping
.pop("typedef", Field
.c_typedef
)
315 cls
= super().__new
__(metacls
, name
, bases
, attrs
, typedef
=typedef
)
316 cls
.__enum
= enum_cls
317 cls
.__fields
= dict(map(field
, zip(enum_cls
, fields
.values())))
322 for (key
, value
) in cls
.__fields
.items():
326 yield from cls
.__enum
.c_decl()
328 def c_var(cls
, name
, prefix
="", suffix
=""):
329 yield from Field
.c_var(name
=name
, prefix
=prefix
, suffix
=suffix
)
332 class Fields(metaclass
=FieldsMeta
):
333 def c_value(self
, prefix
="", suffix
=""):
335 for (key
, value
) in self
.__class
__:
336 yield from indent(value
.c_value(prefix
=f
"[{key.c_name}] = ", suffix
=","))
340 class Prefix(Fields
, base
=_SVP64PrefixFields
):
344 class RM(Fields
, base
=_SVP64RMFields
):
348 class Codegen(_enum
.Enum
):
349 PPC_SVP64_H
= _enum
.auto()
350 PPC_SVP64_OPC_C
= _enum
.auto()
353 def _missing_(cls
, value
):
355 "ppc-svp64.h": Codegen
.PPC_SVP64_H
,
356 "ppc-svp64-opc.c": Codegen
.PPC_SVP64_OPC_C
,
361 Codegen
.PPC_SVP64_H
: "ppc-svp64.h",
362 Codegen
.PPC_SVP64_OPC_C
: "ppc-svp64-opc.c",
365 def generate(self
, entries
):
366 def ppc_svp64_h(entries
, num_entries
):
367 yield from DISCLAIMER
370 yield f
"#ifndef {self.name}"
371 yield f
"#define {self.name}"
374 yield "#include <stdint.h>"
377 yield "#ifdef __cplusplus"
378 yield "extern \"C\" {"
383 In1Sel
, In2Sel
, In3Sel
, OutSel
,
385 SVPType
, SVEType
, SVEXTRA
,
389 yield from enum
.c_decl()
392 structs
= (Field
, Record
, Entry
, Prefix
, RM
)
393 for struct
in structs
:
394 yield from struct
.c_decl()
397 for name
in ("in1", "in2", "in3", "out", "out2", "cr_in", "cr_out"):
398 yield "unsigned char"
399 yield f
"svp64_record_{name}_opsel(const struct svp64_record *record);"
402 yield from entries
.__class
__.c_var("svp64_entries", prefix
="extern const ", suffix
=";")
403 yield from num_entries
.__class
__.c_var("svp64_num_entries", prefix
="extern const ", suffix
=";")
406 yield f
"#define SVP64_NAME_MAX {max(map(lambda entry: len(entry.name), entries))}"
409 yield "#ifdef __cplusplus"
414 yield f
"#endif /* {self.name} */"
417 def ppc_svp64_opc_c(entries
, num_entries
):
418 yield from DISCLAIMER
421 yield "#include \"opcode/ppc-svp64.h\""
424 def opsel(enum
, name
, table
):
425 sep
= (max(map(len, list(table
.values()) + ["UNUSED"])) + 1)
426 c_tag
= f
"svp64_{enum.__name__.lower()}"
427 yield "unsigned char"
428 yield f
"svp64_record_{name}_opsel(const struct svp64_record *record)"
430 yield from indent(["static const unsigned char table[] = {"])
432 value
= table
.get(key
, "UNUSED")
433 c_value
= f
"{c_tag.upper()}_{key.name.upper()}"
434 yield from indent(indent([f
"{value:{sep}}, /* {c_value} */"]))
435 yield from indent(["};"])
437 yield from indent([f
"return table[record->{name}];"])
441 yield from opsel(In1Sel
, "in1", {
443 In1Sel
.RA_OR_ZERO
: "RA",
449 yield from opsel(In2Sel
, "in2", {
455 yield from opsel(In3Sel
, "in3", {
463 for name
in ("out", "out2"):
464 yield from opsel(OutSel
, name
, {
468 OutSel
.RT_OR_ZERO
: "RT",
472 yield from opsel(CRInSel
, "cr_in", {
476 CRInSel
.WHOLE_REG
: "FXM",
478 yield from opsel(CROutSel
, "cr_out", {
481 CROutSel
.WHOLE_REG
: "FXM",
484 yield from entries
.__class
__.c_var("svp64_entries", prefix
="const ", suffix
=" = \\")
485 yield from entries
.c_value(prefix
="", suffix
=";")
487 yield from num_entries
.__class
__.c_var("svp64_num_entries", prefix
="const ", suffix
=" = \\")
488 yield from indent(num_entries
.c_value(suffix
=";"))
491 for mapping
in (Prefix
, RM
):
492 name
= mapping
.__name
__.lower()
493 yield from mapping
.c_var(name
=f
"svp64_{name}_entries", prefix
="static ", suffix
="[] = \\")
494 yield from mapping().c_value(suffix
=";")
498 entries
= Entry
[...](entries
)
499 num_entries
= Size("(sizeof (svp64_entries) / sizeof (svp64_entries[0])")
502 Codegen
.PPC_SVP64_H
: ppc_svp64_h
,
503 Codegen
.PPC_SVP64_OPC_C
: ppc_svp64_opc_c
,
504 }[self
](entries
, num_entries
)
508 FIELDS
= {field
.name
:field
.type for field
in _dataclasses
.fields(Record
)}
509 FIELDS
.update({field
.name
:field
.type for field
in _dataclasses
.fields(Entry
)})
514 def name_filter(name
):
515 if name
.startswith("l") and name
.endswith("br"):
517 if name
in {"mcrxr", "mcrxrx", "darn"}:
519 if name
in {"bctar", "bcctr"}:
523 if name
in {"setvl"}:
532 def item_mapper(item
):
534 key
= key
.lower().replace(" ", "_")
535 cls
= FIELDS
.get(key
, object)
536 if not isinstance(value
, cls
):
537 if issubclass(cls
, _enum
.Enum
):
538 value
= {item
.name
:item
for item
in cls
}[value
]
543 def item_filter(item
):
545 return (key
in FIELDS
)
547 for record
in ISA
.get_svp64_csv(path
):
548 names
= record
.pop("comment").split("=")[-1].split("/")
549 names
= set(filter(name_filter
, names
))
551 rc
= _RC
[record
["rc"] if record
["rc"] else "NONE"]
553 names
.update({f
"{name}." for name
in names
})
554 record
= dict(filter(item_filter
, map(item_mapper
, record
.items())))
555 for name
in map(Name
, names
):
556 yield Entry(name
=name
, record
=Record(**record
))
575 entries
.extend(parse(path
))
576 entries
= sorted(frozenset(entries
))
578 for line
in codegen
.generate(entries
):
582 if __name__
== "__main__":
583 parser
= _argparse
.ArgumentParser()
584 parser
.add_argument("codegen", type=Codegen
, choices
=Codegen
, help="code generator")
586 args
= vars(parser
.parse_args())