sv_binutils: drop redundant prefix in C tags
[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 operator as _operator
6
7 from openpower.decoder.power_enums import (
8 In1Sel as _In1Sel,
9 In2Sel as _In2Sel,
10 In3Sel as _In3Sel,
11 OutSel as _OutSel,
12 CRInSel as _CRInSel,
13 CROutSel as _CROutSel,
14 SVPtype as _SVPtype,
15 SVEtype as _SVEtype,
16 SVEXTRA as _SVEXTRA,
17 RC as _RC,
18 )
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
24
25
26 DISCLAIMER = """\
27 /* {path} -- {desc}
28 Copyright (C) 2022 Free Software Foundation, Inc.
29 Written by Dmitry Selyutin (ghostmansd).
30 Sponsored by NLnet and NGI POINTER under EU Grants 871528 and 957073.
31
32 This file is part of the GNU opcodes library.
33
34 This library is free software; you can redistribute it and/or modify
35 it under the terms of the GNU General Public License as published by
36 the Free Software Foundation; either version 3, or (at your option)
37 any later version.
38
39 It is distributed in the hope that it will be useful, but WITHOUT
40 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
41 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
42 License for more details.
43
44 You should have received a copy of the GNU General Public License
45 along with this file; see the file COPYING. If not, write to the
46 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
47 MA 02110-1301, USA. */\
48 """
49
50
51 def indent(strings):
52 return map(lambda string: (" " + string), strings)
53
54
55 class CTypeMeta(type):
56 def __new__(metacls, name, bases, attrs, typedef=None):
57 cls = super().__new__(metacls, name, bases, attrs)
58 cls.__typedef = typedef
59
60 return cls
61
62 def __getitem__(cls, size):
63 name = f"{cls.__name__}[{'' if size is Ellipsis else size}]"
64 return type(name, (Array,), {}, type=cls, size=size)
65
66 @property
67 def c_typedef(cls):
68 return cls.__typedef
69
70 @_abc.abstractmethod
71 def c_decl(cls):
72 yield from ()
73
74 def c_var(cls, name, prefix="", suffix=""):
75 return f"{prefix}{cls.c_typedef} {name}{suffix}"
76
77
78 class ArrayMeta(CTypeMeta):
79 def __new__(metacls, name, bases, attrs, type, size, **kwargs):
80 cls = super().__new__(metacls, name, bases, attrs, **kwargs)
81 cls.__type = type
82 cls.__ellipsis = (size is Ellipsis)
83 cls.__size = 0 if cls.__ellipsis else size
84
85 return cls
86
87 def __len__(cls):
88 return cls.__size
89
90 def c_decl(cls):
91 size = "" if cls.__ellipsis else f"{cls.__size}"
92 yield f"{cls.__type.c_typedef}[{size}]"
93
94 def c_var(cls, name, prefix="", suffix=""):
95 size = "" if cls.__ellipsis else f"{cls.__size}"
96 return f"{prefix}{cls.__type.c_typedef} {name}[{size}]{suffix}"
97
98
99 class BitmapMeta(CTypeMeta):
100 def __new__(metacls, name, bases, attrs,
101 typedef="uint64_t", bits=0, **kwargs):
102 cls = super().__new__(metacls, name, bases, attrs,
103 typedef=typedef, **kwargs)
104 cls.__bits = bits
105 return cls
106
107 def __len__(cls):
108 return cls.__bits
109
110 def c_var(cls, name, prefix="", suffix=""):
111 return f"{prefix}{cls.c_typedef} {name} : {cls.__bits}{suffix}"
112
113
114 class CType(metaclass=CTypeMeta):
115 @_abc.abstractmethod
116 def c_value(self, *, prefix="", suffix="", **kwargs):
117 yield from ()
118
119
120 class Array(CType, tuple, metaclass=ArrayMeta, type=CType, size=...):
121 def c_value(self, *, prefix="", suffix="", **kwargs):
122 yield f"{prefix}{{"
123 for (index, item) in enumerate(self):
124 yield from indent(item.c_value(suffix=","))
125 yield f"}}{suffix}"
126
127
128 class Bitmap(metaclass=BitmapMeta):
129 pass
130
131
132 class Void(CType, typedef="void"):
133 def c_var(cls, name, prefix="", suffix=""):
134 raise NotImplementedError
135
136
137 class EnumMeta(_enum.EnumMeta, CTypeMeta):
138 def __call__(metacls, name, entries, tag=None, exclude=None, **kwargs):
139 if exclude is None:
140 exclude = frozenset()
141 if isinstance(entries, type) and issubclass(entries, _enum.Enum):
142 # Use __members__, not __iter__, otherwise aliases are lost.
143 entries = dict(entries.__members__)
144 if isinstance(entries, dict):
145 entries = tuple(entries.items())
146 entries = ((key, value) for (key, value) in entries if key not in exclude)
147 if tag is None:
148 tag = f"svp64_{name.lower()}"
149
150 cls = super().__call__(value=name, names=entries, **kwargs)
151 cls.__tag = tag
152
153 return cls
154
155 @property
156 def c_typedef(cls):
157 return f"enum {cls.c_tag}"
158
159 @property
160 def c_tag(cls):
161 return cls.__tag
162
163 def c_decl(cls):
164 yield f"{cls.c_typedef} {{"
165 for item in cls:
166 yield from indent(item.c_value(suffix=","))
167 yield f"}};"
168
169 def c_var(cls, name, prefix="", suffix=""):
170 return f"{prefix}{cls.c_typedef} {name}{suffix}"
171
172
173 class Enum(CType, _enum.Enum, metaclass=EnumMeta):
174 @property
175 def c_name(self):
176 return f"{self.__class__.c_tag.upper()}_{self.name.upper()}"
177
178 def c_value(self, *, prefix="", suffix="", **kwargs):
179 yield f"{prefix}{self.c_name}{suffix}"
180
181
182 In1Sel = Enum("In1Sel", _In1Sel, tag="svp64_in1_sel")
183 In2Sel = Enum("In2Sel", _In2Sel, tag="svp64_in2_sel")
184 In3Sel = Enum("In3Sel", _In3Sel, tag="svp64_in3_sel")
185 OutSel = Enum("OutSel", _OutSel, tag="svp64_out_sel")
186 CRInSel = Enum("CRInSel", _CRInSel, tag="svp64_cr_in_sel")
187 CROutSel = Enum("CROutSel", _CROutSel, tag="svp64_cr_out_sel")
188 PType = Enum("PType", _SVPtype, tag="svp64_ptype")
189 EType = Enum("EType", _SVEtype, tag="svp64_etype", exclude="NONE")
190 Extra = Enum("Extra", _SVEXTRA, tag="svp64_extra", exclude="Idx_1_2")
191
192
193 class Constant(CType, _enum.Enum, metaclass=EnumMeta):
194 @classmethod
195 def c_decl(cls):
196 yield f"/* {cls.c_tag.upper()} constants */"
197 # Use __members__, not __iter__, otherwise aliases are lost.
198 for (key, item) in cls.__members__.items():
199 key = f"{cls.c_tag.upper()}_{key.upper()}"
200 value = f"0x{item.value:08x}U"
201 yield f"#define {key} {value}"
202
203 def c_value(self, *, prefix="", suffix="", **kwargs):
204 yield f"{prefix}{self.__class__.c_tag.upper()}_{self.c_name.upper()}{suffix}"
205
206
207 Mode = Constant("Mode", _SVP64MODE)
208
209
210 class StructMeta(CTypeMeta):
211 def __new__(metacls, name, bases, attrs, tag=None, **kwargs):
212 if tag is None:
213 tag = f"svp64_{name.lower()}"
214 if "typedef" not in kwargs:
215 kwargs["typedef"] = f"struct {tag}"
216
217 cls = super().__new__(metacls, name, bases, attrs, **kwargs)
218 cls.__tag = tag
219
220 return cls
221
222 @property
223 def c_tag(cls):
224 return cls.__tag
225
226 def c_decl(cls):
227 yield f"{cls.c_typedef} {{"
228 for field in _dataclasses.fields(cls):
229 yield from indent([field.type.c_var(name=f"{field.name}",
230 suffix=";")])
231 yield f"}};"
232
233
234 @_dataclasses.dataclass(eq=True, frozen=True)
235 class Struct(CType, metaclass=StructMeta):
236 def c_value(self, *, prefix="", suffix="", **kwargs):
237 yield f"{prefix}{{"
238 for field in _dataclasses.fields(self):
239 name = field.name
240 attr = getattr(self, name)
241 yield from indent(attr.c_value(prefix=f".{name} = ", suffix=","))
242 yield f"}}{suffix}"
243
244
245 class Integer(CType, str):
246 def c_value(self, *, prefix="", suffix="", **kwargs):
247 yield f"{prefix}{self}{suffix}"
248
249
250 class Byte(Integer, typedef="uint8_t"):
251 pass
252
253
254 class Size(Integer, typedef="size_t"):
255 pass
256
257
258 class UInt32(Integer, typedef="uint32_t"):
259 pass
260
261
262 class Name(CType, str):
263 def __repr__(self):
264 escaped = self.replace("\"", "\\\"")
265 return f"\"{escaped}\""
266
267 def c_value(self, *, prefix="", suffix="", **kwargs):
268 yield f"{prefix}{self!r}{suffix}"
269
270 @classmethod
271 def c_var(cls, name, prefix="", suffix=""):
272 return f"{prefix}const char *{name}{suffix}"
273
274
275 @_dataclasses.dataclass(eq=True, frozen=True)
276 class Record(Struct):
277 in1: In1Sel
278 in2: In2Sel
279 in3: In3Sel
280 out: OutSel
281 out2: OutSel
282 cr_in: CRInSel
283 cr_out: CROutSel
284 sv_ptype: PType
285 sv_etype: EType
286 sv_in1: Extra
287 sv_in2: Extra
288 sv_in3: Extra
289 sv_out: Extra
290 sv_out2: Extra
291 sv_cr_in: Extra
292 sv_cr_out: Extra
293
294 @classmethod
295 def c_decl(cls):
296 bits_all = 0
297 yield f"struct svp64_record {{"
298 for field in _dataclasses.fields(cls):
299 bits = len(field.type).bit_length()
300 yield from indent([f"uint64_t {field.name} : {bits};"])
301 bits_all += bits
302 bits_rsvd = (64 - (bits_all % 64))
303 if bits_rsvd:
304 yield from indent([f"uint64_t : {bits_rsvd};"])
305 yield f"}};"
306
307
308 @_dataclasses.dataclass(eq=True, frozen=True)
309 class Entry(Struct):
310 name: Name
311 record: Record
312
313 def __lt__(self, other):
314 if not isinstance(other, self.__class__):
315 return NotImplemented
316
317 return self.name < other.name
318
319
320 class FunctionMeta(CTypeMeta):
321 def __new__(metacls, name, bases, attrs, rv, args):
322 cls = super().__new__(metacls, name, bases, attrs)
323 cls.__rv = rv
324 cls.__args = args
325
326 return cls
327
328 def c_var(cls, name, prefix="", suffix=""):
329 rv = cls.__rv.c_typedef
330 args = ", ".join(arg_cls.c_var(arg_name) \
331 for (arg_name, arg_cls) in cls.__args)
332 return f"{prefix}{rv} {name}({args}){suffix}"
333
334
335 class FieldsMappingMeta(EnumMeta):
336 class HelperMeta(FunctionMeta):
337 def __new__(metacls, name, bases, attrs, rv, args, enum):
338 cls = super().__new__(metacls, name, bases, attrs, rv=rv, args=args)
339 cls.__enum = enum
340 return cls
341
342 def __iter__(cls):
343 short_c_tag = cls.__enum.c_tag[:-len("_field")]
344 # Use __members__, not __iter__, otherwise aliases are lost.
345 for (name, value) in cls.__enum.__members__.items():
346 yield (f"{short_c_tag}_{name}".upper(), value)
347
348 class GetterMeta(HelperMeta):
349 def __new__(metacls, name, bases, attrs, enum, struct):
350 return super().__new__(metacls, name, bases, attrs,
351 enum=enum, rv=UInt32, args=(
352 ("storage", struct),
353 ("field", enum),
354 ))
355
356 class SetterMeta(HelperMeta):
357 def __new__(metacls, name, bases, attrs, enum, struct):
358 return super().__new__(metacls, name, bases, attrs, enum=enum,
359 rv=Void, args=(
360 ("*storage", struct),
361 ("field", enum),
362 ("value", UInt32),
363 ))
364
365 def __call__(metacls, name, base=SelectableIntMapping, **kwargs):
366 def flatten(mapping, parent=""):
367 for (key, value) in mapping.items():
368 key = f"{parent}_{key}" if parent else key
369 if isinstance(value, dict):
370 yield from flatten(mapping=value, parent=key)
371 else:
372 value = map(lambda bit: bit, reversed(value))
373 # value = map(lambda bit: ((base.bits - 1) - bit),
374 # reversed(value))
375 yield (key.upper(), tuple(value))
376
377 tag = f"svp64_{name.lower()}"
378 fields = dict(flatten(mapping=dict(base)))
379 bitmap = type(name, (Bitmap,), {}, typedef="uint32_t", bits=base.bits)
380 struct = _dataclasses.make_dataclass(name, (("value", bitmap),),
381 bases=(Struct,), frozen=True, eq=True)
382
383 cls = super().__call__(name=name, entries=fields, tag=f"{tag}_field",
384 **kwargs)
385
386 def c_value(fields, stmt):
387 yield "switch (field) {"
388 for (field_name, field_value) in fields:
389 yield from indent([f"case {field_name}:"])
390 yield from indent(indent(map(stmt,
391 enumerate(field_value.value))))
392 yield from indent(indent(["break;"]))
393 yield "}"
394
395 class Getter(metaclass=FieldsMappingMeta.GetterMeta,
396 enum=cls, struct=struct):
397 def c_value(self, prefix="", suffix=""):
398 yield f"{prefix}{{"
399 yield from indent([
400 UInt32.c_var(name="result", suffix=" = UINT32_C(0);"),
401 UInt32.c_var(name="origin", suffix=" = storage.value;"),
402 ])
403 yield ""
404 yield from indent(c_value(fields=self.__class__,
405 stmt=lambda kv: f"result |= SVP64_FIELD_GET(origin, {kv[1]}, {kv[0]});"))
406 yield ""
407 yield from indent(["return result;"])
408 yield f"}}{suffix}"
409
410 class Setter(metaclass=FieldsMappingMeta.SetterMeta,
411 enum=cls, struct=struct):
412 def c_value(self, prefix="", suffix=""):
413 yield f"{prefix}{{"
414 yield from indent([
415 UInt32.c_var(name="result", suffix=" = storage->value;"),
416 ])
417 yield ""
418 yield from indent(c_value(fields=self.__class__,
419 stmt=lambda kv: f"SVP64_FIELD_SET(&result, value, {kv[0]}, {kv[1]});"))
420 yield ""
421 yield from indent(["storage->value = result;"])
422 yield f"}}{suffix}"
423
424 cls.__tag = tag
425 cls.__struct = struct
426 cls.__getter = Getter()
427 cls.__setter = Setter()
428
429 return cls
430
431 @property
432 def c_getter(cls):
433 return cls.__getter
434
435 @property
436 def c_setter(cls):
437 return cls.__setter
438
439 def c_decl(cls):
440 yield f"{cls.c_typedef} {{"
441 for field_name in cls.__members__.keys():
442 short_c_tag = cls.c_tag[:-len("_field")]
443 yield from indent([f"{short_c_tag}_{field_name},".upper()])
444 yield f"}};"
445 yield from cls.__struct.c_decl()
446 yield cls.__getter.__class__.c_var(name=f"{cls.__tag}_get", suffix=";")
447 yield cls.__setter.__class__.c_var(name=f"{cls.__tag}_set", suffix=";")
448
449
450 class FieldsMapping(Enum, metaclass=FieldsMappingMeta):
451 @property
452 def c_name(self):
453 short_c_tag = self.__class__.c_tag[:-len("_field")]
454 return f"{short_c_tag}_{self.name}".upper()
455
456
457 Prefix = FieldsMapping("Prefix", base=_SVP64PrefixFields)
458 RM = FieldsMapping("RM", base=_SVP64RMFields)
459
460
461 class Codegen(_enum.Enum):
462 PPC_SVP64_H = _enum.auto()
463 PPC_SVP64_OPC_C = _enum.auto()
464
465 @classmethod
466 def _missing_(cls, value):
467 return {
468 "ppc-svp64.h": Codegen.PPC_SVP64_H,
469 "ppc-svp64-opc.c": Codegen.PPC_SVP64_OPC_C,
470 }.get(value)
471
472 def __str__(self):
473 return {
474 Codegen.PPC_SVP64_H: "ppc-svp64.h",
475 Codegen.PPC_SVP64_OPC_C: "ppc-svp64-opc.c",
476 }[self]
477
478 def generate(self, entries):
479 def ppc_svp64_h(entries, num_entries):
480 disclaimer = DISCLAIMER.format(path=str(self),
481 desc="Header file for PowerPC opcode table (SVP64 extensions)")
482 yield from disclaimer.splitlines()
483 yield ""
484
485 yield f"#ifndef {self.name}"
486 yield f"#define {self.name}"
487 yield ""
488
489 yield "#include <stdint.h>"
490 yield ""
491
492 yield "#ifdef __cplusplus"
493 yield "extern \"C\" {"
494 yield "#endif"
495 yield ""
496
497 enums = (
498 In1Sel, In2Sel, In3Sel, OutSel,
499 CRInSel, CROutSel,
500 PType, EType, Extra,
501 Mode,
502 )
503 for enum in enums:
504 yield from enum.c_decl()
505 yield ""
506
507 for cls in (Record, Entry, Prefix, RM):
508 yield from cls.c_decl()
509 yield ""
510
511 for name in ("in1", "in2", "in3", "out", "out2", "cr_in", "cr_out"):
512 yield "ppc_opindex_t"
513 yield f"svp64_record_{name}_opindex(const struct svp64_record *record);"
514 yield ""
515
516 yield entries.__class__.c_var("svp64_entries",
517 prefix="extern const ", suffix=";")
518 yield num_entries.__class__.c_var("svp64_num_entries",
519 prefix="extern const ", suffix=";")
520 yield ""
521
522 yield f"#define SVP64_NAME_MAX {max(map(lambda entry: len(entry.name), entries))}"
523 yield ""
524
525 yield "#ifdef __cplusplus"
526 yield "}"
527 yield "#endif"
528 yield ""
529
530 yield f"#endif /* {self.name} */"
531 yield ""
532
533 def ppc_svp64_opc_c(entries, num_entries):
534 disclaimer = DISCLAIMER.format(path=str(self),
535 desc="PowerPC opcode list (SVP64 extensions)")
536 yield from disclaimer.splitlines()
537 yield ""
538
539 yield "#include \"opcode/ppc-svp64.h\""
540 yield ""
541
542 def opindex(enum, name, table):
543 sep = (max(map(len, list(table.values()) + ["UNUSED"])) + 1)
544 c_tag = f"svp64_{enum.__name__.lower()}"
545 yield "ppc_opindex_t"
546 yield f"svp64_record_{name}_opindex(const struct svp64_record *record)"
547 yield "{"
548 yield from indent(["static const ppc_opindex_t table[] = {"])
549 for key in enum:
550 value = table.get(key, "UNUSED")
551 yield from indent(indent([f"{value:{sep}}, /* {key.c_name} */"]))
552 yield from indent(["};"])
553 yield ""
554 yield from indent([f"return table[record->{name}];"])
555 yield "}"
556 yield ""
557
558 yield from opindex(In1Sel, "in1", {
559 In1Sel.RA: "RA",
560 In1Sel.RA_OR_ZERO: "RA",
561 In1Sel.SPR: "SPR",
562 In1Sel.RS: "RS",
563 In1Sel.FRA: "FRA",
564 In1Sel.FRS: "FRS",
565 })
566 yield from opindex(In2Sel, "in2", {
567 In2Sel.RB: "RB",
568 In2Sel.SPR: "SPR",
569 In2Sel.RS: "RS",
570 In2Sel.FRB: "FRB",
571 })
572 yield from opindex(In3Sel, "in3", {
573 In3Sel.RS: "RS",
574 In3Sel.RB: "RB",
575 In3Sel.FRS: "FRS",
576 In3Sel.FRC: "FRC",
577 In3Sel.RC: "RC",
578 In3Sel.RT: "RT",
579 })
580 for name in ("out", "out2"):
581 yield from opindex(OutSel, name, {
582 OutSel.RT: "RT",
583 OutSel.RA: "RA",
584 OutSel.SPR: "SPR",
585 OutSel.RT_OR_ZERO: "RT",
586 OutSel.FRT: "FRT",
587 OutSel.FRS: "FRS",
588 })
589 yield from opindex(CRInSel, "cr_in", {
590 CRInSel.BI: "BI",
591 CRInSel.BFA: "BFA",
592 CRInSel.BC: "BC",
593 CRInSel.WHOLE_REG: "FXM",
594 })
595 yield from opindex(CROutSel, "cr_out", {
596 CROutSel.BF: "BF",
597 CROutSel.BT: "BT",
598 CROutSel.WHOLE_REG: "FXM",
599 })
600
601 yield entries.__class__.c_var("svp64_entries",
602 prefix="const ", suffix=" = \\")
603 yield from entries.c_value(prefix="", suffix=";")
604 yield ""
605 yield num_entries.__class__.c_var("svp64_num_entries",
606 prefix="const ", suffix=" = \\")
607 yield from indent(num_entries.c_value(suffix=";"))
608 yield ""
609
610 bit_shl = lambda val, pos: f"({val} << UINT32_C({pos}))"
611 bit_shr = lambda val, pos: f"({val} >> UINT32_C({pos}))"
612 bit_get = lambda val, pos: f"({bit_shr(val, pos)} & UINT32_C(1))"
613 bit_or = lambda lhs, rhs: f"({lhs} | {rhs})"
614 bit_and = lambda lhs, rhs: f"({lhs} & {rhs})"
615 bit_not = lambda val: f"~({val})"
616
617 macros = (
618 (
619 "SVP64_FIELD_CLEAR",
620 ("VALUE", "BIT"),
621 bit_and("VALUE", bit_not(bit_shl("UINT32_C(1)", "BIT"))),
622 ),
623 (
624 "SVP64_FIELD_REMAP",
625 ("VALUE", "SRC", "DST"),
626 bit_shl(bit_get("VALUE", "SRC"), "DST"),
627 ),
628 (
629 "SVP64_FIELD_GET",
630 ("ORIGIN", "SRC", "DST"),
631 "SVP64_FIELD_REMAP(ORIGIN, SRC, DST)",
632 ),
633 (
634 "SVP64_FIELD_SET",
635 ("RESULT", "VALUE", "SRC", "DST"),
636 ("do { (*RESULT) = " + bit_or(
637 lhs="SVP64_FIELD_CLEAR(*(RESULT), DST)",
638 rhs="SVP64_FIELD_REMAP(VALUE, SRC, DST)",
639 ) + "; } while (0)"),
640 ),
641 )
642 for (name, args, body) in macros:
643 yield f"#define {name}({', '.join(args)}) \\"
644 yield from indent([body])
645 yield ""
646
647 for cls in (Prefix, RM):
648 table = {
649 "get": cls.c_getter,
650 "set": cls.c_setter,
651 }
652 for (mode, subcls) in table.items():
653 yield subcls.__class__.c_var(name=f"svp64_{cls.__name__.lower()}_{mode}")
654 yield from subcls.c_value()
655 yield ""
656
657 for name in map(_operator.itemgetter(0), macros):
658 yield f"#undef {name}"
659 yield ""
660
661
662 entries = Entry[...](entries)
663 num_entries = Size("(sizeof (svp64_entries) / sizeof (svp64_entries[0]))")
664
665 return {
666 Codegen.PPC_SVP64_H: ppc_svp64_h,
667 Codegen.PPC_SVP64_OPC_C: ppc_svp64_opc_c,
668 }[self](entries, num_entries)
669
670
671 ISA = _SVP64RM()
672 FIELDS = {field.name:field.type for field in _dataclasses.fields(Record)}
673
674 def parse(path):
675 visited = set()
676
677 def name_filter(name):
678 if name.startswith("l") and name.endswith("br"):
679 return False
680 if name in {"mcrxr", "mcrxrx", "darn"}:
681 return False
682 if name in {"bctar", "bcctr"}:
683 return False
684 if "rfid" in name:
685 return False
686 if name in {"setvl"}:
687 return False
688 if name in visited:
689 return False
690
691 visited.add(name)
692
693 return True
694
695 for data in ISA.get_svp64_csv(path):
696 comment = data.pop("comment")
697 names = comment.split("=")[-1].split("/")
698 names = set(filter(name_filter, names))
699 if not names:
700 continue
701 rc = _RC[data["rc"] if data["rc"] else "NONE"]
702 if rc is _RC.RC:
703 names.update({f"{name}." for name in names})
704
705 record = {}
706 for (key, value) in data.items():
707 key = key.lower().replace(" ", "_")
708 cls = FIELDS.get(key)
709 if cls is None:
710 continue
711
712 if ((cls is EType and value == "NONE") or
713 (cls is Extra and value == "Idx_1_2")):
714 record = {}
715 break
716
717 if not isinstance(value, cls):
718 if issubclass(cls, _enum.Enum):
719 value = {item.name:item for item in cls}[value]
720 else:
721 value = cls(value)
722 record[key] = value
723
724 if not record:
725 continue
726
727 record = Record(**record)
728 for name in map(Name, names):
729 yield Entry(name=name, record=record)
730
731
732 def main(codegen):
733 entries = []
734 paths = (
735 "minor_19.csv",
736 "minor_30.csv",
737 "minor_31.csv",
738 "minor_58.csv",
739 "minor_62.csv",
740 "minor_22.csv",
741 "minor_5.csv",
742 "minor_63.csv",
743 "minor_59.csv",
744 "major.csv",
745 "extra.csv",
746 )
747 for path in paths:
748 entries.extend(parse(path))
749 entries = sorted(frozenset(entries))
750
751 for line in codegen.generate(entries):
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)