1 import collections
as _collections
3 import dataclasses
as _dataclasses
5 import functools
as _functools
6 import itertools
as _itertools
8 import operator
as _operator
9 import pathlib
as _pathlib
13 from functools
import cached_property
15 from cached_property
import cached_property
17 from openpower
.decoder
.power_enums
import (
18 Function
as _Function
,
25 CRIn2Sel
as _CRIn2Sel
,
26 CROutSel
as _CROutSel
,
28 LDSTMode
as _LDSTMode
,
33 SVmask_src
as _SVmask_src
,
38 SVExtraRegType
as _SVExtraRegType
,
39 SVExtraReg
as _SVExtraReg
,
41 from openpower
.decoder
.selectable_int
import (
42 SelectableInt
as _SelectableInt
,
43 selectconcat
as _selectconcat
,
45 from openpower
.decoder
.power_fields
import (
48 DecodeFields
as _DecodeFields
,
50 from openpower
.decoder
.pseudo
.pagereader
import ISA
as _ISA
53 @_functools.total_ordering
54 class Verbosity(_enum
.Enum
):
57 VERBOSE
= _enum
.auto()
59 def __lt__(self
, other
):
60 if not isinstance(other
, self
.__class
__):
62 return (self
.value
< other
.value
)
65 @_functools.total_ordering
66 class Priority(_enum
.Enum
):
72 def _missing_(cls
, value
):
73 if isinstance(value
, str):
78 return super()._missing
_(value
)
80 def __lt__(self
, other
):
81 if not isinstance(other
, self
.__class
__):
84 # NOTE: the order is inversed, LOW < NORMAL < HIGH
85 return (self
.value
> other
.value
)
88 def dataclass(cls
, record
, keymap
=None, typemap
=None):
92 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
94 def transform(key_value
):
95 (key
, value
) = key_value
96 key
= keymap
.get(key
, key
)
97 hook
= typemap
.get(key
, lambda value
: value
)
98 if hook
is bool and value
in ("", "0"):
104 record
= dict(map(transform
, record
.items()))
105 for key
in frozenset(record
.keys()):
106 if record
[key
] == "":
112 @_functools.total_ordering
113 @_dataclasses.dataclass(eq
=True, frozen
=True)
116 def __new__(cls
, value
):
117 if isinstance(value
, str):
118 value
= int(value
, 0)
119 if not isinstance(value
, int):
120 raise ValueError(value
)
122 if value
.bit_length() > 64:
123 raise ValueError(value
)
125 return super().__new
__(cls
, value
)
128 return self
.__repr
__()
131 return f
"{self:0{self.bit_length()}b}"
133 def bit_length(self
):
134 if super().bit_length() > 32:
138 class Value(Integer
):
147 def __lt__(self
, other
):
148 if not isinstance(other
, Opcode
):
149 return NotImplemented
150 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
153 def pattern(value
, mask
, bit_length
):
154 for bit
in range(bit_length
):
155 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
157 elif (value
& (1 << (bit_length
- bit
- 1))):
162 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
164 def match(self
, key
):
165 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
168 class IntegerOpcode(Opcode
):
169 def __init__(self
, value
):
170 if value
.startswith("0b"):
171 mask
= int(("1" * len(value
[2:])), 2)
175 value
= Opcode
.Value(value
)
176 mask
= Opcode
.Mask(mask
)
178 return super().__init
__(value
=value
, mask
=mask
)
181 class PatternOpcode(Opcode
):
182 def __init__(self
, pattern
):
183 if not isinstance(pattern
, str):
184 raise ValueError(pattern
)
186 (value
, mask
) = (0, 0)
187 for symbol
in pattern
:
188 if symbol
not in {"0", "1", "-"}:
189 raise ValueError(pattern
)
190 value |
= (symbol
== "1")
191 mask |
= (symbol
!= "-")
197 value
= Opcode
.Value(value
)
198 mask
= Opcode
.Mask(mask
)
200 return super().__init
__(value
=value
, mask
=mask
)
203 @_dataclasses.dataclass(eq
=True, frozen
=True)
205 class FlagsMeta(type):
220 class Flags(frozenset, metaclass
=FlagsMeta
):
221 def __new__(cls
, flags
=frozenset()):
222 flags
= frozenset(flags
)
223 diff
= (flags
- frozenset(cls
))
225 raise ValueError(flags
)
226 return super().__new
__(cls
, flags
)
230 flags
: Flags
= Flags()
232 function
: _Function
= _Function
.NONE
233 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
234 in1
: _In1Sel
= _In1Sel
.RA
235 in2
: _In2Sel
= _In2Sel
.NONE
236 in3
: _In3Sel
= _In3Sel
.NONE
237 out
: _OutSel
= _OutSel
.NONE
238 cr_in
: _CRInSel
= _CRInSel
.NONE
239 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
240 cr_out
: _CROutSel
= _CROutSel
.NONE
241 cry_in
: _CryIn
= _CryIn
.ZERO
242 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
243 upd
: _LDSTMode
= _LDSTMode
.NONE
244 Rc
: _RCOE
= _RCOE
.NONE
245 form
: _Form
= _Form
.NONE
247 unofficial
: bool = False
251 "internal op": "intop",
255 "ldst len": "ldst_len",
257 "CONDITIONS": "conditions",
260 def __lt__(self
, other
):
261 if not isinstance(other
, self
.__class
__):
262 return NotImplemented
263 lhs
= (self
.opcode
, self
.comment
)
264 rhs
= (other
.opcode
, other
.comment
)
268 def CSV(cls
, record
, opcode_cls
):
269 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
270 typemap
["opcode"] = opcode_cls
272 if record
["CR in"] == "BA_BB":
273 record
["cr_in"] = "BA"
274 record
["cr_in2"] = "BB"
278 for flag
in frozenset(PPCRecord
.Flags
):
279 if bool(record
.pop(flag
, "")):
281 record
["flags"] = PPCRecord
.Flags(flags
)
283 return dataclass(cls
, record
,
284 keymap
=PPCRecord
.__KEYMAP
,
289 return frozenset(self
.comment
.split("=")[-1].split("/"))
292 class PPCMultiRecord(tuple):
293 def __getattr__(self
, attr
):
295 raise AttributeError(attr
)
296 return getattr(self
[0], attr
)
299 @_dataclasses.dataclass(eq
=True, frozen
=True)
301 class ExtraMap(tuple):
303 @_dataclasses.dataclass(eq
=True, frozen
=True)
305 regtype
: _SVExtraRegType
= _SVExtraRegType
.NONE
306 reg
: _SVExtraReg
= _SVExtraReg
.NONE
309 return f
"{self.regtype.value}:{self.reg.name}"
311 def __new__(cls
, value
="0"):
312 if isinstance(value
, str):
313 def transform(value
):
314 (regtype
, reg
) = value
.split(":")
315 regtype
= _SVExtraRegType(regtype
)
316 reg
= _SVExtraReg(reg
)
317 return cls
.Entry(regtype
=regtype
, reg
=reg
)
322 value
= map(transform
, value
.split(";"))
324 return super().__new
__(cls
, value
)
327 return repr(list(self
))
329 def __new__(cls
, value
=tuple()):
333 return super().__new
__(cls
, map(cls
.Extra
, value
))
336 return repr({index
:self
[index
] for index
in range(0, 4)})
339 ptype
: _SVPtype
= _SVPtype
.NONE
340 etype
: _SVEtype
= _SVEtype
.NONE
341 msrc
: _SVmask_src
= _SVmask_src
.NO
# MASK_SRC is active
342 in1
: _In1Sel
= _In1Sel
.NONE
343 in2
: _In2Sel
= _In2Sel
.NONE
344 in3
: _In3Sel
= _In3Sel
.NONE
345 out
: _OutSel
= _OutSel
.NONE
346 out2
: _OutSel
= _OutSel
.NONE
347 cr_in
: _CRInSel
= _CRInSel
.NONE
348 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
349 cr_out
: _CROutSel
= _CROutSel
.NONE
350 extra
: ExtraMap
= ExtraMap()
352 mode
: _SVMode
= _SVMode
.NORMAL
356 "CONDITIONS": "conditions",
365 def CSV(cls
, record
):
366 for key
in frozenset({
367 "in1", "in2", "in3", "CR in",
368 "out", "out2", "CR out",
374 if record
["CR in"] == "BA_BB":
375 record
["cr_in"] = "BA"
376 record
["cr_in2"] = "BB"
380 for idx
in range(0, 4):
381 extra
.append(record
.pop(f
"{idx}"))
383 record
["extra"] = cls
.ExtraMap(extra
)
385 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
387 @_functools.lru_cache(maxsize
=None)
388 def extra_idx(self
, key
):
396 if key
not in frozenset({
397 "in1", "in2", "in3", "cr_in", "cr_in2",
398 "out", "out2", "cr_out",
402 sel
= getattr(self
, key
)
403 if sel
is _CRInSel
.BA_BB
:
404 return _SVExtra
.Idx_1_2
405 reg
= _SVExtraReg(sel
)
406 if reg
is _SVExtraReg
.NONE
:
410 _SVExtraRegType
.SRC
: {},
411 _SVExtraRegType
.DST
: {},
413 for index
in range(0, 4):
414 for entry
in self
.extra
[index
]:
415 extra_map
[entry
.regtype
][entry
.reg
] = extra_idx
[index
]
417 for regtype
in (_SVExtraRegType
.SRC
, _SVExtraRegType
.DST
):
418 extra
= extra_map
[regtype
].get(reg
, _SVExtra
.NONE
)
419 if extra
is not _SVExtra
.NONE
:
424 extra_idx_in1
= property(_functools
.partial(extra_idx
, key
="in1"))
425 extra_idx_in2
= property(_functools
.partial(extra_idx
, key
="in2"))
426 extra_idx_in3
= property(_functools
.partial(extra_idx
, key
="in3"))
427 extra_idx_out
= property(_functools
.partial(extra_idx
, key
="out"))
428 extra_idx_out2
= property(_functools
.partial(extra_idx
, key
="out2"))
429 extra_idx_cr_in
= property(_functools
.partial(extra_idx
, key
="cr_in"))
430 extra_idx_cr_in2
= property(_functools
.partial(extra_idx
, key
="cr_in2"))
431 extra_idx_cr_out
= property(_functools
.partial(extra_idx
, key
="cr_out"))
433 @_functools.lru_cache(maxsize
=None)
434 def extra_reg(self
, key
):
435 return _SVExtraReg(getattr(self
, key
))
437 extra_reg_in1
= property(_functools
.partial(extra_reg
, key
="in1"))
438 extra_reg_in2
= property(_functools
.partial(extra_reg
, key
="in2"))
439 extra_reg_in3
= property(_functools
.partial(extra_reg
, key
="in3"))
440 extra_reg_out
= property(_functools
.partial(extra_reg
, key
="out"))
441 extra_reg_out2
= property(_functools
.partial(extra_reg
, key
="out2"))
442 extra_reg_cr_in
= property(_functools
.partial(extra_reg
, key
="cr_in"))
443 extra_reg_cr_in2
= property(_functools
.partial(extra_reg
, key
="cr_in2"))
444 extra_reg_cr_out
= property(_functools
.partial(extra_reg
, key
="cr_out"))
449 for idx
in range(0, 4):
450 for entry
in self
.svp64
.extra
[idx
]:
451 if entry
.regtype
is _SVExtraRegType
.DST
:
452 if regtype
is not None:
453 raise ValueError(self
.svp64
)
454 regtype
= _RegType(entry
.reg
)
455 if regtype
not in (_RegType
.CR_5BIT
, _RegType
.CR_3BIT
):
456 raise ValueError(self
.svp64
)
457 return (regtype
is _RegType
.CR_3BIT
)
461 def __init__(self
, value
=(0, 32)):
462 if isinstance(value
, str):
463 (start
, end
) = map(int, value
.split(":"))
466 if start
< 0 or end
< 0 or start
>= end
:
467 raise ValueError(value
)
472 return super().__init
__()
475 return (self
.__end
- self
.__start
+ 1)
478 return f
"[{self.__start}:{self.__end}]"
481 yield from range(self
.start
, (self
.end
+ 1))
483 def __reversed__(self
):
484 return tuple(reversed(tuple(self
)))
495 @_dataclasses.dataclass(eq
=True, frozen
=True)
497 class Mode(_enum
.Enum
):
498 INTEGER
= _enum
.auto()
499 PATTERN
= _enum
.auto()
502 def _missing_(cls
, value
):
503 if isinstance(value
, str):
504 return cls
[value
.upper()]
505 return super()._missing
_(value
)
508 def __new__(cls
, value
=None):
509 if isinstance(value
, str):
510 if value
.upper() == "NONE":
513 value
= int(value
, 0)
517 return super().__new
__(cls
, value
)
523 return (bin(self
) if self
else "None")
529 opcode
: IntegerOpcode
= None
530 priority
: Priority
= Priority
.NORMAL
532 def __lt__(self
, other
):
533 if not isinstance(other
, self
.__class
__):
534 return NotImplemented
535 return (self
.priority
< other
.priority
)
538 def CSV(cls
, record
):
539 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
540 if record
["opcode"] == "NONE":
541 typemap
["opcode"] = lambda _
: None
543 return dataclass(cls
, record
, typemap
=typemap
)
547 def __init__(self
, items
):
548 if isinstance(items
, dict):
549 items
= items
.items()
552 (name
, bitrange
) = item
553 return (name
, tuple(bitrange
.values()))
555 self
.__mapping
= dict(map(transform
, items
))
557 return super().__init
__()
560 return repr(self
.__mapping
)
563 yield from self
.__mapping
.items()
565 def __contains__(self
, key
):
566 return self
.__mapping
.__contains
__(key
)
568 def __getitem__(self
, key
):
569 return self
.__mapping
.get(key
, None)
573 def __init__(self
, insn
, iterable
):
575 "b": {"target_addr": TargetAddrOperandLI
},
576 "ba": {"target_addr": TargetAddrOperandLI
},
577 "bl": {"target_addr": TargetAddrOperandLI
},
578 "bla": {"target_addr": TargetAddrOperandLI
},
579 "bc": {"target_addr": TargetAddrOperandBD
},
580 "bca": {"target_addr": TargetAddrOperandBD
},
581 "bcl": {"target_addr": TargetAddrOperandBD
},
582 "bcla": {"target_addr": TargetAddrOperandBD
},
583 "addpcis": {"D": DOperandDX
},
584 "fishmv": {"D": DOperandDX
},
585 "fmvis": {"D": DOperandDX
},
588 "SVi": NonZeroOperand
,
589 "SVd": NonZeroOperand
,
590 "SVxd": NonZeroOperand
,
591 "SVyd": NonZeroOperand
,
592 "SVzd": NonZeroOperand
,
594 "D": SignedImmediateOperand
,
598 "SIM": SignedOperand
,
599 "SVD": SignedOperand
,
600 "SVDS": SignedOperand
,
602 custom_immediates
= {
608 for operand
in iterable
:
612 (name
, value
) = operand
.split("=")
613 mapping
[name
] = (StaticOperand
, {
619 if name
.endswith(")"):
620 name
= name
.replace("(", " ").replace(")", "")
621 (immediate
, _
, name
) = name
.partition(" ")
625 if immediate
is not None:
626 cls
= custom_immediates
.get(immediate
, ImmediateOperand
)
628 if insn
in custom_insns
and name
in custom_insns
[insn
]:
629 cls
= custom_insns
[insn
][name
]
630 elif name
in custom_fields
:
631 cls
= custom_fields
[name
]
633 if name
in _RegType
.__members
__:
634 regtype
= _RegType
[name
]
635 if regtype
is _RegType
.GPR
:
637 elif regtype
is _RegType
.FPR
:
639 if regtype
is _RegType
.CR_5BIT
:
641 if regtype
is _RegType
.CR_3BIT
:
644 mapping
[name
] = (cls
, {"name": name
})
648 for (name
, (cls
, kwargs
)) in mapping
.items():
649 kwargs
= dict(kwargs
)
650 kwargs
["name"] = name
651 if issubclass(cls
, StaticOperand
):
652 static
.append((cls
, kwargs
))
653 elif issubclass(cls
, DynamicOperand
):
654 dynamic
.append((cls
, kwargs
))
656 raise ValueError(name
)
658 self
.__mapping
= mapping
659 self
.__static
= tuple(static
)
660 self
.__dynamic
= tuple(dynamic
)
662 return super().__init
__()
665 for (_
, items
) in self
.__mapping
.items():
666 (cls
, kwargs
) = items
670 return self
.__mapping
.__repr
__()
672 def __contains__(self
, key
):
673 return self
.__mapping
.__contains
__(key
)
675 def __getitem__(self
, key
):
676 return self
.__mapping
.__getitem
__(key
)
684 return self
.__dynamic
688 def __init__(self
, iterable
):
689 self
.__pcode
= tuple(iterable
)
690 return super().__init
__()
693 yield from self
.__pcode
696 return self
.__pcode
.__repr
__()
699 @_dataclasses.dataclass(eq
=True, frozen
=True)
700 class MarkdownRecord
:
705 @_functools.total_ordering
706 @_dataclasses.dataclass(eq
=True, frozen
=True)
713 svp64
: SVP64Record
= None
715 def __lt__(self
, other
):
716 if not isinstance(other
, Record
):
717 return NotImplemented
718 lhs
= (min(self
.opcodes
), self
.name
)
719 rhs
= (min(other
.opcodes
), other
.name
)
724 PO
= self
.section
.opcode
726 assert len(self
.ppc
) == 1
727 PO
= self
.ppc
[0].opcode
729 return POStaticOperand(record
=self
,
730 name
="PO", value
=int(PO
.value
), mask
=int(PO
.mask
))
736 PO
= self
.section
.opcode
742 return XOStaticOperand(record
=self
,
743 name
="XO", value
=0, mask
=0)
745 return XOStaticOperand(record
=self
,
746 name
="XO", value
=int(XO
.value
), mask
=int(XO
.mask
))
748 return tuple(dict.fromkeys(map(XO
, self
.ppc
)))
751 def static_operands(self
):
754 operands
.append(self
.PO
)
755 operands
.extend(self
.XO
)
757 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
758 operands
.append(cls(record
=self
, **kwargs
))
760 return tuple(operands
)
763 def dynamic_operands(self
):
766 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
767 operands
.append(cls(record
=self
, **kwargs
))
769 return tuple(operands
)
774 if self
.svp64
is not None:
776 origin_value
= ([0] * bits
)
777 origin_mask
= ([0] * bits
)
779 for operand
in ((self
.PO
,) + tuple(self
.static_operands
)):
780 for (src
, dst
) in enumerate(reversed(operand
.span
)):
781 origin_value
[dst
] = int((operand
.value
& (1 << src
)) != 0)
785 value
= list(origin_value
)
786 mask
= list(origin_mask
)
787 for (src
, dst
) in enumerate(reversed(XO
.span
)):
788 value
[dst
] = int((XO
.value
& (1 << src
)) != 0)
791 value
= Opcode
.Value(int(("".join(map(str, value
))), 2))
792 mask
= Opcode
.Mask(int(("".join(map(str, mask
))), 2))
794 return Opcode(value
=value
, mask
=mask
)
796 return tuple(dict.fromkeys(map(opcode
, self
.XO
)))
798 def match(self
, key
):
799 for opcode
in self
.opcodes
:
800 if opcode
.match(key
):
807 return self
.svp64
.mode
827 if self
.svp64
is None:
833 return self
.ppc
.cr_in
837 return self
.ppc
.cr_in2
841 return self
.ppc
.cr_out
843 ptype
= property(lambda self
: self
.svp64
.ptype
)
844 etype
= property(lambda self
: self
.svp64
.etype
)
846 def extra_idx(self
, key
):
847 return self
.svp64
.extra_idx(key
)
849 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
850 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
851 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
852 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
853 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
854 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
855 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
856 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
858 def __contains__(self
, key
):
859 return self
.mdwn
.operands
.__contains
__(key
)
861 def __getitem__(self
, key
):
862 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
863 return cls(record
=self
, **kwargs
)
869 return bool(self
["Rc"])
872 @_dataclasses.dataclass(eq
=True, frozen
=True)
875 record
: Record
= _dataclasses
.field(repr=False)
877 def __post_init__(self
):
882 span
= self
.record
.fields
[self
.name
]
883 if self
.record
.svp64
is not None:
884 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
887 def assemble(self
, value
, insn
):
889 if isinstance(value
, str):
890 value
= int(value
, 0)
892 raise ValueError("signed operands not allowed")
895 def disassemble(self
, insn
,
896 verbosity
=Verbosity
.NORMAL
, indent
=""):
897 raise NotImplementedError
900 @_dataclasses.dataclass(eq
=True, frozen
=True)
901 class DynamicOperand(Operand
):
902 def disassemble(self
, insn
,
903 verbosity
=Verbosity
.NORMAL
, indent
=""):
907 if verbosity
>= Verbosity
.VERBOSE
:
908 span
= map(str, span
)
909 yield f
"{indent}{self.name}"
910 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
911 yield f
"{indent}{indent}{', '.join(span)}"
913 yield str(int(value
))
916 @_dataclasses.dataclass(eq
=True, frozen
=True)
917 class SignedOperand(DynamicOperand
):
918 def assemble(self
, value
, insn
):
919 if isinstance(value
, str):
920 value
= int(value
, 0)
921 return super().assemble(value
=value
, insn
=insn
)
923 def disassemble(self
, insn
,
924 verbosity
=Verbosity
.NORMAL
, indent
=""):
928 if verbosity
>= Verbosity
.VERBOSE
:
929 span
= map(str, span
)
930 yield f
"{indent}{self.name}"
931 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
932 yield f
"{indent}{indent}{', '.join(span)}"
934 yield str(value
.to_signed_int())
937 @_dataclasses.dataclass(eq
=True, frozen
=True)
938 class StaticOperand(Operand
):
941 def assemble(self
, insn
):
942 return super().assemble(value
=self
.value
, insn
=insn
)
944 def disassemble(self
, insn
,
945 verbosity
=Verbosity
.NORMAL
, indent
=""):
949 if verbosity
>= Verbosity
.VERBOSE
:
950 span
= map(str, span
)
951 yield f
"{indent}{self.name}"
952 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
953 yield f
"{indent}{indent}{', '.join(span)}"
955 yield str(int(value
))
958 @_dataclasses.dataclass(eq
=True, frozen
=True)
959 class POStaticOperand(StaticOperand
):
964 span
= tuple(range(0, 6))
965 if self
.record
.svp64
is not None:
966 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
970 @_dataclasses.dataclass(eq
=True, frozen
=True)
971 class XOStaticOperand(StaticOperand
):
974 def __post_init__(self
):
975 if self
.record
.section
.opcode
is None:
976 assert self
.value
== 0
977 assert self
.mask
== 0
978 object.__setattr
__(self
, "span", ())
981 bits
= self
.record
.section
.bitsel
982 value
= _SelectableInt(value
=self
.value
, bits
=len(bits
))
983 span
= dict(zip(bits
, range(len(bits
))))
984 span_rev
= {value
:key
for (key
, value
) in span
.items()}
986 # This part is tricky: we could have used self.record.static_operands,
987 # but this would cause an infinite recursion, since this code is called
988 # from the self.record.static_operands method already.
990 operands
.extend(self
.record
.mdwn
.operands
.static
)
991 operands
.extend(self
.record
.mdwn
.operands
.dynamic
)
992 for (cls
, kwargs
) in operands
:
993 operand
= cls(record
=self
.record
, **kwargs
)
994 for idx
in operand
.span
:
995 rev
= span
.pop(idx
, None)
997 span_rev
.pop(rev
, None)
999 # This part is simpler: we drop bits which are not in the mask.
1000 for bit
in tuple(span
.values()):
1001 rev
= (len(bits
) - bit
- 1)
1002 if ((self
.mask
& (1 << bit
)) == 0):
1003 idx
= span_rev
.pop(rev
, None)
1007 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1008 span
= tuple(span
.keys())
1009 if self
.record
.svp64
is not None:
1010 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
1012 object.__setattr
__(self
, "value", value
)
1013 object.__setattr
__(self
, "span", span
)
1015 return super().__post
_init
__()
1018 @_dataclasses.dataclass(eq
=True, frozen
=True)
1019 class ImmediateOperand(DynamicOperand
):
1023 @_dataclasses.dataclass(eq
=True, frozen
=True)
1024 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1028 @_dataclasses.dataclass(eq
=True, frozen
=True)
1029 class NonZeroOperand(DynamicOperand
):
1030 def assemble(self
, value
, insn
):
1031 if isinstance(value
, str):
1032 value
= int(value
, 0)
1033 if not isinstance(value
, int):
1034 raise ValueError("non-integer operand")
1036 return super().assemble(value
=value
, insn
=insn
)
1038 def disassemble(self
, insn
,
1039 verbosity
=Verbosity
.NORMAL
, indent
=""):
1043 if verbosity
>= Verbosity
.VERBOSE
:
1044 span
= map(str, span
)
1045 yield f
"{indent}{self.name}"
1046 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1047 yield f
"{indent}{indent}{', '.join(span)}"
1049 yield str(int(value
) + 1)
1052 @_dataclasses.dataclass(eq
=True, frozen
=True)
1053 class ExtendableOperand(DynamicOperand
):
1054 def sv_spec_enter(self
, value
, span
):
1055 return (value
, span
)
1057 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1058 return (value
, span
)
1060 def spec(self
, insn
):
1064 span
= tuple(map(str, span
))
1066 if isinstance(insn
, SVP64Instruction
):
1067 (origin_value
, origin_span
) = (value
, span
)
1068 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1070 extra_idx
= self
.extra_idx
1071 if extra_idx
is _SVExtra
.NONE
:
1072 return (vector
, value
, span
)
1074 if self
.record
.etype
is _SVEtype
.EXTRA3
:
1075 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1076 elif self
.record
.etype
is _SVEtype
.EXTRA2
:
1077 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1079 raise ValueError(self
.record
.etype
)
1082 vector
= bool(spec
[0])
1083 spec_span
= spec
.__class
__
1084 if self
.record
.etype
is _SVEtype
.EXTRA3
:
1085 spec_span
= tuple(map(str, spec_span
[1, 2]))
1087 elif self
.record
.etype
is _SVEtype
.EXTRA2
:
1088 spec_span
= tuple(map(str, spec_span
[1,]))
1089 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1092 spec_span
= (spec_span
+ ("{0}",))
1094 spec_span
= (("{0}",) + spec_span
)
1096 raise ValueError(self
.record
.etype
)
1098 vector_shift
= (2 + (5 - value
.bits
))
1099 scalar_shift
= value
.bits
1100 spec_shift
= (5 - value
.bits
)
1102 bits
= (len(span
) + len(spec_span
))
1103 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1104 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1106 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1107 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1109 value
= ((spec
<< scalar_shift
) | value
)
1110 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1112 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1113 origin_value
=origin_value
, origin_span
=origin_span
)
1115 return (vector
, value
, span
)
1118 def extra_reg(self
):
1119 return _SVExtraReg(self
.name
)
1122 def extra_idx(self
):
1123 for key
in frozenset({
1124 "in1", "in2", "in3", "cr_in", "cr_in2",
1125 "out", "out2", "cr_out",
1127 extra_reg
= self
.record
.svp64
.extra_reg(key
=key
)
1128 if extra_reg
is self
.extra_reg
:
1129 return self
.record
.extra_idx(key
=key
)
1131 return _SVExtra
.NONE
1133 def remap(self
, value
, vector
):
1134 raise NotImplementedError
1136 def assemble(self
, value
, insn
, prefix
):
1139 if isinstance(value
, str):
1140 value
= value
.lower()
1141 if value
.startswith("%"):
1143 if value
.startswith("*"):
1144 if not isinstance(insn
, SVP64Instruction
):
1145 raise ValueError(value
)
1148 if value
.startswith(prefix
):
1149 value
= value
[len(prefix
):]
1150 value
= int(value
, 0)
1152 if isinstance(insn
, SVP64Instruction
):
1153 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1155 extra_idx
= self
.extra_idx
1156 if extra_idx
is _SVExtra
.NONE
:
1157 raise ValueError(self
.record
)
1159 if self
.record
.etype
is _SVEtype
.EXTRA3
:
1160 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1161 elif self
.record
.etype
is _SVEtype
.EXTRA2
:
1162 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1164 raise ValueError(self
.record
.etype
)
1166 return super().assemble(value
=value
, insn
=insn
)
1168 return super().assemble(value
=value
, insn
=insn
)
1170 def disassemble(self
, insn
,
1171 verbosity
=Verbosity
.NORMAL
, prefix
="", indent
=""):
1172 (vector
, value
, span
) = self
.spec(insn
=insn
)
1174 if verbosity
>= Verbosity
.VERBOSE
:
1175 mode
= "vector" if vector
else "scalar"
1176 yield f
"{indent}{self.name} ({mode})"
1177 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1178 yield f
"{indent}{indent}{', '.join(span)}"
1179 if isinstance(insn
, SVP64Instruction
):
1180 extra_idx
= self
.extra_idx
1181 if self
.record
.etype
is _SVEtype
.NONE
:
1182 yield f
"{indent}{indent}extra[none]"
1184 etype
= repr(self
.record
.etype
).lower()
1185 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1187 vector
= "*" if vector
else ""
1188 yield f
"{vector}{prefix}{int(value)}"
1191 @_dataclasses.dataclass(eq
=True, frozen
=True)
1192 class SimpleRegisterOperand(ExtendableOperand
):
1193 def remap(self
, value
, vector
):
1195 extra
= (value
& 0b11)
1196 value
= (value
>> 2)
1198 extra
= (value
>> 5)
1199 value
= (value
& 0b11111)
1201 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1202 # (and shrink to a single bit if ok)
1203 if self
.record
.etype
is _SVEtype
.EXTRA2
:
1205 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1206 assert (extra
& 0b01) == 0, \
1207 ("vector field %s cannot fit into EXTRA2" % value
)
1208 extra
= (0b10 |
(extra
>> 1))
1210 # range is r0-r63 in increments of 1
1211 assert (extra
>> 1) == 0, \
1212 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1214 elif self
.record
.etype
is _SVEtype
.EXTRA3
:
1216 # EXTRA3 vector bit needs marking
1219 raise ValueError(self
.record
.etype
)
1221 return (value
, extra
)
1224 @_dataclasses.dataclass(eq
=True, frozen
=True)
1225 class GPROperand(SimpleRegisterOperand
):
1226 def assemble(self
, value
, insn
):
1227 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1229 def disassemble(self
, insn
,
1230 verbosity
=Verbosity
.NORMAL
, indent
=""):
1231 prefix
= "" if (verbosity
<= Verbosity
.SHORT
) else "r"
1232 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1233 verbosity
=verbosity
, indent
=indent
)
1236 @_dataclasses.dataclass(eq
=True, frozen
=True)
1237 class FPROperand(SimpleRegisterOperand
):
1238 def assemble(self
, value
, insn
):
1239 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1241 def disassemble(self
, insn
,
1242 verbosity
=Verbosity
.NORMAL
, indent
=""):
1243 prefix
= "" if (verbosity
<= Verbosity
.SHORT
) else "f"
1244 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1245 verbosity
=verbosity
, indent
=indent
)
1248 @_dataclasses.dataclass(eq
=True, frozen
=True)
1249 class ConditionRegisterFieldOperand(ExtendableOperand
):
1250 def pattern(name_pattern
):
1251 (name
, pattern
) = name_pattern
1252 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1261 CR
= r
"(?:CR|cr)([0-9]+)"
1263 BIT
= rf
"({'|'.join(CONDS.keys())})"
1264 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1265 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1266 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1267 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1268 XCR
= fr
"{CR}\.{BIT}"
1269 PATTERNS
= tuple(map(pattern
, (
1274 ("BIT+CR", (LBIT
+ CR
)),
1275 ("CR+BIT", (CR
+ RBIT
)),
1276 ("BIT+CR*N", (LBIT
+ CRN
)),
1277 ("CR*N+BIT", (CRN
+ RBIT
)),
1278 ("BIT+N*CR", (LBIT
+ NCR
)),
1279 ("N*CR+BIT", (NCR
+ RBIT
)),
1282 def remap(self
, value
, vector
, regtype
):
1283 if regtype
is _RegType
.CR_5BIT
:
1284 subvalue
= (value
& 0x3)
1288 extra
= (value
& 0xf)
1291 extra
= (value
>> 3)
1294 if self
.record
.etype
is _SVEtype
.EXTRA2
:
1296 assert (extra
& 0x7) == 0, \
1297 "vector CR cannot fit into EXTRA2"
1298 extra
= (0x2 |
(extra
>> 3))
1300 assert (extra
>> 1) == 0, \
1301 "scalar CR cannot fit into EXTRA2"
1303 elif self
.record
.etype
is _SVEtype
.EXTRA3
:
1305 assert (extra
& 0x3) == 0, \
1306 "vector CR cannot fit into EXTRA3"
1307 extra
= (0x4 |
(extra
>> 2))
1309 assert (extra
>> 2) == 0, \
1310 "scalar CR cannot fit into EXTRA3"
1313 if regtype
is _RegType
.CR_5BIT
:
1314 value
= ((value
<< 2) | subvalue
)
1316 return (value
, extra
)
1318 def assemble(self
, value
, insn
):
1319 if isinstance(value
, str):
1322 if value
.startswith("*"):
1323 if not isinstance(insn
, SVP64Instruction
):
1324 raise ValueError(value
)
1328 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1329 match
= pattern
.match(value
)
1330 if match
is not None:
1331 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1332 values
= match
.groups()
1333 match
= dict(zip(keys
, values
))
1334 CR
= int(match
["CR"])
1338 N
= int(match
.get("N", "1"))
1339 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1340 value
= ((CR
* N
) + BIT
)
1343 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1345 def disassemble(self
, insn
,
1346 verbosity
=Verbosity
.NORMAL
, prefix
="", indent
=""):
1347 (vector
, value
, span
) = self
.spec(insn
=insn
)
1349 if verbosity
>= Verbosity
.VERBOSE
:
1350 mode
= "vector" if vector
else "scalar"
1351 yield f
"{indent}{self.name} ({mode})"
1352 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1353 yield f
"{indent}{indent}{', '.join(span)}"
1354 if isinstance(insn
, SVP64Instruction
):
1355 extra_idx
= self
.extra_idx
1356 if self
.record
.etype
is _SVEtype
.NONE
:
1357 yield f
"{indent}{indent}extra[none]"
1359 etype
= repr(self
.record
.etype
).lower()
1360 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1362 vector
= "*" if vector
else ""
1363 cr
= int(value
>> 2)
1365 cond
= ("lt", "gt", "eq", "so")[cc
]
1366 if verbosity
>= Verbosity
.NORMAL
:
1368 if isinstance(insn
, SVP64Instruction
):
1369 yield f
"{vector}cr{cr}.{cond}"
1371 yield f
"4*cr{cr}+{cond}"
1375 yield f
"{vector}{prefix}{int(value)}"
1378 @_dataclasses.dataclass(eq
=True, frozen
=True)
1379 class CR3Operand(ConditionRegisterFieldOperand
):
1380 def remap(self
, value
, vector
):
1381 return super().remap(value
=value
, vector
=vector
,
1382 regtype
=_RegType
.CR_3BIT
)
1385 @_dataclasses.dataclass(eq
=True, frozen
=True)
1386 class CR5Operand(ConditionRegisterFieldOperand
):
1387 def remap(self
, value
, vector
):
1388 return super().remap(value
=value
, vector
=vector
,
1389 regtype
=_RegType
.CR_5BIT
)
1391 def sv_spec_enter(self
, value
, span
):
1392 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1393 return (value
, span
)
1395 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1396 value
= _selectconcat(value
, origin_value
[3:5])
1398 return (value
, span
)
1401 @_dataclasses.dataclass(eq
=True, frozen
=True)
1402 class EXTSOperand(DynamicOperand
):
1403 field
: str # real name to report
1404 nz
: int = 0 # number of zeros
1405 fmt
: str = "d" # integer formatter
1407 def __post_init__(self
):
1409 object.__setattr
__(self
, "field", self
.name
)
1413 span
= self
.record
.fields
[self
.field
]
1414 if self
.record
.svp64
is not None:
1415 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
1418 def disassemble(self
, insn
,
1419 verbosity
=Verbosity
.NORMAL
, indent
=""):
1423 if verbosity
>= Verbosity
.VERBOSE
:
1424 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1425 zeros
= ("0" * self
.nz
)
1426 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1427 yield f
"{indent * 1}{hint}"
1428 yield f
"{indent * 2}{self.field}"
1429 yield f
"{indent * 3}{int(value):0{value.bits}b}{zeros}"
1430 yield f
"{indent * 3}{', '.join(span)}"
1432 value
= _selectconcat(value
,
1433 _SelectableInt(value
=0, bits
=self
.nz
)).to_signed_int()
1434 yield f
"{value:{self.fmt}}"
1437 @_dataclasses.dataclass(eq
=True, frozen
=True)
1438 class TargetAddrOperand(EXTSOperand
):
1443 @_dataclasses.dataclass(eq
=True, frozen
=True)
1444 class TargetAddrOperandLI(TargetAddrOperand
):
1448 @_dataclasses.dataclass(eq
=True, frozen
=True)
1449 class TargetAddrOperandBD(TargetAddrOperand
):
1453 @_dataclasses.dataclass(eq
=True, frozen
=True)
1454 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1459 @_dataclasses.dataclass(eq
=True, frozen
=True)
1460 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1465 @_dataclasses.dataclass(eq
=True, frozen
=True)
1466 class DOperandDX(SignedOperand
):
1469 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1470 operands
= map(cls
, ("d0", "d1", "d2"))
1471 spans
= map(lambda operand
: operand
.span
, operands
)
1472 span
= sum(spans
, tuple())
1473 if self
.record
.svp64
is not None:
1474 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
1477 def disassemble(self
, insn
,
1478 verbosity
=Verbosity
.NORMAL
, indent
=""):
1482 if verbosity
>= Verbosity
.VERBOSE
:
1489 for (subname
, subspan
) in mapping
.items():
1490 operand
= DynamicOperand(name
=subname
)
1493 span
= map(str, span
)
1494 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1495 yield f
"{indent}{indent}{indent}{int(value):0{value.bits}b}"
1496 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1498 yield str(value
.to_signed_int())
1501 class Instruction(_Mapping
):
1503 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1504 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1505 raise ValueError(bits
)
1507 if isinstance(value
, bytes
):
1508 if ((len(value
) * 8) != bits
):
1509 raise ValueError(f
"bit length mismatch")
1510 value
= int.from_bytes(value
, byteorder
=byteorder
)
1512 if isinstance(value
, int):
1513 value
= _SelectableInt(value
=value
, bits
=bits
)
1514 elif isinstance(value
, Instruction
):
1515 value
= value
.storage
1517 if not isinstance(value
, _SelectableInt
):
1518 raise ValueError(value
)
1521 if len(value
) != bits
:
1522 raise ValueError(value
)
1524 value
= _SelectableInt(value
=value
, bits
=bits
)
1526 return cls(storage
=value
)
1529 return hash(int(self
))
1531 def __getitem__(self
, key
):
1532 return self
.storage
.__getitem
__(key
)
1534 def __setitem__(self
, key
, value
):
1535 return self
.storage
.__setitem
__(key
, value
)
1537 def bytes(self
, byteorder
="little"):
1538 nr_bytes
= (len(self
.__class
__) // 8)
1539 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1541 def record(self
, db
):
1544 raise KeyError(self
)
1547 def spec(self
, db
, prefix
):
1548 record
= self
.record(db
=db
)
1550 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1551 self
.dynamic_operands(db
=db
)))
1553 static_operands
= []
1554 for (name
, value
) in self
.static_operands(db
=db
):
1555 static_operands
.append(f
"{name}={value}")
1558 if dynamic_operands
:
1560 operands
+= ",".join(dynamic_operands
)
1563 operands
+= " ".join(static_operands
)
1565 return f
"{prefix}{record.name}{operands}"
1567 def dynamic_operands(self
, db
, verbosity
=Verbosity
.NORMAL
):
1568 record
= self
.record(db
=db
)
1573 for operand
in record
.dynamic_operands
:
1575 value
= " ".join(operand
.disassemble(insn
=self
,
1576 verbosity
=min(verbosity
, Verbosity
.NORMAL
)))
1578 name
= f
"{imm_name}({name})"
1579 value
= f
"{imm_value}({value})"
1581 if isinstance(operand
, ImmediateOperand
):
1588 def static_operands(self
, db
):
1589 record
= self
.record(db
=db
)
1590 for operand
in record
.static_operands
:
1591 yield (operand
.name
, operand
.value
)
1594 def assemble(cls
, db
, opcode
, arguments
=None):
1595 raise NotImplementedError(f
"{cls.__name__}.assemble")
1597 def disassemble(self
, db
,
1599 verbosity
=Verbosity
.NORMAL
):
1600 raise NotImplementedError
1603 class WordInstruction(Instruction
):
1604 _
: _Field
= range(0, 32)
1605 PO
: _Field
= range(0, 6)
1608 def integer(cls
, value
, byteorder
="little"):
1609 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1614 for idx
in range(32):
1615 bit
= int(self
[idx
])
1617 return "".join(map(str, bits
))
1620 def assemble(cls
, db
, opcode
, arguments
=None):
1621 if arguments
is None:
1625 insn
= cls
.integer(value
=0)
1626 for operand
in record
.static_operands
:
1627 operand
.assemble(insn
=insn
)
1629 dynamic_operands
= tuple(record
.dynamic_operands
)
1630 if len(dynamic_operands
) != len(arguments
):
1631 raise ValueError("operands count mismatch")
1632 for (value
, operand
) in zip(arguments
, dynamic_operands
):
1633 operand
.assemble(value
=value
, insn
=insn
)
1637 def disassemble(self
, db
,
1639 verbosity
=Verbosity
.NORMAL
):
1640 if verbosity
<= Verbosity
.SHORT
:
1643 blob
= self
.bytes(byteorder
=byteorder
)
1644 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1649 yield f
"{blob}.long 0x{int(self):08x}"
1652 operands
= tuple(map(_operator
.itemgetter(1),
1653 self
.dynamic_operands(db
=db
, verbosity
=verbosity
)))
1655 operands
= ",".join(operands
)
1656 yield f
"{blob}{record.name} {operands}"
1658 yield f
"{blob}{record.name}"
1660 if verbosity
>= Verbosity
.VERBOSE
:
1662 binary
= self
.binary
1663 spec
= self
.spec(db
=db
, prefix
="")
1664 yield f
"{indent}spec"
1665 yield f
"{indent}{indent}{spec}"
1666 yield f
"{indent}pcode"
1667 for stmt
in record
.mdwn
.pcode
:
1668 yield f
"{indent}{indent}{stmt}"
1669 yield f
"{indent}binary"
1670 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1671 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1672 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1673 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1674 yield f
"{indent}opcodes"
1675 for opcode
in record
.opcodes
:
1676 yield f
"{indent}{indent}{opcode!r}"
1677 for (cls
, kwargs
) in record
.mdwn
.operands
:
1678 operand
= cls(record
=record
, **kwargs
)
1679 yield from operand
.disassemble(insn
=self
,
1680 verbosity
=verbosity
, indent
=indent
)
1684 class PrefixedInstruction(Instruction
):
1685 class Prefix(WordInstruction
.remap(range(0, 32))):
1688 class Suffix(WordInstruction
.remap(range(32, 64))):
1691 _
: _Field
= range(64)
1697 def integer(cls
, value
, byteorder
="little"):
1698 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
1701 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
1702 def transform(value
):
1703 return WordInstruction
.integer(value
=value
,
1704 byteorder
=byteorder
)[0:32]
1706 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
1707 value
= _selectconcat(prefix
, suffix
)
1709 return super().integer(bits
=64, value
=value
)
1712 class Mode(_Mapping
):
1713 _
: _Field
= range(0, 5)
1716 class Extra(_Mapping
):
1717 _
: _Field
= range(0, 9)
1720 class Extra2(Extra
):
1721 idx0
: _Field
= range(0, 2)
1722 idx1
: _Field
= range(2, 4)
1723 idx2
: _Field
= range(4, 6)
1724 idx3
: _Field
= range(6, 8)
1726 def __getitem__(self
, key
):
1732 _SVExtra
.Idx0
: self
.idx0
,
1733 _SVExtra
.Idx1
: self
.idx1
,
1734 _SVExtra
.Idx2
: self
.idx2
,
1735 _SVExtra
.Idx3
: self
.idx3
,
1738 def __setitem__(self
, key
, value
):
1739 self
[key
].assign(value
)
1742 class Extra3(Extra
):
1743 idx0
: _Field
= range(0, 3)
1744 idx1
: _Field
= range(3, 6)
1745 idx2
: _Field
= range(6, 9)
1747 def __getitem__(self
, key
):
1752 _SVExtra
.Idx0
: self
.idx0
,
1753 _SVExtra
.Idx1
: self
.idx1
,
1754 _SVExtra
.Idx2
: self
.idx2
,
1757 def __setitem__(self
, key
, value
):
1758 self
[key
].assign(value
)
1761 class BaseRM(_Mapping
):
1762 _
: _Field
= range(24)
1763 mmode
: _Field
= (0,)
1764 mask
: _Field
= range(1, 4)
1765 elwidth
: _Field
= range(4, 6)
1766 ewsrc
: _Field
= range(6, 8)
1767 subvl
: _Field
= range(8, 10)
1768 mode
: Mode
.remap(range(19, 24))
1769 smask
: _Field
= range(16, 19)
1770 extra
: Extra
.remap(range(10, 19))
1771 extra2
: Extra2
.remap(range(10, 19))
1772 extra3
: Extra3
.remap(range(10, 19))
1774 def specifiers(self
, record
):
1775 subvl
= int(self
.subvl
)
1783 def disassemble(self
, verbosity
=Verbosity
.NORMAL
):
1784 if verbosity
>= Verbosity
.VERBOSE
:
1786 for (name
, span
) in self
.traverse(path
="RM"):
1787 value
= self
.storage
[span
]
1789 yield f
"{indent}{int(value):0{value.bits}b}"
1790 yield f
"{indent}{', '.join(map(str, span))}"
1793 class FFPRRc1BaseRM(BaseRM
):
1794 def specifiers(self
, record
, mode
):
1795 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
1796 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
1797 mask
= int(_selectconcat(CR
, inv
))
1798 predicate
= PredicateBaseRM
.predicate(True, mask
)
1799 yield f
"{mode}={predicate}"
1801 yield from super().specifiers(record
=record
)
1804 class FFPRRc0BaseRM(BaseRM
):
1805 def specifiers(self
, record
, mode
):
1807 inv
= "~" if self
.inv
else ""
1808 yield f
"{mode}={inv}RC1"
1810 yield from super().specifiers(record
=record
)
1813 class SatBaseRM(BaseRM
):
1814 def specifiers(self
, record
):
1820 yield from super().specifiers(record
=record
)
1823 class ZZBaseRM(BaseRM
):
1824 def specifiers(self
, record
):
1828 yield from super().specifiers(record
=record
)
1831 class DZBaseRM(BaseRM
):
1832 def specifiers(self
, record
):
1836 yield from super().specifiers(record
=record
)
1839 class SZBaseRM(BaseRM
):
1840 def specifiers(self
, record
):
1844 yield from super().specifiers(record
=record
)
1847 class MRBaseRM(BaseRM
):
1848 def specifiers(self
, record
):
1854 yield from super().specifiers(record
=record
)
1857 class ElsBaseRM(BaseRM
):
1858 def specifiers(self
, record
):
1862 yield from super().specifiers(record
=record
)
1865 class WidthBaseRM(BaseRM
):
1867 def width(FP
, width
):
1876 width
= ("fp" + width
)
1879 def specifiers(self
, record
):
1880 # elwidths: use "w=" if same otherwise dw/sw
1881 # FIXME this should consider FP instructions
1883 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
1884 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
1893 yield from super().specifiers(record
=record
)
1896 class PredicateBaseRM(BaseRM
):
1898 def predicate(CR
, mask
):
1901 (False, 0b001): "1<<r3",
1902 (False, 0b010): "r3",
1903 (False, 0b011): "~r3",
1904 (False, 0b100): "r10",
1905 (False, 0b101): "~r10",
1906 (False, 0b110): "r30",
1907 (False, 0b111): "~r30",
1909 (True, 0b000): "lt",
1910 (True, 0b001): "ge",
1911 (True, 0b010): "gt",
1912 (True, 0b011): "le",
1913 (True, 0b100): "eq",
1914 (True, 0b101): "ne",
1915 (True, 0b110): "so",
1916 (True, 0b111): "ns",
1919 def specifiers(self
, record
):
1920 # predication - single and twin
1921 # use "m=" if same otherwise sm/dm
1922 CR
= (int(self
.mmode
) == 1)
1923 mask
= int(self
.mask
)
1924 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
1925 if record
.svp64
.ptype
is _SVPtype
.P2
:
1926 smask
= int(self
.smask
)
1927 sm
= PredicateBaseRM
.predicate(CR
, smask
)
1936 yield from super().specifiers(record
=record
)
1939 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
1943 class SEABaseRM(BaseRM
):
1944 def specifiers(self
, record
):
1948 yield from super().specifiers(record
=record
)
1951 class VLiBaseRM(BaseRM
):
1952 def specifiers(self
, record
):
1956 yield from super().specifiers(record
=record
)
1959 class NormalBaseRM(PredicateWidthBaseRM
):
1962 https://libre-soc.org/openpower/sv/normal/
1967 class NormalSimpleRM(DZBaseRM
, SZBaseRM
, NormalBaseRM
):
1968 """normal: simple mode"""
1972 def specifiers(self
, record
):
1973 yield from super().specifiers(record
=record
)
1976 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
1977 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
1981 class NormalFFRc1RM(FFPRRc1BaseRM
, NormalBaseRM
):
1982 """normal: Rc=1: ffirst CR sel"""
1984 CR
: BaseRM
.mode
[3, 4]
1986 def specifiers(self
, record
):
1987 yield from super().specifiers(record
=record
, mode
="ff")
1990 class NormalFFRc0RM(FFPRRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
1991 """normal: Rc=0: ffirst z/nonz"""
1996 def specifiers(self
, record
):
1997 yield from super().specifiers(record
=record
, mode
="ff")
2000 class NormalSatRM(SatBaseRM
, DZBaseRM
, SZBaseRM
, NormalBaseRM
):
2001 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2007 class NormalPRRc1RM(FFPRRc1BaseRM
, NormalBaseRM
):
2008 """normal: Rc=1: pred-result CR sel"""
2010 CR
: BaseRM
.mode
[3, 4]
2012 def specifiers(self
, record
):
2013 yield from super().specifiers(record
=record
, mode
="pr")
2016 class NormalPRRc0RM(FFPRRc0BaseRM
, ZZBaseRM
, NormalBaseRM
):
2017 """normal: Rc=0: pred-result z/nonz"""
2024 def specifiers(self
, record
):
2025 yield from super().specifiers(record
=record
, mode
="pr")
2028 class NormalRM(NormalBaseRM
):
2029 simple
: NormalSimpleRM
2031 ffrc1
: NormalFFRc1RM
2032 ffrc0
: NormalFFRc0RM
2034 prrc1
: NormalPRRc1RM
2035 prrc0
: NormalPRRc0RM
2038 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2040 LD/ST Immediate mode
2041 https://libre-soc.org/openpower/sv/ldst/
2046 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2047 """ld/st immediate: simple mode"""
2054 class LDSTImmPostRM(LDSTImmBaseRM
):
2055 """ld/st immediate: postinc mode (and load-fault)"""
2056 pi
: BaseRM
.mode
[3] # Post-Increment Mode
2057 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2059 def specifiers(self
, record
):
2066 class LDSTImmFFRc1RM(FFPRRc1BaseRM
, LDSTImmBaseRM
):
2067 """ld/st immediate: Rc=1: ffirst CR sel"""
2069 CR
: BaseRM
.mode
[3, 4]
2071 def specifiers(self
, record
):
2072 yield from super().specifiers(record
=record
, mode
="ff")
2075 class LDSTImmFFRc0RM(FFPRRc0BaseRM
, ElsBaseRM
, LDSTImmBaseRM
):
2076 """ld/st immediate: Rc=0: ffirst z/nonz"""
2081 def specifiers(self
, record
):
2082 yield from super().specifiers(record
=record
, mode
="ff")
2085 class LDSTImmSatRM(ElsBaseRM
, SatBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2086 """ld/st immediate: sat mode: N=0/1 u/s"""
2094 class LDSTImmPRRc1RM(FFPRRc1BaseRM
, LDSTImmBaseRM
):
2095 """ld/st immediate: Rc=1: pred-result CR sel"""
2097 CR
: BaseRM
.mode
[3, 4]
2099 def specifiers(self
, record
):
2100 yield from super().specifiers(record
=record
, mode
="pr")
2103 class LDSTImmPRRc0RM(FFPRRc0BaseRM
, ElsBaseRM
, LDSTImmBaseRM
):
2104 """ld/st immediate: Rc=0: pred-result z/nonz"""
2109 def specifiers(self
, record
):
2110 yield from super().specifiers(record
=record
, mode
="pr")
2113 class LDSTImmRM(LDSTImmBaseRM
):
2114 simple
: LDSTImmSimpleRM
2116 ffrc1
: LDSTImmFFRc1RM
2117 ffrc0
: LDSTImmFFRc0RM
2119 prrc1
: LDSTImmPRRc1RM
2120 prrc0
: LDSTImmPRRc0RM
2123 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2126 https://libre-soc.org/openpower/sv/ldst/
2131 class LDSTIdxSimpleRM(SEABaseRM
, DZBaseRM
, SZBaseRM
, LDSTIdxBaseRM
):
2132 """ld/st index: simple mode"""
2138 class LDSTIdxStrideRM(SEABaseRM
, DZBaseRM
, SZBaseRM
, LDSTIdxBaseRM
):
2139 """ld/st index: strided (scalar only source)"""
2144 def specifiers(self
, record
):
2147 yield from super().specifiers(record
=record
)
2150 class LDSTIdxSatRM(SatBaseRM
, DZBaseRM
, SZBaseRM
, LDSTIdxBaseRM
):
2151 """ld/st index: sat mode: N=0/1 u/s"""
2157 class LDSTIdxPRRc1RM(LDSTIdxBaseRM
):
2158 """ld/st index: Rc=1: pred-result CR sel"""
2160 CR
: BaseRM
.mode
[3, 4]
2162 def specifiers(self
, record
):
2163 yield from super().specifiers(record
=record
, mode
="pr")
2166 class LDSTIdxPRRc0RM(FFPRRc0BaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2167 """ld/st index: Rc=0: pred-result z/nonz"""
2174 def specifiers(self
, record
):
2175 yield from super().specifiers(record
=record
, mode
="pr")
2178 class LDSTIdxRM(LDSTIdxBaseRM
):
2179 simple
: LDSTIdxSimpleRM
2180 stride
: LDSTIdxStrideRM
2182 prrc1
: LDSTIdxPRRc1RM
2183 prrc0
: LDSTIdxPRRc0RM
2187 class CROpBaseRM(BaseRM
):
2190 https://libre-soc.org/openpower/sv/cr_ops/
2195 class CROpSimpleRM(PredicateBaseRM
, DZBaseRM
, SZBaseRM
, CROpBaseRM
):
2196 """cr_op: simple mode"""
2201 def specifiers(self
, record
):
2203 yield "rg" # simple CR Mode reports /rg
2205 yield from super().specifiers(record
=record
)
2207 class CROpMRRM(MRBaseRM
, DZBaseRM
, SZBaseRM
, CROpBaseRM
):
2208 """cr_op: scalar reduce mode (mapreduce), SUBVL=1"""
2214 class CROpFF3RM(FFPRRc1BaseRM
, VLiBaseRM
, ZZBaseRM
, PredicateBaseRM
, CROpBaseRM
):
2215 """cr_op: ffirst 3-bit mode"""
2223 def specifiers(self
, record
):
2224 yield from super().specifiers(record
=record
, mode
="ff")
2227 class CROpFF5RM(FFPRRc0BaseRM
, PredicateBaseRM
,
2228 VLiBaseRM
, DZBaseRM
, SZBaseRM
, CROpBaseRM
):
2229 """cr_op: ffirst 5-bit mode"""
2232 RC1
: BaseRM
[19] # cheat: set RC=1 based on ffirst mode being set
2236 def specifiers(self
, record
):
2237 yield from super().specifiers(record
=record
, mode
="ff")
2240 class CROpRM(CROpBaseRM
):
2241 simple
: CROpSimpleRM
2247 # ********************
2249 # https://libre-soc.org/openpower/sv/branches/
2250 class BranchBaseRM(BaseRM
):
2260 def specifiers(self
, record
):
2272 raise ValueError(self
.sz
)
2284 # Branch modes lack source mask.
2285 # Therefore a custom code is needed.
2286 CR
= (int(self
.mmode
) == 1)
2287 mask
= int(self
.mask
)
2288 m
= PredicateBaseRM
.predicate(CR
, mask
)
2292 yield from super().specifiers(record
=record
)
2295 class BranchSimpleRM(BranchBaseRM
):
2296 """branch: simple mode"""
2300 class BranchVLSRM(BranchBaseRM
):
2301 """branch: VLSET mode"""
2305 def specifiers(self
, record
):
2311 }[int(self
.VSb
), int(self
.VLi
)]
2313 yield from super().specifiers(record
=record
)
2316 class BranchCTRRM(BranchBaseRM
):
2317 """branch: CTR-test mode"""
2320 def specifiers(self
, record
):
2326 yield from super().specifiers(record
=record
)
2329 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2330 """branch: CTR-test+VLSET mode"""
2334 class BranchRM(BranchBaseRM
):
2335 simple
: BranchSimpleRM
2338 ctrvls
: BranchCTRVLSRM
2348 def select(self
, record
):
2352 # the idea behind these tables is that they are now literally
2353 # in identical format to insndb.csv and minor_xx.csv and can
2354 # be done precisely as that. the only thing to watch out for
2355 # is the insertion of Rc=1 as a "mask/value" bit and likewise
2356 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
2359 if record
.svp64
.mode
is _SVMode
.NORMAL
:
2360 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
2361 # mode Rc mask Rc member
2363 (0b000000, 0b111000, "simple"), # simple (no Rc)
2364 (0b001000, 0b111000, "mr"), # mapreduce (no Rc)
2365 (0b010001, 0b110001, "ffrc1"), # ffirst, Rc=1
2366 (0b010000, 0b110001, "ffrc0"), # ffirst, Rc=0
2367 (0b100000, 0b110000, "sat"), # saturation (no Rc)
2368 (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
2369 (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
2372 search
= ((int(rm
.mode
) << 1) | Rc
)
2374 elif record
.svp64
.mode
is _SVMode
.LDST_IMM
:
2375 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
2376 # mode Rc mask Rc member
2377 # ironically/coincidentally this table is identical to NORMAL
2378 # mode except reserved in place of mr
2380 (0b000000, 0b111000, "simple"), # simple (no Rc)
2381 (0b001000, 0b111000, "post"), # post (no Rc)
2382 (0b010001, 0b110001, "ffrc1"), # ffirst, Rc=1
2383 (0b010000, 0b110001, "ffrc0"), # ffirst, Rc=0
2384 (0b100000, 0b110000, "sat"), # saturation (no Rc)
2385 (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
2386 (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
2389 search
= ((int(rm
.mode
) << 1) | Rc
)
2391 elif record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2392 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
2393 # mode Rc mask Rc member
2395 (0b000000, 0b110000, "simple"), # simple (no Rc)
2396 (0b010000, 0b110000, "stride"), # strided, (no Rc)
2397 (0b100000, 0b110000, "sat"), # saturation (no Rc)
2398 (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
2399 (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
2402 search
= ((int(rm
.mode
) << 1) | Rc
)
2404 elif record
.svp64
.mode
is _SVMode
.CROP
:
2405 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
2406 # mode 3b mask 3b member
2408 (0b000000, 0b111000, "simple"), # simple
2409 (0b001000, 0b111000, "mr"), # mapreduce
2410 (0b100001, 0b100001, "ff3"), # ffirst, 3-bit CR
2411 (0b100000, 0b100000, "ff5"), # ffirst, 5-bit CR
2414 search
= ((int(rm
.mode
) << 1) |
int(record
.svp64
.cr_3bit
))
2416 elif record
.svp64
.mode
is _SVMode
.BRANCH
:
2420 (0b00, 0b11, "simple"), # simple
2421 (0b01, 0b11, "vls"), # VLset
2422 (0b10, 0b11, "ctr"), # CTR mode
2423 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
2425 # slightly weird: doesn't have a 5-bit "mode" field like others
2427 search
= int(rm
.mode
[0, 1])
2430 if table
is not None:
2431 for (value
, mask
, member
) in table
:
2432 if ((value
& mask
) == (search
& mask
)):
2433 rm
= getattr(rm
, member
)
2436 if rm
.__class
__ is self
.__class
__:
2437 raise ValueError(self
)
2442 class SVP64Instruction(PrefixedInstruction
):
2443 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
2444 class Prefix(PrefixedInstruction
.Prefix
):
2446 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
2450 def record(self
, db
):
2451 record
= db
[self
.suffix
]
2453 raise KeyError(self
)
2459 for idx
in range(64):
2460 bit
= int(self
[idx
])
2462 return "".join(map(str, bits
))
2465 def assemble(cls
, db
, opcode
, arguments
=None):
2466 if arguments
is None:
2470 insn
= cls
.integer(value
=0)
2472 for operand
in record
.static_operands
:
2473 operand
.assemble(insn
=insn
)
2475 dynamic_operands
= tuple(record
.dynamic_operands
)
2476 if len(dynamic_operands
) != len(arguments
):
2477 raise ValueError("operands count mismatch")
2478 for (value
, operand
) in zip(arguments
, dynamic_operands
):
2479 operand
.assemble(value
=value
, insn
=insn
)
2481 insn
.prefix
.PO
= 0x1
2482 insn
.prefix
.id = 0x3
2486 def disassemble(self
, db
,
2488 verbosity
=Verbosity
.NORMAL
):
2490 if verbosity
<= Verbosity
.SHORT
:
2493 blob
= insn
.bytes(byteorder
=byteorder
)
2494 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
2497 record
= self
.record(db
=db
)
2498 blob_prefix
= blob(self
.prefix
)
2499 blob_suffix
= blob(self
.suffix
)
2500 if record
is None or record
.svp64
is None:
2501 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
2502 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
2505 name
= f
"sv.{record.name}"
2507 rm
= self
.prefix
.rm
.select(record
=record
)
2509 # convert specifiers to /x/y/z (sorted lexicographically)
2510 specifiers
= sorted(rm
.specifiers(record
=record
))
2511 if specifiers
: # if any add one extra to get the extra "/"
2512 specifiers
= ([""] + specifiers
)
2513 specifiers
= "/".join(specifiers
)
2515 # convert operands to " ,x,y,z"
2516 operands
= tuple(map(_operator
.itemgetter(1),
2517 self
.dynamic_operands(db
=db
, verbosity
=verbosity
)))
2518 operands
= ",".join(operands
)
2519 if len(operands
) > 0: # if any separate with a space
2520 operands
= (" " + operands
)
2522 yield f
"{blob_prefix}{name}{specifiers}{operands}"
2524 yield f
"{blob_suffix}"
2526 if verbosity
>= Verbosity
.VERBOSE
:
2528 binary
= self
.binary
2529 spec
= self
.spec(db
=db
, prefix
="sv.")
2531 yield f
"{indent}spec"
2532 yield f
"{indent}{indent}{spec}"
2533 yield f
"{indent}pcode"
2534 for stmt
in record
.mdwn
.pcode
:
2535 yield f
"{indent}{indent}{stmt}"
2536 yield f
"{indent}binary"
2537 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
2538 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
2539 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
2540 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
2541 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
2542 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
2543 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
2544 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
2545 yield f
"{indent}opcodes"
2546 for opcode
in record
.opcodes
:
2547 yield f
"{indent}{indent}{opcode!r}"
2548 for (cls
, kwargs
) in record
.mdwn
.operands
:
2549 operand
= cls(record
=record
, **kwargs
)
2550 yield from operand
.disassemble(insn
=self
,
2551 verbosity
=verbosity
, indent
=indent
)
2553 yield f
"{indent}{indent}{rm.__doc__}"
2554 for line
in rm
.disassemble(verbosity
=verbosity
):
2555 yield f
"{indent}{indent}{line}"
2559 def parse(stream
, factory
):
2561 return ("TODO" not in frozenset(entry
.values()))
2563 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
2564 entries
= _csv
.DictReader(lines
)
2565 entries
= filter(match
, entries
)
2566 return tuple(map(factory
, entries
))
2569 class MarkdownDatabase
:
2572 for (name
, desc
) in _ISA():
2575 (dynamic
, *static
) = desc
.regs
2576 operands
.extend(dynamic
)
2577 operands
.extend(static
)
2578 pcode
= PCode(iterable
=desc
.pcode
)
2579 operands
= Operands(insn
=name
, iterable
=operands
)
2580 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
2582 self
.__db
= dict(sorted(db
.items()))
2584 return super().__init
__()
2587 yield from self
.__db
.items()
2589 def __contains__(self
, key
):
2590 return self
.__db
.__contains
__(key
)
2592 def __getitem__(self
, key
):
2593 return self
.__db
.__getitem
__(key
)
2596 class FieldsDatabase
:
2599 df
= _DecodeFields()
2601 for (form
, fields
) in df
.instrs
.items():
2602 if form
in {"DQE", "TX"}:
2606 db
[_Form
[form
]] = Fields(fields
)
2610 return super().__init
__()
2612 def __getitem__(self
, key
):
2613 return self
.__db
.__getitem
__(key
)
2617 def __init__(self
, root
, mdwndb
):
2618 # The code below groups the instructions by name:section.
2619 # There can be multiple names for the same instruction.
2620 # The point is to capture different opcodes for the same instruction.
2621 dd
= _collections
.defaultdict
2623 records
= _collections
.defaultdict(set)
2624 path
= (root
/ "insndb.csv")
2625 with
open(path
, "r", encoding
="UTF-8") as stream
:
2626 for section
in sorted(parse(stream
, Section
.CSV
)):
2627 path
= (root
/ section
.path
)
2629 section
.Mode
.INTEGER
: IntegerOpcode
,
2630 section
.Mode
.PATTERN
: PatternOpcode
,
2632 factory
= _functools
.partial(
2633 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
2634 with
open(path
, "r", encoding
="UTF-8") as stream
:
2635 for insn
in parse(stream
, factory
):
2636 for name
in insn
.names
:
2637 records
[name
].add(insn
)
2638 sections
[name
] = section
2640 items
= sorted(records
.items())
2642 for (name
, multirecord
) in items
:
2643 records
[name
] = PPCMultiRecord(sorted(multirecord
))
2645 def exact_match(name
):
2646 record
= records
.get(name
)
2652 if not name
.endswith("l"):
2654 alias
= exact_match(name
[:-1])
2657 record
= records
[alias
]
2658 if "lk" not in record
.flags
:
2659 raise ValueError(record
)
2663 if not name
.endswith("a"):
2665 alias
= LK_match(name
[:-1])
2668 record
= records
[alias
]
2669 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
2670 raise ValueError(record
)
2671 if "AA" not in mdwndb
[name
].operands
:
2672 raise ValueError(record
)
2676 if not name
.endswith("."):
2678 alias
= exact_match(name
[:-1])
2681 record
= records
[alias
]
2682 if record
.Rc
is _RCOE
.NONE
:
2683 raise ValueError(record
)
2687 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
2688 for (name
, _
) in mdwndb
:
2689 if name
.startswith("sv."):
2692 for match
in matches
:
2694 if alias
is not None:
2698 section
= sections
[alias
]
2699 record
= records
[alias
]
2700 db
[name
] = (section
, record
)
2702 self
.__db
= dict(sorted(db
.items()))
2704 return super().__init
__()
2706 @_functools.lru_cache(maxsize
=512, typed
=False)
2707 def __getitem__(self
, key
):
2708 return self
.__db
.get(key
, (None, None))
2711 class SVP64Database
:
2712 def __init__(self
, root
, ppcdb
):
2714 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
2715 for (prefix
, _
, names
) in _os
.walk(root
):
2716 prefix
= _pathlib
.Path(prefix
)
2717 for name
in filter(lambda name
: pattern
.match(name
), names
):
2718 path
= (prefix
/ _pathlib
.Path(name
))
2719 with
open(path
, "r", encoding
="UTF-8") as stream
:
2720 db
.update(parse(stream
, SVP64Record
.CSV
))
2721 db
= {record
.name
:record
for record
in db
}
2723 self
.__db
= dict(sorted(db
.items()))
2724 self
.__ppcdb
= ppcdb
2726 return super().__init
__()
2728 def __getitem__(self
, key
):
2729 (_
, record
) = self
.__ppcdb
[key
]
2733 for name
in record
.names
:
2734 record
= self
.__db
.get(name
, None)
2735 if record
is not None:
2742 def __init__(self
, root
):
2743 root
= _pathlib
.Path(root
)
2744 mdwndb
= MarkdownDatabase()
2745 fieldsdb
= FieldsDatabase()
2746 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
2747 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
2751 opcodes
= _collections
.defaultdict(
2752 lambda: _collections
.defaultdict(set))
2754 for (name
, mdwn
) in mdwndb
:
2755 if name
.startswith("sv."):
2757 (section
, ppc
) = ppcdb
[name
]
2760 svp64
= svp64db
[name
]
2761 fields
= fieldsdb
[ppc
.form
]
2762 record
= Record(name
=name
,
2763 section
=section
, ppc
=ppc
, svp64
=svp64
,
2764 mdwn
=mdwn
, fields
=fields
)
2766 names
[record
.name
] = record
2770 opcodes
[section
][PO
.value
].add(record
)
2772 self
.__db
= sorted(db
)
2773 self
.__names
= dict(sorted(names
.items()))
2774 self
.__opcodes
= dict(sorted(opcodes
.items()))
2776 return super().__init
__()
2779 return repr(self
.__db
)
2782 yield from self
.__db
2784 @_functools.lru_cache(maxsize
=None)
2785 def __contains__(self
, key
):
2786 return self
.__getitem
__(key
) is not None
2788 @_functools.lru_cache(maxsize
=None)
2789 def __getitem__(self
, key
):
2790 if isinstance(key
, Instruction
):
2793 for (section
, group
) in self
.__opcodes
.items():
2794 for record
in group
[PO
]:
2795 if record
.match(key
=key
):
2800 elif isinstance(key
, str):
2801 return self
.__names
.get(key
)
2803 raise ValueError("instruction or name expected")