pysvp64dis: accept SelectableInt as an Instruction
[openpower-isa.git] / src / openpower / sv / sv_binutils.py
1 import abc as _abc
2 import argparse as _argparse
3 import collections as _collections
4 import dataclasses as _dataclasses
5 import enum as _enum
6 import functools as _functools
7 import operator as _operator
8
9 from openpower.decoder.power_enums import (
10 In1Sel as _In1Sel,
11 In2Sel as _In2Sel,
12 In3Sel as _In3Sel,
13 OutSel as _OutSel,
14 CRInSel as _CRInSel,
15 CROutSel as _CROutSel,
16 SVPtype as _SVPtype,
17 SVEtype as _SVEtype,
18 SVExtra as _SVExtra,
19 RC as _RC,
20 Function as _Function,
21 find_wiki_dir as _find_wiki_dir,
22 )
23 from openpower.consts import SVP64MODE as _SVP64MODE
24 from openpower.decoder.power_insn import Database as _Database
25 from openpower.decoder.isa.caller import SVP64RMFields as _SVP64RMFields
26 from openpower.decoder.isa.caller import SVP64PrefixFields as _SVP64PrefixFields
27 from openpower.decoder.selectable_int import SelectableIntMapping
28
29
30 DISCLAIMER = """\
31 /* {path} -- {desc}
32 Copyright (C) 2022 Free Software Foundation, Inc.
33 Written by Dmitry Selyutin (ghostmansd).
34 Sponsored by NLnet and NGI POINTER under EU Grants 871528 and 957073.
35
36 This file is part of the GNU opcodes library.
37
38 This library is free software; you can redistribute it and/or modify
39 it under the terms of the GNU General Public License as published by
40 the Free Software Foundation; either version 3, or (at your option)
41 any later version.
42
43 It is distributed in the hope that it will be useful, but WITHOUT
44 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
45 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
46 License for more details.
47
48 You should have received a copy of the GNU General Public License
49 along with this file; see the file COPYING. If not, write to the
50 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
51 MA 02110-1301, USA. */\
52 """
53
54
55 def indent(strings):
56 return map(lambda string: (" " + string), strings)
57
58
59 class CTypeMeta(type):
60 def __new__(metacls, name, bases, attrs, typedef="void"):
61 cls = super().__new__(metacls, name, bases, attrs)
62 if typedef == "void":
63 for base in bases:
64 if (hasattr(base, "c_typedef") and
65 (base.c_typedef != "void")):
66 typedef = base.c_typedef
67 break
68 cls.__typedef = typedef
69
70 return cls
71
72 def __getitem__(cls, size):
73 name = f"{cls.__name__}[{'' if size is Ellipsis else size}]"
74 return type(name, (Array,), {}, type=cls, size=size)
75
76 @property
77 def c_typedef(cls):
78 return cls.__typedef
79
80 @_abc.abstractmethod
81 def c_decl(cls):
82 yield from ()
83
84 def c_var(cls, name, prefix="", suffix=""):
85 return f"{prefix}{cls.c_typedef} {name}{suffix}"
86
87
88 class ArrayMeta(CTypeMeta):
89 def __new__(metacls, name, bases, attrs, type, size, **kwargs):
90 cls = super().__new__(metacls, name, bases, attrs, **kwargs)
91 cls.__type = type
92 cls.__ellipsis = (size is Ellipsis)
93 cls.__size = 0 if cls.__ellipsis else size
94
95 return cls
96
97 def __len__(cls):
98 return cls.__size
99
100 def c_decl(cls):
101 size = "" if cls.__ellipsis else f"{cls.__size}"
102 yield f"{cls.__type.c_typedef}[{size}]"
103
104 def c_var(cls, name, prefix="", suffix=""):
105 size = "" if cls.__ellipsis else f"{cls.__size}"
106 return f"{prefix}{cls.__type.c_typedef} {name}[{size}]{suffix}"
107
108
109 class BitmapMeta(CTypeMeta):
110 def __new__(metacls, name, bases, attrs,
111 typedef="uint64_t", bits=0, **kwargs):
112 cls = super().__new__(metacls,
113 name, bases, attrs, typedef=typedef, **kwargs)
114 cls.__bits = bits
115 return cls
116
117 def __len__(cls):
118 return cls.__bits
119
120 def c_var(cls, name, prefix="", suffix=""):
121 return f"{prefix}{cls.c_typedef} {name} : {cls.__bits}{suffix}"
122
123
124 class CType(metaclass=CTypeMeta):
125 @_abc.abstractmethod
126 def c_value(self, *, prefix="", suffix="", **kwargs):
127 yield from ()
128
129
130 class Array(CType, tuple, metaclass=ArrayMeta, type=CType, size=...):
131 def c_value(self, *, prefix="", suffix="", **kwargs):
132 yield f"{prefix}{{"
133 for (index, item) in enumerate(self):
134 yield from indent(item.c_value(suffix=","))
135 yield f"}}{suffix}"
136
137
138 class Bitmap(metaclass=BitmapMeta):
139 pass
140
141
142 class Void(CType, typedef="void"):
143 def c_var(cls, name, prefix="", suffix=""):
144 raise NotImplementedError
145
146
147 class EnumMeta(_enum.EnumMeta, CTypeMeta):
148 def __call__(metacls, name, entries, tag=None, exclude=None, **kwargs):
149 if exclude is None:
150 exclude = frozenset()
151 if isinstance(entries, type) and issubclass(entries, _enum.Enum):
152 # Use __members__, not __iter__, otherwise aliases are lost.
153 entries = dict(entries.__members__)
154 if isinstance(entries, dict):
155 entries = tuple(entries.items())
156 entries = ((key, value) for (key, value) in entries if key not in exclude)
157 if tag is None:
158 tag = f"svp64_{name.lower()}"
159
160 cls = super().__call__(value=name, names=entries, **kwargs)
161 cls.__tag = tag
162
163 return cls
164
165 @property
166 def c_typedef(cls):
167 return f"enum {cls.c_tag}"
168
169 @property
170 def c_tag(cls):
171 return cls.__tag
172
173 def c_decl(cls):
174 yield f"{cls.c_typedef} {{"
175 for item in cls:
176 yield from indent(item.c_value(suffix=","))
177 yield f"}};"
178
179 def c_var(cls, name, prefix="", suffix=""):
180 return f"{prefix}{cls.c_typedef} {name}{suffix}"
181
182
183 class Enum(CType, _enum.Enum, metaclass=EnumMeta):
184 @property
185 def c_name(self):
186 return f"{self.__class__.c_tag.upper()}_{self.name.upper()}"
187
188 def c_value(self, *, prefix="", suffix="", **kwargs):
189 yield f"{prefix}{self.c_name}{suffix}"
190
191
192 In1Sel = Enum("In1Sel", _In1Sel, tag="svp64_in1_sel")
193 In2Sel = Enum("In2Sel", _In2Sel, tag="svp64_in2_sel")
194 In3Sel = Enum("In3Sel", _In3Sel, tag="svp64_in3_sel")
195 OutSel = Enum("OutSel", _OutSel, tag="svp64_out_sel")
196 CRInSel = Enum("CRInSel", _CRInSel, tag="svp64_cr_in_sel")
197 CROutSel = Enum("CROutSel", _CROutSel, tag="svp64_cr_out_sel")
198 PType = Enum("PType", _SVPtype, tag="svp64_ptype")
199 EType = Enum("EType", _SVEtype, tag="svp64_etype", exclude="NONE")
200 Extra = Enum("Extra", _SVExtra, tag="svp64_extra", exclude="Idx_1_2")
201 Function = Enum("Function", _Function, tag="svp64_function")
202
203
204 class Constant(CType, _enum.Enum, metaclass=EnumMeta):
205 @classmethod
206 def c_decl(cls):
207 yield f"/* {cls.c_tag.upper()} constants */"
208 # Use __members__, not __iter__, otherwise aliases are lost.
209 for (key, item) in cls.__members__.items():
210 key = f"{cls.c_tag.upper()}_{key.upper()}"
211 value = f"0x{item.value:08x}U"
212 yield f"#define {key} {value}"
213
214 def c_value(self, *, prefix="", suffix="", **kwargs):
215 yield f"{prefix}{self.__class__.c_tag.upper()}_{self.c_name.upper()}{suffix}"
216
217
218 Mode = Constant("Mode", _SVP64MODE)
219
220
221 class StructMeta(CTypeMeta):
222 def __new__(metacls, name, bases, attrs, tag=None, **kwargs):
223 if tag is None:
224 tag = f"svp64_{name.lower()}"
225 if "typedef" not in kwargs:
226 kwargs["typedef"] = f"struct {tag}"
227
228 cls = super().__new__(metacls, name, bases, attrs, **kwargs)
229 cls.__tag = tag
230
231 return cls
232
233 @property
234 def c_tag(cls):
235 return cls.__tag
236
237 def c_decl(cls):
238 def transform(field):
239 return field.type.c_var(name=f"{field.name}", suffix=";")
240
241 yield f"{cls.c_typedef} {{"
242 yield from indent(map(transform, _dataclasses.fields(cls)))
243 yield f"}};"
244
245
246 @_dataclasses.dataclass(eq=True, frozen=True)
247 class Struct(CType, metaclass=StructMeta):
248 def c_value(self, *, prefix="", suffix="", **kwargs):
249 yield f"{prefix}{{"
250 for field in _dataclasses.fields(self):
251 name = field.name
252 attr = getattr(self, name)
253 yield from indent(attr.c_value(prefix=f".{name} = ", suffix=","))
254 yield f"}}{suffix}"
255
256
257 class Integer(CType, str):
258 def c_value(self, *, prefix="", suffix="", **kwargs):
259 yield f"{prefix}{self}{suffix}"
260
261
262 class Byte(Integer, typedef="uint8_t"):
263 pass
264
265
266 class Size(Integer, typedef="size_t"):
267 pass
268
269
270 class UInt32(Integer, typedef="uint32_t"):
271 pass
272
273
274 class Name(CType, str, typedef="const char *"):
275 def __repr__(self):
276 escaped = self.replace("\"", "\\\"")
277 return f"\"{escaped}\""
278
279 def c_value(self, *, prefix="", suffix="", **kwargs):
280 yield f"{prefix}{self!r}{suffix}"
281
282 @classmethod
283 def c_var(cls, name, prefix="", suffix=""):
284 return f"{prefix}const char *{name}{suffix}"
285
286
287 @_dataclasses.dataclass(eq=True, frozen=True)
288 class Opcode(Struct):
289 class Value(UInt32):
290 def __new__(cls, value):
291 if isinstance(value, int):
292 value = f"0x{value:08x}"
293 return super().__new__(cls, value)
294
295 class Mask(UInt32):
296 def __new__(cls, value):
297 if isinstance(value, int):
298 value = f"0x{value:08x}"
299 return super().__new__(cls, value)
300
301 value: Value
302 mask: Mask
303
304
305 @_dataclasses.dataclass(eq=True, frozen=True)
306 class Desc(Struct):
307 function: Function
308 in1: In1Sel
309 in2: In2Sel
310 in3: In3Sel
311 out: OutSel
312 out2: OutSel
313 cr_in: CRInSel
314 cr_out: CROutSel
315 sv_ptype: PType
316 sv_etype: EType
317 sv_in1: Extra
318 sv_in2: Extra
319 sv_in3: Extra
320 sv_out: Extra
321 sv_out2: Extra
322 sv_cr_in: Extra
323 sv_cr_out: Extra
324
325 @classmethod
326 def c_decl(cls):
327 bits_all = 0
328 yield f"struct svp64_desc {{"
329 for field in _dataclasses.fields(cls):
330 bits = len(field.type).bit_length()
331 yield from indent([f"uint64_t {field.name} : {bits};"])
332 bits_all += bits
333 bits_rsvd = (64 - (bits_all % 64))
334 if bits_rsvd:
335 yield from indent([f"uint64_t : {bits_rsvd};"])
336 yield f"}};"
337
338
339 @_dataclasses.dataclass(eq=True, frozen=True)
340 class Record(Struct):
341 name: Name
342 opcode: Opcode
343 desc: Desc
344
345 def __lt__(self, other):
346 if not isinstance(other, self.__class__):
347 return NotImplemented
348
349 return self.name < other.name
350
351
352 class FunctionMeta(CTypeMeta):
353 def __new__(metacls, name, bases, attrs, rv, args):
354 cls = super().__new__(metacls, name, bases, attrs)
355 cls.__rv = rv
356 cls.__args = args
357
358 return cls
359
360 def c_var(cls, name, prefix="", suffix=""):
361 rv = cls.__rv.c_typedef
362 args = ", ".join(arg_cls.c_var(arg_name) \
363 for (arg_name, arg_cls) in cls.__args)
364 return f"{prefix}{rv} {name}({args}){suffix}"
365
366
367 class FieldsMappingMeta(EnumMeta):
368 class HelperMeta(FunctionMeta):
369 def __new__(metacls, name, bases, attrs, rv, args, enum):
370 cls = super().__new__(metacls, name, bases, attrs, rv=rv, args=args)
371 cls.__enum = enum
372 return cls
373
374 def __iter__(cls):
375 short_c_tag = cls.__enum.c_tag[:-len("_field")]
376 # Use __members__, not __iter__, otherwise aliases are lost.
377 for (name, value) in cls.__enum.__members__.items():
378 yield (f"{short_c_tag}_{name}".upper(), value)
379
380 class GetterMeta(HelperMeta):
381 def __new__(metacls, name, bases, attrs, enum, struct):
382 return super().__new__(metacls, name, bases, attrs,
383 enum=enum, rv=UInt32, args=(
384 ("storage", struct),
385 ("field", enum),
386 ))
387
388 class SetterMeta(HelperMeta):
389 def __new__(metacls, name, bases, attrs, enum, struct):
390 return super().__new__(metacls, name, bases, attrs, enum=enum,
391 rv=Void, args=(
392 ("*storage", struct),
393 ("field", enum),
394 ("value", UInt32),
395 ))
396
397 def __call__(metacls, name, base=SelectableIntMapping, **kwargs):
398 def flatten(mapping, parent=""):
399 for (key, value) in mapping.items():
400 key = f"{parent}_{key}" if parent else key
401 if isinstance(value, dict):
402 yield from flatten(mapping=value, parent=key)
403 else:
404 value = map(lambda bit: bit, reversed(value))
405 yield (key.upper(), tuple(value))
406
407 tag = f"svp64_{name.lower()}"
408 entries = dict(flatten(mapping=dict(base)))
409 bitmap = type(name, (Bitmap,), {}, typedef="uint32_t", bits=base.bits)
410 struct = _dataclasses.make_dataclass(name, (("value", bitmap),),
411 bases=(Struct,), frozen=True, eq=True)
412
413 cls = super().__call__(name=name,
414 entries=entries, tag=f"{tag}_field", **kwargs)
415
416 def c_value(entries, stmt):
417 yield "switch (field) {"
418 for (field_name, field_value) in entries:
419 yield from indent([f"case {field_name}:"])
420 yield from indent(indent(map(stmt,
421 enumerate(field_value.value))))
422 yield from indent(indent(["break;"]))
423 yield "}"
424
425 class Getter(metaclass=FieldsMappingMeta.GetterMeta,
426 enum=cls, struct=struct):
427 def c_value(self, prefix="", suffix=""):
428 yield f"{prefix}{{"
429 yield from indent([
430 UInt32.c_var(name="result", suffix=" = UINT32_C(0);"),
431 UInt32.c_var(name="origin", suffix=" = storage.value;"),
432 ])
433 yield ""
434 yield from indent(c_value(entries=self.__class__,
435 stmt=lambda kv: f"result |= SVP64_FIELD_GET(origin, {kv[1]}, {kv[0]});"))
436 yield ""
437 yield from indent(["return result;"])
438 yield f"}}{suffix}"
439
440 class Setter(metaclass=FieldsMappingMeta.SetterMeta,
441 enum=cls, struct=struct):
442 def c_value(self, prefix="", suffix=""):
443 yield f"{prefix}{{"
444 yield from indent([
445 UInt32.c_var(name="result", suffix=" = storage->value;"),
446 ])
447 yield ""
448 yield from indent(c_value(entries=self.__class__,
449 stmt=lambda kv: f"SVP64_FIELD_SET(&result, value, {kv[0]}, {kv[1]});"))
450 yield ""
451 yield from indent(["storage->value = result;"])
452 yield f"}}{suffix}"
453
454 cls.__tag = tag
455 cls.__struct = struct
456 cls.__getter = Getter()
457 cls.__setter = Setter()
458
459 return cls
460
461 @property
462 def c_getter(cls):
463 return cls.__getter
464
465 @property
466 def c_setter(cls):
467 return cls.__setter
468
469 def c_decl(cls):
470 yield f"{cls.c_typedef} {{"
471 for field_name in cls.__members__.keys():
472 short_c_tag = cls.c_tag[:-len("_field")]
473 yield from indent([f"{short_c_tag}_{field_name},".upper()])
474 yield f"}};"
475 yield from cls.__struct.c_decl()
476 yield cls.__getter.__class__.c_var(name=f"{cls.__tag}_get", suffix=";")
477 yield cls.__setter.__class__.c_var(name=f"{cls.__tag}_set", suffix=";")
478
479
480 class FieldsMapping(Enum, metaclass=FieldsMappingMeta):
481 @property
482 def c_name(self):
483 short_c_tag = self.__class__.c_tag[:-len("_field")]
484 return f"{short_c_tag}_{self.name}".upper()
485
486
487 Prefix = FieldsMapping("Prefix", base=_SVP64PrefixFields)
488 RM = FieldsMapping("RM", base=_SVP64RMFields)
489
490
491 class Codegen(_enum.Enum):
492 PPC_SVP64_GEN_H = _enum.auto()
493 PPC_SVP64_OPC_GEN_C = _enum.auto()
494
495 @classmethod
496 def _missing_(cls, value):
497 return {
498 "ppc-svp64-gen.h": Codegen.PPC_SVP64_GEN_H,
499 "ppc-svp64-opc-gen.c": Codegen.PPC_SVP64_OPC_GEN_C,
500 }.get(value)
501
502 def __str__(self):
503 return {
504 Codegen.PPC_SVP64_GEN_H: "ppc-svp64-gen.h",
505 Codegen.PPC_SVP64_OPC_GEN_C: "ppc-svp64-opc-gen.c",
506 }[self]
507
508 def generate(self, records):
509 def ppc_svp64_h(records, num_records):
510 disclaimer = DISCLAIMER.format(path=str(self),
511 desc="Header file for PowerPC opcode table (SVP64 extensions)")
512 yield from disclaimer.splitlines()
513 yield ""
514
515 yield f"#ifndef {self.name}"
516 yield f"#define {self.name}"
517 yield ""
518
519 yield "#include <stdint.h>"
520 yield ""
521
522 yield "#ifdef __cplusplus"
523 yield "extern \"C\" {"
524 yield "#endif"
525 yield ""
526
527 enums = (
528 In1Sel, In2Sel, In3Sel, OutSel,
529 CRInSel, CROutSel,
530 PType, EType, Extra,
531 Mode, Function,
532 )
533 for enum in enums:
534 yield from enum.c_decl()
535 yield ""
536
537 for cls in (Desc, Opcode, Record, Prefix, RM):
538 yield from cls.c_decl()
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
721 for insn in filter(lambda insn: insn.svp64 is not None, db):
722 desc = {}
723
724 for (key, cls) in fields.items():
725 value = getattr(insn, key)
726
727 if (((cls is EType) and (value is _SVEtype.NONE)) or
728 ((cls is Extra) and (value is _SVExtra.Idx_1_2))):
729 desc = None
730 break
731
732 if issubclass(cls, _enum.Enum):
733 value = cls[value.name]
734 else:
735 value = cls(value)
736 desc[key] = value
737
738 if desc is None:
739 continue
740
741 name = Name(f"sv.{insn.name}")
742 value = Opcode.Value(insn.opcode.value)
743 mask = Opcode.Mask(insn.opcode.mask)
744 opcode = Opcode(value=value, mask=mask)
745 desc = Desc(**desc)
746
747 yield Record(name=name, opcode=opcode, desc=desc)
748
749
750 def main(codegen):
751 db = _Database(_find_wiki_dir())
752 for line in codegen.generate(records(db)):
753 print(line)
754
755
756 if __name__ == "__main__":
757 parser = _argparse.ArgumentParser()
758 parser.add_argument("codegen",
759 type=Codegen, choices=Codegen,
760 help="code generator")
761
762 args = vars(parser.parse_args())
763 main(**args)