sv_binutils: support opcodes
[openpower-isa.git] / src / openpower / sv / sv_binutils.py
1 import abc as _abc
2 import argparse as _argparse
3 import dataclasses as _dataclasses
4 import enum as _enum
5 import functools as _functools
6 import operator as _operator
7
8 from openpower.decoder.power_enums import (
9 In1Sel as _In1Sel,
10 In2Sel as _In2Sel,
11 In3Sel as _In3Sel,
12 OutSel as _OutSel,
13 CRInSel as _CRInSel,
14 CROutSel as _CROutSel,
15 SVPtype as _SVPtype,
16 SVEtype as _SVEtype,
17 SVExtra as _SVExtra,
18 RC as _RC,
19 find_wiki_dir as _find_wiki_dir,
20 )
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
26
27
28 DISCLAIMER = """\
29 /* {path} -- {desc}
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.
33
34 This file is part of the GNU opcodes library.
35
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)
39 any later version.
40
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.
45
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. */\
50 """
51
52
53 def indent(strings):
54 return map(lambda string: (" " + string), strings)
55
56
57 class CTypeMeta(type):
58 def __new__(metacls, name, bases, attrs, typedef="void"):
59 cls = super().__new__(metacls, name, bases, attrs)
60 if typedef == "void":
61 for base in bases:
62 if (hasattr(base, "c_typedef") and
63 (base.c_typedef != "void")):
64 typedef = base.c_typedef
65 break
66 cls.__typedef = typedef
67
68 return cls
69
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)
73
74 @property
75 def c_typedef(cls):
76 return cls.__typedef
77
78 @_abc.abstractmethod
79 def c_decl(cls):
80 yield from ()
81
82 def c_var(cls, name, prefix="", suffix=""):
83 return f"{prefix}{cls.c_typedef} {name}{suffix}"
84
85
86 class ArrayMeta(CTypeMeta):
87 def __new__(metacls, name, bases, attrs, type, size, **kwargs):
88 cls = super().__new__(metacls, name, bases, attrs, **kwargs)
89 cls.__type = type
90 cls.__ellipsis = (size is Ellipsis)
91 cls.__size = 0 if cls.__ellipsis else size
92
93 return cls
94
95 def __len__(cls):
96 return cls.__size
97
98 def c_decl(cls):
99 size = "" if cls.__ellipsis else f"{cls.__size}"
100 yield f"{cls.__type.c_typedef}[{size}]"
101
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}"
105
106
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)
112 cls.__bits = bits
113 return cls
114
115 def __len__(cls):
116 return cls.__bits
117
118 def c_var(cls, name, prefix="", suffix=""):
119 return f"{prefix}{cls.c_typedef} {name} : {cls.__bits}{suffix}"
120
121
122 class CType(metaclass=CTypeMeta):
123 @_abc.abstractmethod
124 def c_value(self, *, prefix="", suffix="", **kwargs):
125 yield from ()
126
127
128 class Array(CType, tuple, metaclass=ArrayMeta, type=CType, size=...):
129 def c_value(self, *, prefix="", suffix="", **kwargs):
130 yield f"{prefix}{{"
131 for (index, item) in enumerate(self):
132 yield from indent(item.c_value(suffix=","))
133 yield f"}}{suffix}"
134
135
136 class Bitmap(metaclass=BitmapMeta):
137 pass
138
139
140 class Void(CType, typedef="void"):
141 def c_var(cls, name, prefix="", suffix=""):
142 raise NotImplementedError
143
144
145 class EnumMeta(_enum.EnumMeta, CTypeMeta):
146 def __call__(metacls, name, entries, tag=None, exclude=None, **kwargs):
147 if exclude is None:
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)
155 if tag is None:
156 tag = f"svp64_{name.lower()}"
157
158 cls = super().__call__(value=name, names=entries, **kwargs)
159 cls.__tag = tag
160
161 return cls
162
163 @property
164 def c_typedef(cls):
165 return f"enum {cls.c_tag}"
166
167 @property
168 def c_tag(cls):
169 return cls.__tag
170
171 def c_decl(cls):
172 yield f"{cls.c_typedef} {{"
173 for item in cls:
174 yield from indent(item.c_value(suffix=","))
175 yield f"}};"
176
177 def c_var(cls, name, prefix="", suffix=""):
178 return f"{prefix}{cls.c_typedef} {name}{suffix}"
179
180
181 class Enum(CType, _enum.Enum, metaclass=EnumMeta):
182 @property
183 def c_name(self):
184 return f"{self.__class__.c_tag.upper()}_{self.name.upper()}"
185
186 def c_value(self, *, prefix="", suffix="", **kwargs):
187 yield f"{prefix}{self.c_name}{suffix}"
188
189
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")
199
200
201 class Constant(CType, _enum.Enum, metaclass=EnumMeta):
202 @classmethod
203 def c_decl(cls):
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}"
210
211 def c_value(self, *, prefix="", suffix="", **kwargs):
212 yield f"{prefix}{self.__class__.c_tag.upper()}_{self.c_name.upper()}{suffix}"
213
214
215 Mode = Constant("Mode", _SVP64MODE)
216
217
218 class StructMeta(CTypeMeta):
219 def __new__(metacls, name, bases, attrs, tag=None, **kwargs):
220 if tag is None:
221 tag = f"svp64_{name.lower()}"
222 if "typedef" not in kwargs:
223 kwargs["typedef"] = f"struct {tag}"
224
225 cls = super().__new__(metacls, name, bases, attrs, **kwargs)
226 cls.__tag = tag
227
228 return cls
229
230 @property
231 def c_tag(cls):
232 return cls.__tag
233
234 def c_decl(cls):
235 def transform(field):
236 return field.type.c_var(name=f"{field.name}", suffix=";")
237
238 yield f"{cls.c_typedef} {{"
239 yield from indent(map(transform, _dataclasses.fields(cls)))
240 yield f"}};"
241
242
243 @_dataclasses.dataclass(eq=True, frozen=True)
244 class Struct(CType, metaclass=StructMeta):
245 def c_value(self, *, prefix="", suffix="", **kwargs):
246 yield f"{prefix}{{"
247 for field in _dataclasses.fields(self):
248 name = field.name
249 attr = getattr(self, name)
250 yield from indent(attr.c_value(prefix=f".{name} = ", suffix=","))
251 yield f"}}{suffix}"
252
253
254 class Integer(CType, str):
255 def c_value(self, *, prefix="", suffix="", **kwargs):
256 yield f"{prefix}{self}{suffix}"
257
258
259 class Byte(Integer, typedef="uint8_t"):
260 pass
261
262
263 class Size(Integer, typedef="size_t"):
264 pass
265
266
267 class UInt32(Integer, typedef="uint32_t"):
268 pass
269
270
271 class Name(CType, str, typedef="const char *"):
272 def __repr__(self):
273 escaped = self.replace("\"", "\\\"")
274 return f"\"{escaped}\""
275
276 def c_value(self, *, prefix="", suffix="", **kwargs):
277 yield f"{prefix}{self!r}{suffix}"
278
279 @classmethod
280 def c_var(cls, name, prefix="", suffix=""):
281 return f"{prefix}const char *{name}{suffix}"
282
283
284 @_dataclasses.dataclass(eq=True, frozen=True)
285 class Opcode(Struct):
286 class Value(UInt32):
287 def __new__(cls, value):
288 if isinstance(value, int):
289 value = f"0x{value:08x}"
290 return super().__new__(cls, value)
291
292 class Mask(UInt32):
293 def __new__(cls, value):
294 if isinstance(value, int):
295 value = f"0x{value:08x}"
296 return super().__new__(cls, value)
297
298 value: Value
299 mask: Mask
300
301
302 @_dataclasses.dataclass(eq=True, frozen=True)
303 class Desc(Struct):
304 in1: In1Sel
305 in2: In2Sel
306 in3: In3Sel
307 out: OutSel
308 out2: OutSel
309 cr_in: CRInSel
310 cr_out: CROutSel
311 sv_ptype: PType
312 sv_etype: EType
313 sv_in1: Extra
314 sv_in2: Extra
315 sv_in3: Extra
316 sv_out: Extra
317 sv_out2: Extra
318 sv_cr_in: Extra
319 sv_cr_out: Extra
320
321 @classmethod
322 def c_decl(cls):
323 bits_all = 0
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};"])
328 bits_all += bits
329 bits_rsvd = (64 - (bits_all % 64))
330 if bits_rsvd:
331 yield from indent([f"uint64_t : {bits_rsvd};"])
332 yield f"}};"
333
334
335 @_dataclasses.dataclass(eq=True, frozen=True)
336 class Record(Struct):
337 name: Name
338 opcode: Opcode
339 desc: Desc
340
341 def __lt__(self, other):
342 if not isinstance(other, self.__class__):
343 return NotImplemented
344
345 return self.name < other.name
346
347
348 class FunctionMeta(CTypeMeta):
349 def __new__(metacls, name, bases, attrs, rv, args):
350 cls = super().__new__(metacls, name, bases, attrs)
351 cls.__rv = rv
352 cls.__args = args
353
354 return cls
355
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}"
361
362
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)
367 cls.__enum = enum
368 return cls
369
370 def __iter__(cls):
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)
375
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=(
380 ("storage", struct),
381 ("field", enum),
382 ))
383
384 class SetterMeta(HelperMeta):
385 def __new__(metacls, name, bases, attrs, enum, struct):
386 return super().__new__(metacls, name, bases, attrs, enum=enum,
387 rv=Void, args=(
388 ("*storage", struct),
389 ("field", enum),
390 ("value", UInt32),
391 ))
392
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)
399 else:
400 value = map(lambda bit: bit, reversed(value))
401 yield (key.upper(), tuple(value))
402
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)
408
409 cls = super().__call__(name=name,
410 entries=entries, tag=f"{tag}_field", **kwargs)
411
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;"]))
419 yield "}"
420
421 class Getter(metaclass=FieldsMappingMeta.GetterMeta,
422 enum=cls, struct=struct):
423 def c_value(self, prefix="", suffix=""):
424 yield f"{prefix}{{"
425 yield from indent([
426 UInt32.c_var(name="result", suffix=" = UINT32_C(0);"),
427 UInt32.c_var(name="origin", suffix=" = storage.value;"),
428 ])
429 yield ""
430 yield from indent(c_value(entries=self.__class__,
431 stmt=lambda kv: f"result |= SVP64_FIELD_GET(origin, {kv[1]}, {kv[0]});"))
432 yield ""
433 yield from indent(["return result;"])
434 yield f"}}{suffix}"
435
436 class Setter(metaclass=FieldsMappingMeta.SetterMeta,
437 enum=cls, struct=struct):
438 def c_value(self, prefix="", suffix=""):
439 yield f"{prefix}{{"
440 yield from indent([
441 UInt32.c_var(name="result", suffix=" = storage->value;"),
442 ])
443 yield ""
444 yield from indent(c_value(entries=self.__class__,
445 stmt=lambda kv: f"SVP64_FIELD_SET(&result, value, {kv[0]}, {kv[1]});"))
446 yield ""
447 yield from indent(["storage->value = result;"])
448 yield f"}}{suffix}"
449
450 cls.__tag = tag
451 cls.__struct = struct
452 cls.__getter = Getter()
453 cls.__setter = Setter()
454
455 return cls
456
457 @property
458 def c_getter(cls):
459 return cls.__getter
460
461 @property
462 def c_setter(cls):
463 return cls.__setter
464
465 def c_decl(cls):
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()])
470 yield f"}};"
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=";")
474
475
476 class FieldsMapping(Enum, metaclass=FieldsMappingMeta):
477 @property
478 def c_name(self):
479 short_c_tag = self.__class__.c_tag[:-len("_field")]
480 return f"{short_c_tag}_{self.name}".upper()
481
482
483 Prefix = FieldsMapping("Prefix", base=_SVP64PrefixFields)
484 RM = FieldsMapping("RM", base=_SVP64RMFields)
485
486
487 class Codegen(_enum.Enum):
488 PPC_SVP64_GEN_H = _enum.auto()
489 PPC_SVP64_OPC_GEN_C = _enum.auto()
490
491 @classmethod
492 def _missing_(cls, value):
493 return {
494 "ppc-svp64-gen.h": Codegen.PPC_SVP64_GEN_H,
495 "ppc-svp64-opc-gen.c": Codegen.PPC_SVP64_OPC_GEN_C,
496 }.get(value)
497
498 def __str__(self):
499 return {
500 Codegen.PPC_SVP64_GEN_H: "ppc-svp64-gen.h",
501 Codegen.PPC_SVP64_OPC_GEN_C: "ppc-svp64-opc-gen.c",
502 }[self]
503
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()
509 yield ""
510
511 yield f"#ifndef {self.name}"
512 yield f"#define {self.name}"
513 yield ""
514
515 yield "#include <stdint.h>"
516 yield ""
517
518 yield "#ifdef __cplusplus"
519 yield "extern \"C\" {"
520 yield "#endif"
521 yield ""
522
523 enums = (
524 In1Sel, In2Sel, In3Sel, OutSel,
525 CRInSel, CROutSel,
526 PType, EType, Extra,
527 Mode,
528 )
529 for enum in enums:
530 yield from enum.c_decl()
531 yield ""
532
533 for cls in (Desc, Opcode, Record, Prefix, RM):
534 yield from cls.c_decl()
535 yield ""
536
537 yield "enum svp64_rm_field"
538 yield "svp64_opindex_rm_field (const struct svp64_desc *desc, ppc_opindex_t opindex);"
539 yield ""
540
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=";")
545 yield ""
546
547 yield "extern const struct powerpc_pd_reg svp64_regs[];"
548 yield Size.c_var("svp64_num_regs", prefix="extern const ", suffix=";")
549 yield ""
550
551 yield "#ifdef __cplusplus"
552 yield "}"
553 yield "#endif"
554 yield ""
555
556 yield f"#endif /* {self.name} */"
557 yield ""
558
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()
563 yield ""
564
565 yield "#include \"opcode/ppc-svp64.h\""
566 yield ""
567
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)"
573 yield "{"
574 yield from indent(["static const ppc_opindex_t table[] = {"])
575 for key in enum:
576 value = table.get(key, "UNUSED")
577 yield from indent(indent([f"{value:{sep}}, /* {key.c_name} */"]))
578 yield from indent(["};"])
579 yield ""
580 yield from indent([f"return table[desc->{name}];"])
581 yield "}"
582 yield ""
583
584 yield from opindex(In1Sel, "in1", {
585 In1Sel.RA: "RA",
586 In1Sel.RA_OR_ZERO: "RA0",
587 In1Sel.SPR: "SPR",
588 In1Sel.RS: "RS",
589 In1Sel.FRA: "FRA",
590 In1Sel.FRS: "FRS",
591 })
592 yield from opindex(In2Sel, "in2", {
593 In2Sel.RB: "RB",
594 In2Sel.SPR: "SPR",
595 In2Sel.RS: "RS",
596 In2Sel.FRB: "FRB",
597 })
598 yield from opindex(In3Sel, "in3", {
599 In3Sel.RS: "RS",
600 In3Sel.RB: "RB",
601 In3Sel.FRS: "FRS",
602 In3Sel.FRC: "FRC",
603 In3Sel.RC: "RC",
604 In3Sel.RT: "RT",
605 })
606 for name in ("out", "out2"):
607 yield from opindex(OutSel, name, {
608 OutSel.RT: "RT",
609 OutSel.RA: "RA",
610 OutSel.SPR: "SPR",
611 OutSel.RT_OR_ZERO: "RT",
612 OutSel.FRT: "FRT",
613 OutSel.FRS: "FRS",
614 })
615 yield from opindex(CRInSel, "cr_in", {
616 CRInSel.BI: "BI",
617 CRInSel.BFA: "BFA",
618 CRInSel.BC: "BC",
619 CRInSel.WHOLE_REG: "FXM",
620 })
621 yield from opindex(CROutSel, "cr_out", {
622 CROutSel.BF: "BF",
623 CROutSel.BT: "BT",
624 CROutSel.WHOLE_REG: "FXM",
625 })
626
627 yield records.__class__.c_var("svp64_records",
628 prefix="const ", suffix=" = \\")
629 yield from records.c_value(prefix="", suffix=";")
630 yield ""
631 yield num_records.__class__.c_var("svp64_num_records",
632 prefix="const ", suffix=" = \\")
633 yield from indent(num_records.c_value(suffix=";"))
634 yield ""
635
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})"
642
643 macros = (
644 (
645 "SVP64_FIELD_CLEAR",
646 ("VALUE", "BIT"),
647 bit_and("VALUE", bit_not(bit_shl("UINT32_C(1)", "BIT"))),
648 ),
649 (
650 "SVP64_FIELD_REMAP",
651 ("VALUE", "SRC", "DST"),
652 bit_shl(bit_get("VALUE", "SRC"), "DST"),
653 ),
654 (
655 "SVP64_FIELD_GET",
656 ("ORIGIN", "SRC", "DST"),
657 "SVP64_FIELD_REMAP(ORIGIN, SRC, DST)",
658 ),
659 (
660 "SVP64_FIELD_SET",
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)"),
666 ),
667 )
668 for (name, args, body) in macros:
669 yield f"#define {name}({', '.join(args)}) \\"
670 yield from indent([body])
671 yield ""
672
673 for cls in (Prefix, RM):
674 table = {
675 "get": cls.c_getter,
676 "set": cls.c_setter,
677 }
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()
681 yield ""
682
683 for name in map(_operator.itemgetter(0), macros):
684 yield f"#undef {name}"
685 yield ""
686
687 yield "const struct powerpc_pd_reg svp64_regs[] = {"
688 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"),
693 )):
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}}},"])
699 yield "};"
700 yield ""
701
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=";"))
706 yield ""
707
708
709 records = Record[...](records)
710 num_records = Size("(sizeof (svp64_records) / sizeof (svp64_records[0]))")
711
712 return {
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)
716
717
718 def records(db):
719 fields = {field.name:field.type for field in _dataclasses.fields(Desc)}
720 for insn in db:
721 desc = {}
722
723 for (key, cls) in fields.items():
724 value = getattr(insn, key)
725
726 if (((cls is EType) and (value is _SVEtype.NONE)) or
727 ((cls is Extra) and (value is _SVExtra.Idx_1_2))):
728 desc = None
729 break
730
731 if issubclass(cls, _enum.Enum):
732 value = cls[value.name]
733 else:
734 value = cls(value)
735 desc[key] = value
736
737 if desc is None:
738 continue
739
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)
744 desc = Desc(**desc)
745
746 yield Record(name=name, opcode=opcode, desc=desc)
747
748
749 def main(codegen):
750 db = _Database(_find_wiki_dir())
751 for line in codegen.generate(records(db)):
752 print(line)
753
754
755 if __name__ == "__main__":
756 parser = _argparse.ArgumentParser()
757 parser.add_argument("codegen",
758 type=Codegen, choices=Codegen,
759 help="code generator")
760
761 args = vars(parser.parse_args())
762 main(**args)