2 import argparse
as _argparse
3 import dataclasses
as _dataclasses
6 from openpower
.decoder
.power_enums
import (
12 CROutSel
as _CROutSel
,
18 from openpower
.decoder
.power_svp64
import SVP64RM
as _SVP64RM
23 " * this file is auto-generated, do not edit",
24 " * https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/sv/sv_binutils.py",
25 " * part of Libre-SOC, sponsored by NLnet",
31 return map(lambda string
: (" " + string
), strings
)
37 def c_decl(self
, name
):
41 def c_value(self
, prefix
="", suffix
=""):
46 def c_var(self
, name
):
50 class EnumMeta(_enum
.EnumMeta
):
51 def __call__(metacls
, *args
, **kwargs
):
55 names
= kwargs
.pop("names")
57 if isinstance(names
, type) and issubclass(names
, _enum
.Enum
):
58 names
= dict(names
.__members
__)
59 if isinstance(names
, dict):
60 names
= tuple(names
.items())
62 return super().__call
__(*args
, names
=names
, **kwargs
)
65 class Enum(CType
, _enum
.Enum
, metaclass
=EnumMeta
):
68 c_tag
= f
"svp64_{cls.__name__.lower()}"
69 yield f
"enum {c_tag} {{"
71 yield from indent(item
.c_value(suffix
=","))
74 def c_value(self
, prefix
="", suffix
=""):
75 c_tag
= f
"svp64_{self.__class__.__name__.lower()}"
76 yield f
"{prefix}{c_tag.upper()}_{self.name.upper()}{suffix}"
80 c_tag
= f
"svp64_{cls.__name__.lower()}"
81 yield f
"enum {c_tag} {name}"
84 In1Sel
= Enum("In1Sel", names
=_In1Sel
.__members
__.items())
85 In2Sel
= Enum("In2Sel", names
=_In2Sel
.__members
__.items())
86 In3Sel
= Enum("In3Sel", names
=_In3Sel
.__members
__.items())
87 OutSel
= Enum("OutSel", names
=_OutSel
.__members
__.items())
88 CRInSel
= Enum("CRInSel", names
=_CRInSel
.__members
__.items())
89 CROutSel
= Enum("CROutSel", names
=_CROutSel
.__members
__.items())
90 SVPType
= Enum("SVPType", names
=_SVPtype
.__members
__.items())
91 SVEType
= Enum("SVEType", names
=_SVEtype
.__members
__.items())
92 SVEXTRA
= Enum("SVEXTRA", names
=_SVEXTRA
.__members
__.items())
96 def __init__(self
, value
, mask
, bits
):
101 return super().__init
__()
116 fmt
= f
"{{value:0{self.bits}b}}:{{mask:0{self.bits}b}}"
117 return fmt
.format(value
=self
.value
, mask
=self
.mask
)
119 def __lt__(self
, other
):
120 if not isinstance(other
, self
.__class
__):
121 return NotImplemented
123 return self
.__value
< other
.__value
127 yield f
"struct svp64_opcode {{"
134 def c_value(self
, prefix
="", suffix
=""):
137 f
".value = UINT32_C(0x{self.value:08X}),",
138 f
".mask = UINT32_C(0x{self.mask:08X}),",
143 def c_var(cls
, name
):
144 yield f
"struct svp64_opcode {name}"
147 class IntegerOpcode(Opcode
):
148 def __init__(self
, integer
):
149 value
= int(integer
, 0)
150 bits
= max(1, value
.bit_length())
151 mask
= int(("1" * bits
), 2)
153 return super().__init
__(value
=value
, mask
=mask
, bits
=bits
)
156 class PatternOpcode(Opcode
):
157 def __init__(self
, pattern
):
162 value |
= (bit
== "1")
169 return super().__init
__(value
=value
, mask
=mask
, bits
=bits
)
172 class Name(CType
, str):
174 escaped
= self
.replace("\"", "\\\"")
175 return f
"\"{escaped}\""
177 def c_value(self
, prefix
="", suffix
=""):
178 yield f
"{prefix}{self!r}{suffix}"
181 def c_var(cls
, name
):
182 yield f
"const char *{name}"
185 @_dataclasses.dataclass(eq
=True, frozen
=True)
207 yield f
"struct svp64_record {{"
208 for field
in _dataclasses
.fields(cls
):
209 bits
= len(field
.type).bit_length()
210 yield from indent([f
"uint64_t {field.name} : {bits};"])
212 bits_rsvd
= (64 - (bits_all
% 64))
214 yield from indent([f
"uint64_t : {bits_rsvd};"])
217 def c_value(self
, prefix
="", suffix
=""):
219 for field
in _dataclasses
.fields(self
):
221 attr
= getattr(self
, name
)
222 yield from indent(attr
.c_value(prefix
=f
".{name} = ", suffix
=","))
226 def c_var(cls
, name
):
227 yield f
"struct svp64_record {name}"
230 @_dataclasses.dataclass(eq
=True, frozen
=True)
235 def __lt__(self
, other
):
236 if not isinstance(other
, self
.__class
__):
237 return NotImplemented
239 return self
.name
< other
.name
243 yield f
"struct svp64_entry {{"
244 for field
in _dataclasses
.fields(cls
):
245 yield from indent(field
.type.c_var(name
=f
"{field.name};"))
248 def c_value(self
, prefix
="", suffix
=""):
250 for field
in _dataclasses
.fields(self
):
252 attr
= getattr(self
, name
)
253 yield from indent(attr
.c_value(prefix
=f
".{name} = ", suffix
=","))
257 def c_var(cls
, name
):
258 yield f
"struct svp64_entry {name}"
261 class Codegen(_enum
.Enum
):
262 PPC_SVP64_H
= _enum
.auto()
263 PPC_SVP64_OPC_C
= _enum
.auto()
266 def _missing_(cls
, value
):
268 "ppc-svp64.h": Codegen
.PPC_SVP64_H
,
269 "ppc-svp64-opc.c": Codegen
.PPC_SVP64_OPC_C
,
274 Codegen
.PPC_SVP64_H
: "ppc-svp64.h",
275 Codegen
.PPC_SVP64_OPC_C
: "ppc-svp64-opc.c",
278 def generate(self
, entries
):
279 def ppc_svp64_h(entries
):
280 yield from DISCLAIMER
283 yield f
"#ifndef {self.name}"
284 yield f
"#define {self.name}"
287 yield "#include <stdint.h>"
290 yield "#ifdef __cplusplus"
291 yield "extern \"C\" {"
296 In1Sel
, In2Sel
, In3Sel
, OutSel
,
298 SVPType
, SVEType
, SVEXTRA
,
301 yield from enum
.c_decl()
304 yield from Record
.c_decl()
307 yield from Entry
.c_decl()
310 yield "extern const struct svp64_entry svp64_entries[];"
311 yield "extern const unsigned int svp64_num_entries;"
314 yield f
"#define SVP64_NAME_MAX {max(map(lambda entry: len(entry.name), entries))}"
317 yield "#ifdef __cplusplus"
322 yield f
"#endif /* {self.name} */"
325 def ppc_svp64_opc_c(entries
):
326 yield from DISCLAIMER
329 yield "#include \"opcode/ppc-svp64.h\""
332 yield "const struct svp64_entry svp64_entries[] = {"
333 for (index
, entry
) in enumerate(entries
):
334 yield from indent(entry
.c_value(prefix
=f
"[{index}] = ", suffix
=","))
338 yield "const unsigned int svp64_num_entries = \\"
339 yield " sizeof (svp64_entries) / sizeof (svp64_entries[0]);"
343 Codegen
.PPC_SVP64_H
: ppc_svp64_h
,
344 Codegen
.PPC_SVP64_OPC_C
: ppc_svp64_opc_c
,
349 FIELDS
= {field
.name
:field
.type for field
in _dataclasses
.fields(Record
)}
350 FIELDS
.update({field
.name
:field
.type for field
in _dataclasses
.fields(Entry
)})
352 def parse(path
, opcode_cls
):
355 def name_filter(name
):
356 if name
.startswith("l") and name
.endswith("br"):
358 if name
in {"mcrxr", "mcrxrx", "darn"}:
360 if name
in {"bctar", "bcctr"}:
364 if name
in {"setvl"}:
373 def item_mapper(item
):
375 key
= key
.lower().replace(" ", "_")
376 cls
= FIELDS
.get(key
, object)
377 if not isinstance(value
, cls
):
378 if issubclass(cls
, _enum
.Enum
):
379 value
= {item
.name
:item
for item
in cls
}[value
]
384 def item_filter(item
):
386 return (key
in FIELDS
)
388 for record
in ISA
.get_svp64_csv(path
):
389 opcode
= opcode_cls(record
.pop("opcode"))
390 names
= record
.pop("comment").split("=")[-1].split("/")
391 names
= set(filter(name_filter
, names
))
393 rc
= _RC
[record
["rc"] if record
["rc"] else "NONE"]
395 names
.update({f
"{name}." for name
in names
})
396 record
= dict(filter(item_filter
, map(item_mapper
, record
.items())))
397 for name
in map(Name
, names
):
398 yield Entry(name
=name
, record
=Record(**record
))
404 "minor_19.csv": IntegerOpcode
,
405 "minor_30.csv": IntegerOpcode
,
406 "minor_31.csv": IntegerOpcode
,
407 "minor_58.csv": IntegerOpcode
,
408 "minor_62.csv": IntegerOpcode
,
409 "minor_22.csv": IntegerOpcode
,
410 "minor_5.csv": PatternOpcode
,
411 "minor_63.csv": PatternOpcode
,
412 "minor_59.csv": PatternOpcode
,
413 "major.csv": IntegerOpcode
,
414 "extra.csv": PatternOpcode
,
416 for (path
, opcode_cls
) in table
.items():
417 entries
.extend(parse(path
, opcode_cls
))
418 entries
= sorted(frozenset(entries
))
420 for line
in codegen
.generate(entries
):
424 if __name__
== "__main__":
425 parser
= _argparse
.ArgumentParser()
426 parser
.add_argument("codegen", type=Codegen
, choices
=Codegen
, help="code generator")
428 args
= vars(parser
.parse_args())