2 import argparse
as _argparse
3 import dataclasses
as _dataclasses
5 import functools
as _functools
6 import operator
as _operator
8 from openpower
.decoder
.power_enums
import (
14 CROutSel
as _CROutSel
,
19 find_wiki_dir
as _find_wiki_dir
,
21 from openpower
.consts
import SVP64MODE
as _SVP64MODE
22 from openpower
.decoder
.power_insn
import Database
as _Database
23 from openpower
.decoder
.isa
.caller
import SVP64RMFields
as _SVP64RMFields
24 from openpower
.decoder
.isa
.caller
import SVP64PrefixFields
as _SVP64PrefixFields
25 from openpower
.decoder
.selectable_int
import SelectableIntMapping
30 Copyright (C) 2022 Free Software Foundation, Inc.
31 Written by Dmitry Selyutin (ghostmansd).
32 Sponsored by NLnet and NGI POINTER under EU Grants 871528 and 957073.
34 This file is part of the GNU opcodes library.
36 This library is free software; you can redistribute it and/or modify
37 it under the terms of the GNU General Public License as published by
38 the Free Software Foundation; either version 3, or (at your option)
41 It is distributed in the hope that it will be useful, but WITHOUT
42 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
43 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
44 License for more details.
46 You should have received a copy of the GNU General Public License
47 along with this file; see the file COPYING. If not, write to the
48 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
49 MA 02110-1301, USA. */\
54 return map(lambda string
: (" " + string
), strings
)
57 class CTypeMeta(type):
58 def __new__(metacls
, name
, bases
, attrs
, typedef
="void"):
59 cls
= super().__new
__(metacls
, name
, bases
, attrs
)
62 if (hasattr(base
, "c_typedef") and
63 (base
.c_typedef
!= "void")):
64 typedef
= base
.c_typedef
66 cls
.__typedef
= typedef
70 def __getitem__(cls
, size
):
71 name
= f
"{cls.__name__}[{'' if size is Ellipsis else size}]"
72 return type(name
, (Array
,), {}, type=cls
, size
=size
)
82 def c_var(cls
, name
, prefix
="", suffix
=""):
83 return f
"{prefix}{cls.c_typedef} {name}{suffix}"
86 class ArrayMeta(CTypeMeta
):
87 def __new__(metacls
, name
, bases
, attrs
, type, size
, **kwargs
):
88 cls
= super().__new
__(metacls
, name
, bases
, attrs
, **kwargs
)
90 cls
.__ellipsis
= (size
is Ellipsis)
91 cls
.__size
= 0 if cls
.__ellipsis
else size
99 size
= "" if cls
.__ellipsis
else f
"{cls.__size}"
100 yield f
"{cls.__type.c_typedef}[{size}]"
102 def c_var(cls
, name
, prefix
="", suffix
=""):
103 size
= "" if cls
.__ellipsis
else f
"{cls.__size}"
104 return f
"{prefix}{cls.__type.c_typedef} {name}[{size}]{suffix}"
107 class BitmapMeta(CTypeMeta
):
108 def __new__(metacls
, name
, bases
, attrs
,
109 typedef
="uint64_t", bits
=0, **kwargs
):
110 cls
= super().__new
__(metacls
,
111 name
, bases
, attrs
, typedef
=typedef
, **kwargs
)
118 def c_var(cls
, name
, prefix
="", suffix
=""):
119 return f
"{prefix}{cls.c_typedef} {name} : {cls.__bits}{suffix}"
122 class CType(metaclass
=CTypeMeta
):
124 def c_value(self
, *, prefix
="", suffix
="", **kwargs
):
128 class Array(CType
, tuple, metaclass
=ArrayMeta
, type=CType
, size
=...):
129 def c_value(self
, *, prefix
="", suffix
="", **kwargs
):
131 for (index
, item
) in enumerate(self
):
132 yield from indent(item
.c_value(suffix
=","))
136 class Bitmap(metaclass
=BitmapMeta
):
140 class Void(CType
, typedef
="void"):
141 def c_var(cls
, name
, prefix
="", suffix
=""):
142 raise NotImplementedError
145 class EnumMeta(_enum
.EnumMeta
, CTypeMeta
):
146 def __call__(metacls
, name
, entries
, tag
=None, exclude
=None, **kwargs
):
148 exclude
= frozenset()
149 if isinstance(entries
, type) and issubclass(entries
, _enum
.Enum
):
150 # Use __members__, not __iter__, otherwise aliases are lost.
151 entries
= dict(entries
.__members
__)
152 if isinstance(entries
, dict):
153 entries
= tuple(entries
.items())
154 entries
= ((key
, value
) for (key
, value
) in entries
if key
not in exclude
)
156 tag
= f
"svp64_{name.lower()}"
158 cls
= super().__call
__(value
=name
, names
=entries
, **kwargs
)
165 return f
"enum {cls.c_tag}"
172 yield f
"{cls.c_typedef} {{"
174 yield from indent(item
.c_value(suffix
=","))
177 def c_var(cls
, name
, prefix
="", suffix
=""):
178 return f
"{prefix}{cls.c_typedef} {name}{suffix}"
181 class Enum(CType
, _enum
.Enum
, metaclass
=EnumMeta
):
184 return f
"{self.__class__.c_tag.upper()}_{self.name.upper()}"
186 def c_value(self
, *, prefix
="", suffix
="", **kwargs
):
187 yield f
"{prefix}{self.c_name}{suffix}"
190 In1Sel
= Enum("In1Sel", _In1Sel
, tag
="svp64_in1_sel")
191 In2Sel
= Enum("In2Sel", _In2Sel
, tag
="svp64_in2_sel")
192 In3Sel
= Enum("In3Sel", _In3Sel
, tag
="svp64_in3_sel")
193 OutSel
= Enum("OutSel", _OutSel
, tag
="svp64_out_sel")
194 CRInSel
= Enum("CRInSel", _CRInSel
, tag
="svp64_cr_in_sel")
195 CROutSel
= Enum("CROutSel", _CROutSel
, tag
="svp64_cr_out_sel")
196 PType
= Enum("PType", _SVPtype
, tag
="svp64_ptype")
197 EType
= Enum("EType", _SVEtype
, tag
="svp64_etype", exclude
="NONE")
198 Extra
= Enum("Extra", _SVExtra
, tag
="svp64_extra", exclude
="Idx_1_2")
201 class Constant(CType
, _enum
.Enum
, metaclass
=EnumMeta
):
204 yield f
"/* {cls.c_tag.upper()} constants */"
205 # Use __members__, not __iter__, otherwise aliases are lost.
206 for (key
, item
) in cls
.__members
__.items():
207 key
= f
"{cls.c_tag.upper()}_{key.upper()}"
208 value
= f
"0x{item.value:08x}U"
209 yield f
"#define {key} {value}"
211 def c_value(self
, *, prefix
="", suffix
="", **kwargs
):
212 yield f
"{prefix}{self.__class__.c_tag.upper()}_{self.c_name.upper()}{suffix}"
215 Mode
= Constant("Mode", _SVP64MODE
)
218 class StructMeta(CTypeMeta
):
219 def __new__(metacls
, name
, bases
, attrs
, tag
=None, **kwargs
):
221 tag
= f
"svp64_{name.lower()}"
222 if "typedef" not in kwargs
:
223 kwargs
["typedef"] = f
"struct {tag}"
225 cls
= super().__new
__(metacls
, name
, bases
, attrs
, **kwargs
)
235 def transform(field
):
236 return field
.type.c_var(name
=f
"{field.name}", suffix
=";")
238 yield f
"{cls.c_typedef} {{"
239 yield from indent(map(transform
, _dataclasses
.fields(cls
)))
243 @_dataclasses.dataclass(eq
=True, frozen
=True)
244 class Struct(CType
, metaclass
=StructMeta
):
245 def c_value(self
, *, prefix
="", suffix
="", **kwargs
):
247 for field
in _dataclasses
.fields(self
):
249 attr
= getattr(self
, name
)
250 yield from indent(attr
.c_value(prefix
=f
".{name} = ", suffix
=","))
254 class Integer(CType
, str):
255 def c_value(self
, *, prefix
="", suffix
="", **kwargs
):
256 yield f
"{prefix}{self}{suffix}"
259 class Byte(Integer
, typedef
="uint8_t"):
263 class Size(Integer
, typedef
="size_t"):
267 class UInt32(Integer
, typedef
="uint32_t"):
271 class Name(CType
, str, typedef
="const char *"):
273 escaped
= self
.replace("\"", "\\\"")
274 return f
"\"{escaped}\""
276 def c_value(self
, *, prefix
="", suffix
="", **kwargs
):
277 yield f
"{prefix}{self!r}{suffix}"
280 def c_var(cls
, name
, prefix
="", suffix
=""):
281 return f
"{prefix}const char *{name}{suffix}"
284 @_dataclasses.dataclass(eq
=True, frozen
=True)
285 class Opcode(Struct
):
287 def __new__(cls
, value
):
288 if isinstance(value
, int):
289 value
= f
"0x{value:08x}"
290 return super().__new
__(cls
, value
)
293 def __new__(cls
, value
):
294 if isinstance(value
, int):
295 value
= f
"0x{value:08x}"
296 return super().__new
__(cls
, value
)
302 @_dataclasses.dataclass(eq
=True, frozen
=True)
324 yield f
"struct svp64_desc {{"
325 for field
in _dataclasses
.fields(cls
):
326 bits
= len(field
.type).bit_length()
327 yield from indent([f
"uint64_t {field.name} : {bits};"])
329 bits_rsvd
= (64 - (bits_all
% 64))
331 yield from indent([f
"uint64_t : {bits_rsvd};"])
335 @_dataclasses.dataclass(eq
=True, frozen
=True)
336 class Record(Struct
):
341 def __lt__(self
, other
):
342 if not isinstance(other
, self
.__class
__):
343 return NotImplemented
345 return self
.name
< other
.name
348 class FunctionMeta(CTypeMeta
):
349 def __new__(metacls
, name
, bases
, attrs
, rv
, args
):
350 cls
= super().__new
__(metacls
, name
, bases
, attrs
)
356 def c_var(cls
, name
, prefix
="", suffix
=""):
357 rv
= cls
.__rv
.c_typedef
358 args
= ", ".join(arg_cls
.c_var(arg_name
) \
359 for (arg_name
, arg_cls
) in cls
.__args
)
360 return f
"{prefix}{rv} {name}({args}){suffix}"
363 class FieldsMappingMeta(EnumMeta
):
364 class HelperMeta(FunctionMeta
):
365 def __new__(metacls
, name
, bases
, attrs
, rv
, args
, enum
):
366 cls
= super().__new
__(metacls
, name
, bases
, attrs
, rv
=rv
, args
=args
)
371 short_c_tag
= cls
.__enum
.c_tag
[:-len("_field")]
372 # Use __members__, not __iter__, otherwise aliases are lost.
373 for (name
, value
) in cls
.__enum
.__members
__.items():
374 yield (f
"{short_c_tag}_{name}".upper(), value
)
376 class GetterMeta(HelperMeta
):
377 def __new__(metacls
, name
, bases
, attrs
, enum
, struct
):
378 return super().__new
__(metacls
, name
, bases
, attrs
,
379 enum
=enum
, rv
=UInt32
, args
=(
384 class SetterMeta(HelperMeta
):
385 def __new__(metacls
, name
, bases
, attrs
, enum
, struct
):
386 return super().__new
__(metacls
, name
, bases
, attrs
, enum
=enum
,
388 ("*storage", struct
),
393 def __call__(metacls
, name
, base
=SelectableIntMapping
, **kwargs
):
394 def flatten(mapping
, parent
=""):
395 for (key
, value
) in mapping
.items():
396 key
= f
"{parent}_{key}" if parent
else key
397 if isinstance(value
, dict):
398 yield from flatten(mapping
=value
, parent
=key
)
400 value
= map(lambda bit
: bit
, reversed(value
))
401 yield (key
.upper(), tuple(value
))
403 tag
= f
"svp64_{name.lower()}"
404 entries
= dict(flatten(mapping
=dict(base
)))
405 bitmap
= type(name
, (Bitmap
,), {}, typedef
="uint32_t", bits
=base
.bits
)
406 struct
= _dataclasses
.make_dataclass(name
, (("value", bitmap
),),
407 bases
=(Struct
,), frozen
=True, eq
=True)
409 cls
= super().__call
__(name
=name
,
410 entries
=entries
, tag
=f
"{tag}_field", **kwargs
)
412 def c_value(entries
, stmt
):
413 yield "switch (field) {"
414 for (field_name
, field_value
) in entries
:
415 yield from indent([f
"case {field_name}:"])
416 yield from indent(indent(map(stmt
,
417 enumerate(field_value
.value
))))
418 yield from indent(indent(["break;"]))
421 class Getter(metaclass
=FieldsMappingMeta
.GetterMeta
,
422 enum
=cls
, struct
=struct
):
423 def c_value(self
, prefix
="", suffix
=""):
426 UInt32
.c_var(name
="result", suffix
=" = UINT32_C(0);"),
427 UInt32
.c_var(name
="origin", suffix
=" = storage.value;"),
430 yield from indent(c_value(entries
=self
.__class
__,
431 stmt
=lambda kv
: f
"result |= SVP64_FIELD_GET(origin, {kv[1]}, {kv[0]});"))
433 yield from indent(["return result;"])
436 class Setter(metaclass
=FieldsMappingMeta
.SetterMeta
,
437 enum
=cls
, struct
=struct
):
438 def c_value(self
, prefix
="", suffix
=""):
441 UInt32
.c_var(name
="result", suffix
=" = storage->value;"),
444 yield from indent(c_value(entries
=self
.__class
__,
445 stmt
=lambda kv
: f
"SVP64_FIELD_SET(&result, value, {kv[0]}, {kv[1]});"))
447 yield from indent(["storage->value = result;"])
451 cls
.__struct
= struct
452 cls
.__getter
= Getter()
453 cls
.__setter
= Setter()
466 yield f
"{cls.c_typedef} {{"
467 for field_name
in cls
.__members
__.keys():
468 short_c_tag
= cls
.c_tag
[:-len("_field")]
469 yield from indent([f
"{short_c_tag}_{field_name},".upper()])
471 yield from cls
.__struct
.c_decl()
472 yield cls
.__getter
.__class
__.c_var(name
=f
"{cls.__tag}_get", suffix
=";")
473 yield cls
.__setter
.__class
__.c_var(name
=f
"{cls.__tag}_set", suffix
=";")
476 class FieldsMapping(Enum
, metaclass
=FieldsMappingMeta
):
479 short_c_tag
= self
.__class
__.c_tag
[:-len("_field")]
480 return f
"{short_c_tag}_{self.name}".upper()
483 Prefix
= FieldsMapping("Prefix", base
=_SVP64PrefixFields
)
484 RM
= FieldsMapping("RM", base
=_SVP64RMFields
)
487 class Codegen(_enum
.Enum
):
488 PPC_SVP64_GEN_H
= _enum
.auto()
489 PPC_SVP64_OPC_GEN_C
= _enum
.auto()
492 def _missing_(cls
, value
):
494 "ppc-svp64-gen.h": Codegen
.PPC_SVP64_GEN_H
,
495 "ppc-svp64-opc-gen.c": Codegen
.PPC_SVP64_OPC_GEN_C
,
500 Codegen
.PPC_SVP64_GEN_H
: "ppc-svp64-gen.h",
501 Codegen
.PPC_SVP64_OPC_GEN_C
: "ppc-svp64-opc-gen.c",
504 def generate(self
, records
):
505 def ppc_svp64_h(records
, num_records
):
506 disclaimer
= DISCLAIMER
.format(path
=str(self
),
507 desc
="Header file for PowerPC opcode table (SVP64 extensions)")
508 yield from disclaimer
.splitlines()
511 yield f
"#ifndef {self.name}"
512 yield f
"#define {self.name}"
515 yield "#include <stdint.h>"
518 yield "#ifdef __cplusplus"
519 yield "extern \"C\" {"
524 In1Sel
, In2Sel
, In3Sel
, OutSel
,
530 yield from enum
.c_decl()
533 for cls
in (Desc
, Opcode
, Record
, Prefix
, RM
):
534 yield from cls
.c_decl()
537 yield "enum svp64_rm_field"
538 yield "svp64_opindex_rm_field (const struct svp64_desc *desc, ppc_opindex_t opindex);"
541 yield records
.__class
__.c_var("svp64_records",
542 prefix
="extern const ", suffix
=";")
543 yield num_records
.__class
__.c_var("svp64_num_records",
544 prefix
="extern const ", suffix
=";")
547 yield "extern const struct powerpc_pd_reg svp64_regs[];"
548 yield Size
.c_var("svp64_num_regs", prefix
="extern const ", suffix
=";")
551 yield "#ifdef __cplusplus"
556 yield f
"#endif /* {self.name} */"
559 def ppc_svp64_opc_c(records
, num_records
):
560 disclaimer
= DISCLAIMER
.format(path
=str(self
),
561 desc
="PowerPC opcode list (SVP64 extensions)")
562 yield from disclaimer
.splitlines()
565 yield "#include \"opcode/ppc-svp64.h\""
568 def opindex(enum
, name
, table
):
569 sep
= (max(map(len, list(table
.values()) + ["UNUSED"])) + 1)
570 c_tag
= f
"svp64_{enum.__name__.lower()}"
571 yield "static inline ppc_opindex_t"
572 yield f
"svp64_desc_{name}_opindex(const struct svp64_desc *desc)"
574 yield from indent(["static const ppc_opindex_t table[] = {"])
576 value
= table
.get(key
, "UNUSED")
577 yield from indent(indent([f
"{value:{sep}}, /* {key.c_name} */"]))
578 yield from indent(["};"])
580 yield from indent([f
"return table[desc->{name}];"])
584 yield from opindex(In1Sel
, "in1", {
586 In1Sel
.RA_OR_ZERO
: "RA0",
592 yield from opindex(In2Sel
, "in2", {
598 yield from opindex(In3Sel
, "in3", {
606 for name
in ("out", "out2"):
607 yield from opindex(OutSel
, name
, {
611 OutSel
.RT_OR_ZERO
: "RT",
615 yield from opindex(CRInSel
, "cr_in", {
619 CRInSel
.WHOLE_REG
: "FXM",
621 yield from opindex(CROutSel
, "cr_out", {
624 CROutSel
.WHOLE_REG
: "FXM",
627 yield records
.__class
__.c_var("svp64_records",
628 prefix
="const ", suffix
=" = \\")
629 yield from records
.c_value(prefix
="", suffix
=";")
631 yield num_records
.__class
__.c_var("svp64_num_records",
632 prefix
="const ", suffix
=" = \\")
633 yield from indent(num_records
.c_value(suffix
=";"))
636 bit_shl
= lambda val
, pos
: f
"({val} << UINT32_C({pos}))"
637 bit_shr
= lambda val
, pos
: f
"({val} >> UINT32_C({pos}))"
638 bit_get
= lambda val
, pos
: f
"({bit_shr(val, pos)} & UINT32_C(1))"
639 bit_or
= lambda lhs
, rhs
: f
"({lhs} | {rhs})"
640 bit_and
= lambda lhs
, rhs
: f
"({lhs} & {rhs})"
641 bit_not
= lambda val
: f
"~({val})"
647 bit_and("VALUE", bit_not(bit_shl("UINT32_C(1)", "BIT"))),
651 ("VALUE", "SRC", "DST"),
652 bit_shl(bit_get("VALUE", "SRC"), "DST"),
656 ("ORIGIN", "SRC", "DST"),
657 "SVP64_FIELD_REMAP(ORIGIN, SRC, DST)",
661 ("RESULT", "VALUE", "SRC", "DST"),
662 ("do { (*RESULT) = " + bit_or(
663 lhs
="SVP64_FIELD_CLEAR(*(RESULT), DST)",
664 rhs
="SVP64_FIELD_REMAP(VALUE, SRC, DST)",
665 ) + "; } while (0)"),
668 for (name
, args
, body
) in macros
:
669 yield f
"#define {name}({', '.join(args)}) \\"
670 yield from indent([body
])
673 for cls
in (Prefix
, RM
):
678 for (mode
, subcls
) in table
.items():
679 yield subcls
.__class
__.c_var(name
=f
"svp64_{cls.__name__.lower()}_{mode}")
680 yield from subcls
.c_value()
683 for name
in map(_operator
.itemgetter(0), macros
):
684 yield f
"#undef {name}"
687 yield "const struct powerpc_pd_reg svp64_regs[] = {"
689 for (category
, count
, flags
) in sorted((
690 ("r", 128, "PPC_OPERAND_GPR"),
691 ("f", 128, "PPC_OPERAND_FPR"),
692 ("cr", 128, "PPC_OPERAND_CR_REG"),
694 for index
in range(count
):
695 regs
[f
"{category}{index}"] = (index
, flags
)
696 regs
[f
"{category}.{index}"] = (index
, flags
)
697 for (name
, (index
, flags
)) in sorted(regs
.items()):
698 yield from indent([f
"{{\"{name}\", {index}, {flags}}},"])
702 num_regs
= Size("(sizeof (svp64_regs) / sizeof (svp64_regs[0]))")
703 yield Size
.c_var("svp64_num_regs",
704 prefix
="const ", suffix
=" = \\")
705 yield from indent(num_regs
.c_value(suffix
=";"))
709 records
= Record
[...](records
)
710 num_records
= Size("(sizeof (svp64_records) / sizeof (svp64_records[0]))")
713 Codegen
.PPC_SVP64_GEN_H
: ppc_svp64_h
,
714 Codegen
.PPC_SVP64_OPC_GEN_C
: ppc_svp64_opc_c
,
715 }[self
](records
, num_records
)
719 fields
= {field
.name
:field
.type for field
in _dataclasses
.fields(Desc
)}
723 for (key
, cls
) in fields
.items():
724 value
= getattr(insn
, key
)
726 if (((cls
is EType
) and (value
is _SVEtype
.NONE
)) or
727 ((cls
is Extra
) and (value
is _SVExtra
.Idx_1_2
))):
731 if issubclass(cls
, _enum
.Enum
):
732 value
= cls
[value
.name
]
740 name
= Name(insn
.name
)
741 value
= Opcode
.Value(insn
.opcode
.value
)
742 mask
= Opcode
.Mask(insn
.opcode
.mask
)
743 opcode
= Opcode(value
=value
, mask
=mask
)
746 yield Record(name
=name
, opcode
=opcode
, desc
=desc
)
750 db
= _Database(_find_wiki_dir())
751 for line
in codegen
.generate(records(db
)):
755 if __name__
== "__main__":
756 parser
= _argparse
.ArgumentParser()
757 parser
.add_argument("codegen",
758 type=Codegen
, choices
=Codegen
,
759 help="code generator")
761 args
= vars(parser
.parse_args())