a3c61958ce837f865ef3ca33b87a9454bfca1558
2 import argparse
as _argparse
3 import dataclasses
as _dataclasses
5 import operator
as _operator
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
21 from openpower
.decoder
.isa
.caller
import SVP64RMFields
as _SVP64RMFields
22 from openpower
.decoder
.isa
.caller
import SVP64PrefixFields
as _SVP64PrefixFields
23 from openpower
.decoder
.selectable_int
import SelectableIntMapping
28 " * this file is auto-generated, do not edit",
29 " * https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/sv/sv_binutils.py",
30 " * part of Libre-SOC, sponsored by NLnet",
36 return map(lambda string
: (" " + string
), strings
)
39 class CTypeMeta(type):
40 def __new__(metacls
, name
, bases
, attrs
, typedef
=None):
41 cls
= super().__new
__(metacls
, name
, bases
, attrs
)
42 cls
.__typedef
= typedef
46 def __getitem__(cls
, size
):
47 name
= f
"{cls.__name__}[{'' if size is Ellipsis else size}]"
48 return type(name
, (Array
,), {}, type=cls
, size
=size
)
58 def c_var(cls
, name
, prefix
="", suffix
=""):
59 return f
"{prefix}{cls.c_typedef} {name}{suffix}"
62 class ArrayMeta(CTypeMeta
):
63 def __new__(metacls
, name
, bases
, attrs
, type, size
, **kwargs
):
64 cls
= super().__new
__(metacls
, name
, bases
, attrs
, **kwargs
)
66 cls
.__ellipsis
= (size
is Ellipsis)
67 cls
.__size
= 0 if cls
.__ellipsis
else size
75 size
= "" if cls
.__ellipsis
else f
"{cls.__size}"
76 yield f
"{cls.__type.c_typedef}[{size}]"
78 def c_var(cls
, name
, prefix
="", suffix
=""):
79 size
= "" if cls
.__ellipsis
else f
"{cls.__size}"
80 return f
"{prefix}{cls.__type.c_typedef} {name}[{size}]{suffix}"
83 class BitmapMeta(CTypeMeta
):
84 def __new__(metacls
, name
, bases
, attrs
, typedef
="uint64_t", bits
=0, **kwargs
):
85 cls
= super().__new
__(metacls
, name
, bases
, attrs
, typedef
=typedef
, **kwargs
)
92 def c_var(cls
, name
, prefix
="", suffix
=""):
93 return f
"{prefix}{cls.c_typedef} {name} : {cls.__bits}{suffix}"
96 class CType(metaclass
=CTypeMeta
):
98 def c_value(self
, *, prefix
="", suffix
="", **kwargs
):
102 class Array(CType
, tuple, metaclass
=ArrayMeta
, type=CType
, size
=...):
103 def c_value(self
, *, prefix
="", suffix
="", **kwargs
):
105 for (index
, item
) in enumerate(self
):
106 yield from indent(item
.c_value(prefix
=f
"[{index}] = ", suffix
=","))
110 class Bitmap(metaclass
=BitmapMeta
):
114 class Void(CType
, typedef
="void"):
115 def c_var(cls
, name
, prefix
="", suffix
=""):
116 raise NotImplementedError
119 class EnumMeta(_enum
.EnumMeta
, CTypeMeta
):
120 def __call__(metacls
, name
, entries
, tag
=None, **kwargs
):
121 if isinstance(entries
, type) and issubclass(entries
, _enum
.Enum
):
122 # Use __members__, not __iter__, otherwise aliases are lost.
123 entries
= dict(entries
.__members
__)
124 if isinstance(entries
, dict):
125 entries
= tuple(entries
.items())
127 tag
= f
"svp64_{name.lower()}"
129 cls
= super().__call
__(value
=name
, names
=entries
, **kwargs
)
136 return f
"enum {cls.c_tag}"
143 yield f
"{cls.c_typedef} {{"
145 yield from indent(item
.c_value(suffix
=","))
148 def c_var(cls
, name
, prefix
="", suffix
=""):
149 return f
"{prefix}{cls.c_typedef} {name}{suffix}"
152 class Enum(CType
, _enum
.Enum
, metaclass
=EnumMeta
):
155 return f
"{self.__class__.c_tag.upper()}_{self.name.upper()}"
157 def c_value(self
, *, prefix
="", suffix
="", **kwargs
):
158 yield f
"{prefix}{self.c_name}{suffix}"
161 In1Sel
= Enum("In1Sel", _In1Sel
)
162 In2Sel
= Enum("In2Sel", _In2Sel
)
163 In3Sel
= Enum("In3Sel", _In3Sel
)
164 OutSel
= Enum("OutSel", _OutSel
)
165 CRInSel
= Enum("CRInSel", _CRInSel
)
166 CROutSel
= Enum("CROutSel", _CROutSel
)
167 SVPType
= Enum("SVPType", _SVPtype
)
168 SVEType
= Enum("SVEType", _SVEtype
)
169 SVEXTRA
= Enum("SVEXTRA", _SVEXTRA
)
172 class Constant(CType
, _enum
.Enum
, metaclass
=EnumMeta
):
175 yield f
"/* {cls.c_tag.upper()} constants */"
176 # Use __members__, not __iter__, otherwise aliases are lost.
177 for (key
, item
) in cls
.__members
__.items():
178 key
= f
"{cls.c_tag.upper()}_{key.upper()}"
179 value
= f
"0x{item.value:08x}U"
180 yield f
"#define {key} {value}"
182 def c_value(self
, *, prefix
="", suffix
="", **kwargs
):
183 yield f
"{prefix}{self.__class__.c_tag.upper()}_{self.name.upper()}{suffix}"
186 Mode
= Constant("Mode", _SVP64MODE
)
189 class StructMeta(CTypeMeta
):
190 def __new__(metacls
, name
, bases
, attrs
, tag
=None, **kwargs
):
192 tag
= f
"svp64_{name.lower()}"
193 if "typedef" not in kwargs
:
194 kwargs
["typedef"] = f
"struct {tag}"
196 cls
= super().__new
__(metacls
, name
, bases
, attrs
, **kwargs
)
206 yield f
"{cls.c_typedef} {{"
207 for field
in _dataclasses
.fields(cls
):
208 yield from indent([field
.type.c_var(name
=f
"{field.name}", suffix
=";")])
212 @_dataclasses.dataclass(eq
=True, frozen
=True)
213 class Struct(CType
, metaclass
=StructMeta
):
214 def c_value(self
, *, prefix
="", suffix
="", **kwargs
):
216 for field
in _dataclasses
.fields(self
):
218 attr
= getattr(self
, name
)
219 yield from indent(attr
.c_value(prefix
=f
".{name} = ", suffix
=","))
223 class Integer(CType
, str):
224 def c_value(self
, *, prefix
="", suffix
="", **kwargs
):
225 yield f
"{prefix}{self}{suffix}"
228 class Byte(Integer
, typedef
="uint8_t"):
232 class Size(Integer
, typedef
="size_t"):
236 class UInt32(Integer
, typedef
="uint32_t"):
240 class Name(CType
, str):
242 escaped
= self
.replace("\"", "\\\"")
243 return f
"\"{escaped}\""
245 def c_value(self
, *, prefix
="", suffix
="", **kwargs
):
246 yield f
"{prefix}{self!r}{suffix}"
249 def c_var(cls
, name
, prefix
="", suffix
=""):
250 return f
"{prefix}const char *{name}{suffix}"
253 @_dataclasses.dataclass(eq
=True, frozen
=True)
254 class Record(Struct
):
275 yield f
"struct svp64_record {{"
276 for field
in _dataclasses
.fields(cls
):
277 bits
= len(field
.type).bit_length()
278 yield from indent([f
"uint64_t {field.name} : {bits};"])
280 bits_rsvd
= (64 - (bits_all
% 64))
282 yield from indent([f
"uint64_t : {bits_rsvd};"])
286 @_dataclasses.dataclass(eq
=True, frozen
=True)
291 def __lt__(self
, other
):
292 if not isinstance(other
, self
.__class
__):
293 return NotImplemented
295 return self
.name
< other
.name
298 class FunctionMeta(CTypeMeta
):
299 def __new__(metacls
, name
, bases
, attrs
, rv
, args
):
300 cls
= super().__new
__(metacls
, name
, bases
, attrs
)
306 def c_var(cls
, name
, prefix
="", suffix
=""):
307 rv
= cls
.__rv
.c_typedef
308 args
= ", ".join(arg_cls
.c_var(arg_name
) for (arg_name
, arg_cls
) in cls
.__args
)
309 return f
"{prefix}{rv} {name}({args}){suffix}"
312 class FieldsMappingMeta(EnumMeta
):
313 class HelperMeta(FunctionMeta
):
314 def __new__(metacls
, name
, bases
, attrs
, rv
, args
, enum
):
315 cls
= super().__new
__(metacls
, name
, bases
, attrs
, rv
=rv
, args
=args
)
320 prefix
= f
"svp64_{cls.__enum.__name__}"
321 # Use __members__, not __iter__, otherwise aliases are lost.
322 for (name
, value
) in cls
.__enum
.__members
__.items():
323 yield (f
"{prefix}_{name}".upper(), value
)
325 class GetterMeta(HelperMeta
):
326 def __new__(metacls
, name
, bases
, attrs
, enum
, struct
):
327 return super().__new
__(metacls
, name
, bases
, attrs
, enum
=enum
, rv
=UInt32
, args
=(
332 class SetterMeta(HelperMeta
):
333 def __new__(metacls
, name
, bases
, attrs
, enum
, struct
):
334 return super().__new
__(metacls
, name
, bases
, attrs
, enum
=enum
, rv
=Void
, args
=(
335 ("*storage", struct
),
340 def __call__(metacls
, name
, base
=SelectableIntMapping
, **kwargs
):
341 def flatten(mapping
, parent
=""):
342 for (key
, value
) in mapping
.items():
343 key
= f
"{parent}_{key}" if parent
else key
344 if isinstance(value
, dict):
345 yield from flatten(mapping
=value
, parent
=key
)
347 value
= map(lambda bit
: bit
, reversed(value
))
348 # value = map(lambda bit: ((base.bits - 1) - bit), reversed(value))
349 yield (key
.upper(), tuple(value
))
351 tag
= f
"svp64_{name.lower()}"
352 fields
= dict(flatten(mapping
=dict(base
)))
353 bitmap
= type(name
, (Bitmap
,), {}, typedef
="uint32_t", bits
=base
.bits
)
354 struct
= _dataclasses
.make_dataclass(name
, (("value", bitmap
),),
355 bases
=(Struct
,), frozen
=True, eq
=True)
357 cls
= super().__call
__(name
=name
, entries
=fields
, tag
=f
"{tag}_field", **kwargs
)
359 def c_value(fields
, stmt
):
360 yield "switch (field) {"
361 for (field_name
, field_value
) in fields
:
362 yield from indent([f
"case SVP64_FIELD_{field_name.upper()}:"])
363 yield from indent(indent(map(stmt
, enumerate(field_value
.value
))))
364 yield from indent(indent(["break;"]))
367 class Getter(metaclass
=FieldsMappingMeta
.GetterMeta
, enum
=cls
, struct
=struct
):
368 def c_value(self
, prefix
="", suffix
=""):
371 UInt32
.c_var(name
="result", suffix
=" = UINT32_C(0);"),
372 UInt32
.c_var(name
="origin", suffix
=" = storage.value;"),
375 yield from indent(c_value(fields
=self
.__class
__,
376 stmt
=lambda kv
: f
"result |= SVP64_FIELD_GET(origin, {kv[1]}, {kv[0]});"))
378 yield from indent(["return result;"])
381 class Setter(metaclass
=FieldsMappingMeta
.SetterMeta
, enum
=cls
, struct
=struct
):
382 def c_value(self
, prefix
="", suffix
=""):
385 UInt32
.c_var(name
="result", suffix
=" = storage->value;"),
388 yield from indent(c_value(fields
=self
.__class
__,
389 stmt
=lambda kv
: f
"SVP64_FIELD_SET(&result, value, {kv[0]}, {kv[1]});"))
391 yield from indent(["storage->value = result;"])
395 cls
.__struct
= struct
396 cls
.__getter
= Getter()
397 cls
.__setter
= Setter()
410 yield from super().c_decl()
411 yield from cls
.__struct
.c_decl()
412 yield cls
.__getter
.__class
__.c_var(name
=f
"{cls.__tag}_get", suffix
=";")
413 yield cls
.__setter
.__class
__.c_var(name
=f
"{cls.__tag}_set", suffix
=";")
416 class FieldsMapping(Enum
, metaclass
=FieldsMappingMeta
):
419 short_c_tag
= self
.__class
__.c_tag
[:-len("_field")]
420 return f
"{short_c_tag.upper()}_{self.name.upper()}"
423 Prefix
= FieldsMapping("Prefix", base
=_SVP64PrefixFields
)
424 RM
= FieldsMapping("RM", base
=_SVP64RMFields
)
427 class Codegen(_enum
.Enum
):
428 PPC_SVP64_H
= _enum
.auto()
429 PPC_SVP64_OPC_C
= _enum
.auto()
432 def _missing_(cls
, value
):
434 "ppc-svp64.h": Codegen
.PPC_SVP64_H
,
435 "ppc-svp64-opc.c": Codegen
.PPC_SVP64_OPC_C
,
440 Codegen
.PPC_SVP64_H
: "ppc-svp64.h",
441 Codegen
.PPC_SVP64_OPC_C
: "ppc-svp64-opc.c",
444 def generate(self
, entries
):
445 def ppc_svp64_h(entries
, num_entries
):
446 yield from DISCLAIMER
449 yield f
"#ifndef {self.name}"
450 yield f
"#define {self.name}"
453 yield "#include <stdint.h>"
456 yield "#ifdef __cplusplus"
457 yield "extern \"C\" {"
462 In1Sel
, In2Sel
, In3Sel
, OutSel
,
464 SVPType
, SVEType
, SVEXTRA
,
468 yield from enum
.c_decl()
471 for cls
in (Record
, Entry
, Prefix
, RM
):
472 yield from cls
.c_decl()
475 for name
in ("in1", "in2", "in3", "out", "out2", "cr_in", "cr_out"):
476 yield "unsigned char"
477 yield f
"svp64_record_{name}_opsel(const struct svp64_record *record);"
480 yield entries
.__class
__.c_var("svp64_entries", prefix
="extern const ", suffix
=";")
481 yield num_entries
.__class
__.c_var("svp64_num_entries", prefix
="extern const ", suffix
=";")
484 yield f
"#define SVP64_NAME_MAX {max(map(lambda entry: len(entry.name), entries))}"
487 yield "#ifdef __cplusplus"
492 yield f
"#endif /* {self.name} */"
495 def ppc_svp64_opc_c(entries
, num_entries
):
496 yield from DISCLAIMER
499 yield "#include \"opcode/ppc-svp64.h\""
502 def opsel(enum
, name
, table
):
503 sep
= (max(map(len, list(table
.values()) + ["UNUSED"])) + 1)
504 c_tag
= f
"svp64_{enum.__name__.lower()}"
505 yield "unsigned char"
506 yield f
"svp64_record_{name}_opsel(const struct svp64_record *record)"
508 yield from indent(["static const unsigned char table[] = {"])
510 value
= table
.get(key
, "UNUSED")
511 c_value
= f
"{c_tag.upper()}_{key.name.upper()}"
512 yield from indent(indent([f
"{value:{sep}}, /* {c_value} */"]))
513 yield from indent(["};"])
515 yield from indent([f
"return table[record->{name}];"])
519 yield from opsel(In1Sel
, "in1", {
521 In1Sel
.RA_OR_ZERO
: "RA",
527 yield from opsel(In2Sel
, "in2", {
533 yield from opsel(In3Sel
, "in3", {
541 for name
in ("out", "out2"):
542 yield from opsel(OutSel
, name
, {
546 OutSel
.RT_OR_ZERO
: "RT",
550 yield from opsel(CRInSel
, "cr_in", {
554 CRInSel
.WHOLE_REG
: "FXM",
556 yield from opsel(CROutSel
, "cr_out", {
559 CROutSel
.WHOLE_REG
: "FXM",
562 yield entries
.__class
__.c_var("svp64_entries", prefix
="const ", suffix
=" = \\")
563 yield from entries
.c_value(prefix
="", suffix
=";")
565 yield num_entries
.__class
__.c_var("svp64_num_entries", prefix
="const ", suffix
=" = \\")
566 yield from indent(num_entries
.c_value(suffix
=";"))
569 bit_shl
= lambda val
, pos
: f
"({val} << UINT32_C({pos}))"
570 bit_shr
= lambda val
, pos
: f
"({val} >> UINT32_C({pos}))"
571 bit_get
= lambda val
, pos
: f
"({bit_shr(val, pos)} & UINT32_C(1))"
572 bit_or
= lambda lhs
, rhs
: f
"({lhs} | {rhs})"
573 bit_and
= lambda lhs
, rhs
: f
"({lhs} & {rhs})"
574 bit_not
= lambda val
: f
"~({val})"
580 bit_and("VALUE", bit_not(bit_shl("UINT32_C(1)", "BIT"))),
584 ("VALUE", "SRC", "DST"),
585 bit_shl(bit_get("VALUE", "SRC"), "DST"),
589 ("ORIGIN", "SRC", "DST"),
590 "SVP64_FIELD_REMAP(ORIGIN, SRC, DST)",
594 ("RESULT", "VALUE", "SRC", "DST"),
595 ("do { (*RESULT) = " + bit_or(
596 lhs
="SVP64_FIELD_CLEAR(*(RESULT), DST)",
597 rhs
="SVP64_FIELD_REMAP(VALUE, SRC, DST)",
598 ) + "; } while (0)"),
601 for (name
, args
, body
) in macros
:
602 yield f
"#define {name}({', '.join(args)}) \\"
603 yield from indent([body
])
606 for cls
in (Prefix
, RM
):
607 for (mode
, subcls
) in {"get": cls
.c_getter
, "set": cls
.c_setter
}.items():
608 yield subcls
.__class
__.c_var(name
=f
"svp64_{cls.__name__.lower()}_{mode}")
609 yield from subcls
.c_value()
612 for name
in map(_operator
.itemgetter(0), macros
):
613 yield f
"#undef {name}"
617 entries
= Entry
[...](entries
)
618 num_entries
= Size("(sizeof (svp64_entries) / sizeof (svp64_entries[0]))")
621 Codegen
.PPC_SVP64_H
: ppc_svp64_h
,
622 Codegen
.PPC_SVP64_OPC_C
: ppc_svp64_opc_c
,
623 }[self
](entries
, num_entries
)
627 FIELDS
= {field
.name
:field
.type for field
in _dataclasses
.fields(Record
)}
628 FIELDS
.update({field
.name
:field
.type for field
in _dataclasses
.fields(Entry
)})
633 def name_filter(name
):
634 if name
.startswith("l") and name
.endswith("br"):
636 if name
in {"mcrxr", "mcrxrx", "darn"}:
638 if name
in {"bctar", "bcctr"}:
642 if name
in {"setvl"}:
651 def item_mapper(item
):
653 key
= key
.lower().replace(" ", "_")
654 cls
= FIELDS
.get(key
, object)
655 if not isinstance(value
, cls
):
656 if issubclass(cls
, _enum
.Enum
):
657 value
= {item
.name
:item
for item
in cls
}[value
]
662 def item_filter(item
):
664 return (key
in FIELDS
)
666 for record
in ISA
.get_svp64_csv(path
):
667 names
= record
.pop("comment").split("=")[-1].split("/")
668 names
= set(filter(name_filter
, names
))
670 rc
= _RC
[record
["rc"] if record
["rc"] else "NONE"]
672 names
.update({f
"{name}." for name
in names
})
673 record
= dict(filter(item_filter
, map(item_mapper
, record
.items())))
674 for name
in map(Name
, names
):
675 yield Entry(name
=name
, record
=Record(**record
))
694 entries
.extend(parse(path
))
695 entries
= sorted(frozenset(entries
))
697 for line
in codegen
.generate(entries
):
701 if __name__
== "__main__":
702 parser
= _argparse
.ArgumentParser()
703 parser
.add_argument("codegen", type=Codegen
, choices
=Codegen
, help="code generator")
705 args
= vars(parser
.parse_args())