1 import collections
as _collections
2 import contextlib
as _contextlib
4 import dataclasses
as _dataclasses
6 import functools
as _functools
8 import operator
as _operator
9 import pathlib
as _pathlib
11 import types
as _types
12 import typing
as _typing
15 from functools
import cached_property
17 from cached_property
import cached_property
19 from openpower
.decoder
.power_enums
import (
20 Function
as _Function
,
27 CRIn2Sel
as _CRIn2Sel
,
28 CROutSel
as _CROutSel
,
30 LDSTMode
as _LDSTMode
,
35 SVMaskSrc
as _SVMaskSrc
,
42 SVP64SubVL
as _SVP64SubVL
,
43 SVP64Pred
as _SVP64Pred
,
44 SVP64PredMode
as _SVP64PredMode
,
45 SVP64Width
as _SVP64Width
,
47 from openpower
.decoder
.selectable_int
import (
48 SelectableInt
as _SelectableInt
,
49 selectconcat
as _selectconcat
,
51 from openpower
.decoder
.power_fields
import (
54 DecodeFields
as _DecodeFields
,
56 from openpower
.decoder
.pseudo
.pagereader
import ISA
as _ISA
60 @_contextlib.contextmanager
64 @_contextlib.contextmanager
65 def record(self
, record
):
68 @_contextlib.contextmanager
69 def extra(self
, extra
):
73 @_functools.total_ordering
74 class Style(_enum
.Enum
):
78 VERBOSE
= _enum
.auto()
80 def __lt__(self
, other
):
81 if not isinstance(other
, self
.__class
__):
83 return (self
.value
< other
.value
)
86 @_functools.total_ordering
87 class Priority(_enum
.Enum
):
93 def _missing_(cls
, value
):
94 if isinstance(value
, str):
99 return super()._missing
_(value
)
101 def __lt__(self
, other
):
102 if not isinstance(other
, self
.__class
__):
103 return NotImplemented
105 # NOTE: the order is inversed, LOW < NORMAL < HIGH
106 return (self
.value
> other
.value
)
109 def dataclass(cls
, record
, keymap
=None, typemap
=None):
113 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
115 def transform(key_value
):
116 (key
, value
) = key_value
117 key
= keymap
.get(key
, key
)
118 hook
= typemap
.get(key
, lambda value
: value
)
119 if hook
is bool and value
in ("", "0"):
125 record
= dict(map(transform
, record
.items()))
126 for key
in frozenset(record
.keys()):
127 if record
[key
] == "":
133 @_functools.total_ordering
134 @_dataclasses.dataclass(eq
=True, frozen
=True)
137 def __new__(cls
, value
):
138 if isinstance(value
, str):
139 value
= int(value
, 0)
140 if not isinstance(value
, int):
141 raise ValueError(value
)
143 if value
.bit_length() > 64:
144 raise ValueError(value
)
146 return super().__new
__(cls
, value
)
149 return self
.__repr
__()
152 return f
"{self:0{self.bit_length()}b}"
154 def bit_length(self
):
155 if super().bit_length() > 32:
159 class Value(Integer
):
168 def __lt__(self
, other
):
169 if not isinstance(other
, Opcode
):
170 return NotImplemented
171 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
174 return (self
.value
& self
.mask
)
177 return int(self
).__index
__()
180 def pattern(value
, mask
, bit_length
):
181 for bit
in range(bit_length
):
182 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
184 elif (value
& (1 << (bit_length
- bit
- 1))):
189 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
191 def match(self
, key
):
192 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
195 @_functools.total_ordering
196 @_dataclasses.dataclass(eq
=True, frozen
=True)
197 class IntegerOpcode(Opcode
):
198 def __init__(self
, value
):
199 if value
.startswith("0b"):
200 mask
= int(("1" * len(value
[2:])), 2)
204 value
= Opcode
.Value(value
)
205 mask
= Opcode
.Mask(mask
)
207 return super().__init
__(value
=value
, mask
=mask
)
210 @_functools.total_ordering
211 @_dataclasses.dataclass(eq
=True, frozen
=True)
212 class PatternOpcode(Opcode
):
213 def __init__(self
, pattern
):
214 if not isinstance(pattern
, str):
215 raise ValueError(pattern
)
217 (value
, mask
) = (0, 0)
218 for symbol
in pattern
:
219 if symbol
not in {"0", "1", "-"}:
220 raise ValueError(pattern
)
221 value |
= (symbol
== "1")
222 mask |
= (symbol
!= "-")
228 value
= Opcode
.Value(value
)
229 mask
= Opcode
.Mask(mask
)
231 return super().__init
__(value
=value
, mask
=mask
)
234 @_dataclasses.dataclass(eq
=True, frozen
=True)
236 class FlagsMeta(type):
251 class Flags(tuple, metaclass
=FlagsMeta
):
252 def __new__(cls
, flags
=frozenset()):
253 flags
= frozenset(flags
)
254 diff
= (flags
- frozenset(cls
))
256 raise ValueError(flags
)
257 return super().__new
__(cls
, sorted(flags
))
261 flags
: Flags
= Flags()
263 function
: _Function
= _Function
.NONE
264 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
265 in1
: _In1Sel
= _In1Sel
.NONE
266 in2
: _In2Sel
= _In2Sel
.NONE
267 in3
: _In3Sel
= _In3Sel
.NONE
268 out
: _OutSel
= _OutSel
.NONE
269 cr_in
: _CRInSel
= _CRInSel
.NONE
270 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
271 cr_out
: _CROutSel
= _CROutSel
.NONE
272 cry_in
: _CryIn
= _CryIn
.ZERO
273 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
274 upd
: _LDSTMode
= _LDSTMode
.NONE
275 Rc
: _RCOE
= _RCOE
.NONE
276 form
: _Form
= _Form
.NONE
278 unofficial
: bool = False
282 "internal op": "intop",
286 "ldst len": "ldst_len",
288 "CONDITIONS": "conditions",
291 def __lt__(self
, other
):
292 if not isinstance(other
, self
.__class
__):
293 return NotImplemented
294 lhs
= (self
.opcode
, self
.comment
)
295 rhs
= (other
.opcode
, other
.comment
)
299 def CSV(cls
, record
, opcode_cls
):
300 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
301 typemap
["opcode"] = opcode_cls
303 if record
["CR in"] == "BA_BB":
304 record
["cr_in"] = "BA"
305 record
["cr_in2"] = "BB"
309 for flag
in frozenset(PPCRecord
.Flags
):
310 if bool(record
.pop(flag
, "")):
312 record
["flags"] = PPCRecord
.Flags(flags
)
314 return dataclass(cls
, record
,
315 keymap
=PPCRecord
.__KEYMAP
,
320 return frozenset(self
.comment
.split("=")[-1].split("/"))
323 class PPCMultiRecord(tuple):
324 def __getattr__(self
, attr
):
327 raise AttributeError(attr
)
328 return getattr(self
[0], attr
)
331 @_dataclasses.dataclass(eq
=True, frozen
=True)
333 class ExtraMap(tuple):
335 @_dataclasses.dataclass(eq
=True, frozen
=True)
337 seltype
: _SelType
= _SelType
.NONE
338 reg
: _Reg
= _Reg
.NONE
341 return f
"{self.seltype.value}:{self.reg.name}"
343 def __new__(cls
, value
="0"):
344 if isinstance(value
, str):
345 def transform(value
):
346 (seltype
, reg
) = value
.split(":")
347 seltype
= _SelType(seltype
)
349 return cls
.Entry(seltype
=seltype
, reg
=reg
)
354 value
= map(transform
, value
.split(";"))
356 return super().__new
__(cls
, value
)
359 return repr(list(self
))
361 def __new__(cls
, value
=tuple()):
365 return super().__new
__(cls
, map(cls
.Extra
, value
))
368 return repr({index
:self
[index
] for index
in range(0, 4)})
371 ptype
: _SVPType
= _SVPType
.NONE
372 etype
: _SVEType
= _SVEType
.NONE
373 msrc
: _SVMaskSrc
= _SVMaskSrc
.NO
# MASK_SRC is active
374 in1
: _In1Sel
= _In1Sel
.NONE
375 in2
: _In2Sel
= _In2Sel
.NONE
376 in3
: _In3Sel
= _In3Sel
.NONE
377 out
: _OutSel
= _OutSel
.NONE
378 out2
: _OutSel
= _OutSel
.NONE
379 cr_in
: _CRInSel
= _CRInSel
.NONE
380 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
381 cr_out
: _CROutSel
= _CROutSel
.NONE
382 extra
: ExtraMap
= ExtraMap()
384 mode
: _SVMode
= _SVMode
.NORMAL
388 "CONDITIONS": "conditions",
397 def CSV(cls
, record
):
398 record
["insn"] = record
["insn"].split("=")[-1]
400 for key
in frozenset({
401 "in1", "in2", "in3", "CR in",
402 "out", "out2", "CR out",
408 if record
["CR in"] == "BA_BB":
409 record
["cr_in"] = "BA"
410 record
["cr_in2"] = "BB"
414 for idx
in range(0, 4):
415 extra
.append(record
.pop(f
"{idx}"))
417 record
["extra"] = cls
.ExtraMap(extra
)
419 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
424 "in1", "in2", "in3", "cr_in", "cr_in2",
425 "out", "out2", "cr_out",
440 for index
in range(0, 4):
441 for entry
in self
.extra
[index
]:
442 extras
[entry
.seltype
][entry
.reg
] = idxmap
[index
]
444 for (seltype
, regs
) in extras
.items():
445 idx
= regs
.get(reg
, _SVExtra
.NONE
)
446 if idx
is not _SVExtra
.NONE
:
447 yield (reg
, seltype
, idx
)
454 # has the word "in", it is a SelType.SRC "out" -> DST
455 # in1/2/3 and CR in are SRC, and must match only against "s:NN"
456 # out/out1 and CR out are DST, and must match only against "d:NN"
457 keytype
= _SelType
.SRC
if ("in" in key
) else _SelType
.DST
458 sel
= sels
[key
] = getattr(self
, key
)
459 reg
= regs
[key
] = _Reg(sel
)
460 seltypes
[key
] = _SelType
.NONE
461 idxs
[key
] = _SVExtra
.NONE
462 for (reg
, seltype
, idx
) in extra(reg
.alias
):
463 if keytype
!= seltype
: # only check SRC-to-SRC and DST-to-DST
465 if idx
!= idxs
[key
] and idxs
[key
] is not _SVExtra
.NONE
:
466 raise ValueError(idx
)
469 seltypes
[key
] = seltype
471 if sels
["cr_in"] is _CRInSel
.BA_BB
:
472 sels
["cr_in"] = _CRIn2Sel
.BA
473 sels
["cr_in2"] = _CRIn2Sel
.BB
474 idxs
["cr_in2"] = idxs
["cr_in"]
475 for key
in ("cr_in", "cr_in2"):
476 regs
[key
] = _Reg(sels
[key
])
477 seltype
[key
] = _SelType
.SRC
484 "seltype": seltypes
[key
],
488 return _types
.MappingProxyType(records
)
490 extra_idx_in1
= property(lambda self
: self
.extras
["in1"]["idx"])
491 extra_idx_in2
= property(lambda self
: self
.extras
["in2"]["idx"])
492 extra_idx_in3
= property(lambda self
: self
.extras
["in3"]["idx"])
493 extra_idx_out
= property(lambda self
: self
.extras
["out"]["idx"])
494 extra_idx_out2
= property(lambda self
: self
.extras
["out2"]["idx"])
495 extra_idx_cr_in
= property(lambda self
: self
.extras
["cr_in"]["idx"])
496 extra_idx_cr_in2
= property(lambda self
: self
.extras
["cr_in2"]["idx"])
497 extra_idx_cr_out
= property(lambda self
: self
.extras
["cr_out"]["idx"])
502 for idx
in range(0, 4):
503 for entry
in self
.extra
[idx
]:
504 if entry
.seltype
is _SelType
.DST
:
505 if extra
is not None:
506 raise ValueError(self
.svp64
)
510 if _RegType(extra
.reg
) not in (_RegType
.CR_3BIT
, _RegType
.CR_5BIT
):
511 raise ValueError(self
.svp64
)
516 def extra_CR_3bit(self
):
517 return (_RegType(self
.extra_CR
.reg
) is _RegType
.CR_3BIT
)
521 def __init__(self
, value
=(0, 32)):
522 if isinstance(value
, str):
523 (start
, end
) = map(int, value
.split(":"))
526 if start
< 0 or end
< 0 or start
>= end
:
527 raise ValueError(value
)
532 return super().__init
__()
535 return (self
.__end
- self
.__start
+ 1)
538 return f
"[{self.__start}:{self.__end}]"
541 yield from range(self
.start
, (self
.end
+ 1))
543 def __reversed__(self
):
544 return tuple(reversed(tuple(self
)))
555 @_dataclasses.dataclass(eq
=True, frozen
=True)
557 class Mode(_enum
.Enum
):
558 INTEGER
= _enum
.auto()
559 PATTERN
= _enum
.auto()
562 def _missing_(cls
, value
):
563 if isinstance(value
, str):
564 return cls
[value
.upper()]
565 return super()._missing
_(value
)
568 def __new__(cls
, value
=None):
569 if isinstance(value
, str):
570 if value
.upper() == "NONE":
573 value
= int(value
, 0)
577 return super().__new
__(cls
, value
)
583 return (bin(self
) if self
else "None")
589 opcode
: IntegerOpcode
= None
590 priority
: Priority
= Priority
.NORMAL
592 def __lt__(self
, other
):
593 if not isinstance(other
, self
.__class
__):
594 return NotImplemented
595 return (self
.priority
< other
.priority
)
598 def CSV(cls
, record
):
599 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
600 if record
["opcode"] == "NONE":
601 typemap
["opcode"] = lambda _
: None
603 return dataclass(cls
, record
, typemap
=typemap
)
607 def __init__(self
, items
):
608 if isinstance(items
, dict):
609 items
= items
.items()
612 (name
, bitrange
) = item
613 return (name
, tuple(bitrange
.values()))
615 self
.__mapping
= dict(map(transform
, items
))
617 return super().__init
__()
620 return repr(self
.__mapping
)
623 yield from self
.__mapping
.items()
625 def __contains__(self
, key
):
626 return self
.__mapping
.__contains
__(key
)
628 def __getitem__(self
, key
):
629 return self
.__mapping
.get(key
, None)
644 def __init__(self
, insn
, operands
):
646 "b": {"target_addr": TargetAddrOperandLI
},
647 "ba": {"target_addr": TargetAddrOperandLI
},
648 "bl": {"target_addr": TargetAddrOperandLI
},
649 "bla": {"target_addr": TargetAddrOperandLI
},
650 "bc": {"target_addr": TargetAddrOperandBD
},
651 "bca": {"target_addr": TargetAddrOperandBD
},
652 "bcl": {"target_addr": TargetAddrOperandBD
},
653 "bcla": {"target_addr": TargetAddrOperandBD
},
654 "addpcis": {"D": DOperandDX
},
655 "fishmv": {"D": DOperandDX
},
656 "fmvis": {"D": DOperandDX
},
659 "SVi": NonZeroOperand
,
660 "SVd": NonZeroOperand
,
661 "SVxd": NonZeroOperand
,
662 "SVyd": NonZeroOperand
,
663 "SVzd": NonZeroOperand
,
665 "D": SignedImmediateOperand
,
669 "SIM": SignedOperand
,
670 "SVD": SignedOperand
,
671 "SVDS": SignedOperand
,
672 "RSp": GPRPairOperand
,
673 "RTp": GPRPairOperand
,
674 "FRAp": FPRPairOperand
,
675 "FRBp": FPRPairOperand
,
676 "FRSp": FPRPairOperand
,
677 "FRTp": FPRPairOperand
,
679 custom_immediates
= {
685 for operand
in operands
:
689 (name
, value
) = operand
.split("=")
690 mapping
[name
] = (StaticOperand
, {
696 if name
.endswith(")"):
697 name
= name
.replace("(", " ").replace(")", "")
698 (imm_name
, _
, name
) = name
.partition(" ")
702 if imm_name
is not None:
703 imm_cls
= custom_immediates
.get(imm_name
, ImmediateOperand
)
705 if insn
in custom_insns
and name
in custom_insns
[insn
]:
706 cls
= custom_insns
[insn
][name
]
707 elif name
in custom_fields
:
708 cls
= custom_fields
[name
]
709 elif name
in _Reg
.__members
__:
711 if reg
in self
.__class
__.__GPR
_PAIRS
:
713 elif reg
in self
.__class
__.__FPR
_PAIRS
:
716 regtype
= _RegType
[name
]
717 if regtype
is _RegType
.GPR
:
719 elif regtype
is _RegType
.FPR
:
721 elif regtype
is _RegType
.CR_3BIT
:
723 elif regtype
is _RegType
.CR_5BIT
:
726 if imm_name
is not None:
727 mapping
[imm_name
] = (imm_cls
, {"name": imm_name
})
728 mapping
[name
] = (cls
, {"name": name
})
732 for (name
, (cls
, kwargs
)) in mapping
.items():
733 kwargs
= dict(kwargs
)
734 kwargs
["name"] = name
735 if issubclass(cls
, StaticOperand
):
736 static
.append((cls
, kwargs
))
737 elif issubclass(cls
, DynamicOperand
):
738 dynamic
.append((cls
, kwargs
))
740 raise ValueError(name
)
742 self
.__mapping
= mapping
743 self
.__static
= tuple(static
)
744 self
.__dynamic
= tuple(dynamic
)
746 return super().__init
__()
749 for (_
, items
) in self
.__mapping
.items():
750 (cls
, kwargs
) = items
754 return self
.__mapping
.__repr
__()
756 def __contains__(self
, key
):
757 return self
.__mapping
.__contains
__(key
)
759 def __getitem__(self
, key
):
760 return self
.__mapping
.__getitem
__(key
)
768 return self
.__dynamic
771 class Arguments(tuple):
772 def __new__(cls
, record
, arguments
, operands
):
773 operands
= iter(tuple(operands
))
774 arguments
= iter(tuple(arguments
))
779 operand
= next(operands
)
780 except StopIteration:
784 argument
= next(arguments
)
785 except StopIteration:
786 raise ValueError("operands count mismatch")
788 if isinstance(operand
, ImmediateOperand
):
789 argument
= argument
.replace("(", " ").replace(")", "")
790 (imm_argument
, _
, argument
) = argument
.partition(" ")
792 (imm_operand
, operand
) = (operand
, next(operands
))
793 except StopIteration:
794 raise ValueError("operands count mismatch")
795 items
.append((imm_argument
, imm_operand
))
796 items
.append((argument
, operand
))
800 except StopIteration:
803 raise ValueError("operands count mismatch")
805 return super().__new
__(cls
, items
)
809 def __init__(self
, iterable
):
810 self
.__pcode
= tuple(iterable
)
811 return super().__init
__()
814 yield from self
.__pcode
817 return self
.__pcode
.__repr
__()
820 @_dataclasses.dataclass(eq
=True, frozen
=True)
821 class MarkdownRecord
:
826 @_dataclasses.dataclass(eq
=True, frozen
=True)
830 _In1Sel
, _In2Sel
, _In3Sel
, _CRInSel
, _CRIn2Sel
,
837 def visit(self
, visitor
):
838 with visitor
.extra(extra
=self
) as extra
:
843 @_functools.total_ordering
844 @_dataclasses.dataclass(eq
=True, frozen
=True)
851 svp64
: SVP64Record
= None
853 def visit(self
, visitor
):
854 with visitor
.record(record
=self
) as record
:
855 for (name
, fields
) in record
.extras
.items():
856 extra
= Extra(name
=name
, **fields
)
857 extra
.visit(visitor
=visitor
)
861 if self
.svp64
is not None:
862 return self
.svp64
.extras
864 return _types
.MappingProxyType({})
868 return self
.mdwn
.pcode
870 def __lt__(self
, other
):
871 if not isinstance(other
, Record
):
872 return NotImplemented
873 lhs
= (min(self
.opcodes
), self
.name
)
874 rhs
= (min(other
.opcodes
), other
.name
)
879 return (self
.static_operands
+ self
.dynamic_operands
)
882 def static_operands(self
):
884 operands
.append(POStaticOperand(record
=self
, value
=self
.PO
))
886 operands
.append(XOStaticOperand(
888 value
=ppc
.opcode
.value
,
889 span
=self
.section
.bitsel
,
891 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
892 operands
.append(cls(record
=self
, **kwargs
))
893 return tuple(operands
)
896 def dynamic_operands(self
):
898 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
899 operands
.append(cls(record
=self
, **kwargs
))
900 return tuple(operands
)
905 return int("".join(str(int(mapping
[bit
])) \
906 for bit
in sorted(mapping
)), 2)
908 def PO_XO(value
, mask
, opcode
, bits
):
911 for (src
, dst
) in enumerate(reversed(bits
)):
912 value
[dst
] = ((opcode
.value
& (1 << src
)) != 0)
913 mask
[dst
] = ((opcode
.mask
& (1 << src
)) != 0)
916 def PO(value
, mask
, opcode
, bits
):
917 return PO_XO(value
=value
, mask
=mask
, opcode
=opcode
, bits
=bits
)
919 def XO(value
, mask
, opcode
, bits
):
920 (value
, mask
) = PO_XO(value
=value
, mask
=mask
,
921 opcode
=opcode
, bits
=bits
)
922 for (op_cls
, op_kwargs
) in self
.mdwn
.operands
.static
:
923 operand
= op_cls(record
=self
, **op_kwargs
)
924 for (src
, dst
) in enumerate(reversed(operand
.span
)):
925 value
[dst
] = ((operand
.value
& (1 << src
)) != 0)
930 value
= {bit
:False for bit
in range(32)}
931 mask
= {bit
:False for bit
in range(32)}
932 if self
.section
.opcode
is not None:
933 (value
, mask
) = PO(value
=value
, mask
=mask
,
934 opcode
=self
.section
.opcode
, bits
=range(0, 6))
936 pairs
.append(XO(value
=value
, mask
=mask
,
937 opcode
=ppc
.opcode
, bits
=self
.section
.bitsel
))
940 for (value
, mask
) in pairs
:
941 value
= Opcode
.Value(binary(value
))
942 mask
= Opcode
.Mask(binary(mask
))
943 result
.append(Opcode(value
=value
, mask
=mask
))
949 opcode
= self
.section
.opcode
951 opcode
= self
.ppc
[0].opcode
952 if isinstance(opcode
, PatternOpcode
):
953 value
= int(opcode
.value
)
954 bits
= opcode
.value
.bit_length()
955 return int(_SelectableInt(value
=value
, bits
=bits
)[0:6])
957 return int(opcode
.value
)
961 return tuple(ppc
.opcode
for ppc
in self
.ppc
)
963 def match(self
, key
):
964 for opcode
in self
.opcodes
:
965 if opcode
.match(key
):
972 return self
.svp64
.mode
992 if self
.svp64
is None:
998 return self
.ppc
.cr_in
1002 return self
.ppc
.cr_in2
1006 return self
.ppc
.cr_out
1008 ptype
= property(lambda self
: self
.svp64
.ptype
)
1009 etype
= property(lambda self
: self
.svp64
.etype
)
1011 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
1012 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
1013 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
1014 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
1015 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
1016 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
1017 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
1018 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
1020 def __contains__(self
, key
):
1021 return self
.mdwn
.operands
.__contains
__(key
)
1023 def __getitem__(self
, key
):
1024 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
1025 return cls(record
=self
, **kwargs
)
1029 if "Rc" not in self
:
1031 return self
["Rc"].value
1035 def __init__(self
, record
, name
):
1036 self
.__record
= record
1040 yield ("record", self
.record
)
1041 yield ("name", self
.__name
)
1044 return f
"{self.__class__.__name__}({self.name})"
1052 return self
.__record
1056 return self
.record
.fields
[self
.name
]
1058 def assemble(self
, insn
):
1059 raise NotImplementedError()
1061 def disassemble(self
, insn
,
1062 style
=Style
.NORMAL
, indent
=""):
1063 raise NotImplementedError()
1066 class DynamicOperand(Operand
):
1067 def assemble(self
, insn
, value
):
1069 if isinstance(value
, str):
1070 value
= int(value
, 0)
1072 raise ValueError("signed operands not allowed")
1075 def disassemble(self
, insn
,
1076 style
=Style
.NORMAL
, indent
=""):
1080 if style
>= Style
.VERBOSE
:
1081 span
= map(str, span
)
1082 yield f
"{indent}{self.name}"
1083 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1084 yield f
"{indent}{indent}{', '.join(span)}"
1086 yield str(int(value
))
1089 class SignedOperand(DynamicOperand
):
1090 def assemble(self
, insn
, value
):
1091 if isinstance(value
, str):
1092 value
= int(value
, 0)
1093 return super().assemble(value
=value
, insn
=insn
)
1095 def assemble(self
, insn
, value
):
1097 if isinstance(value
, str):
1098 value
= int(value
, 0)
1101 def disassemble(self
, insn
,
1102 style
=Style
.NORMAL
, indent
=""):
1104 value
= insn
[span
].to_signed_int()
1105 sign
= "-" if (value
< 0) else ""
1108 if style
>= Style
.VERBOSE
:
1109 span
= map(str, span
)
1110 yield f
"{indent}{self.name}"
1111 yield f
"{indent}{indent}{sign}{value}"
1112 yield f
"{indent}{indent}{', '.join(span)}"
1114 yield f
"{sign}{value}"
1117 class StaticOperand(Operand
):
1118 def __init__(self
, record
, name
, value
):
1119 self
.__value
= value
1120 return super().__init
__(record
=record
, name
=name
)
1123 yield ("value", self
.__value
)
1124 yield from super().__iter
__()
1127 return f
"{self.__class__.__name__}({self.name}, value={self.value})"
1133 def assemble(self
, insn
):
1134 insn
[self
.span
] = self
.value
1136 def disassemble(self
, insn
,
1137 style
=Style
.NORMAL
, indent
=""):
1141 if style
>= Style
.VERBOSE
:
1142 span
= map(str, span
)
1143 yield f
"{indent}{self.name}"
1144 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1145 yield f
"{indent}{indent}{', '.join(span)}"
1147 yield str(int(value
))
1150 class SpanStaticOperand(StaticOperand
):
1151 def __init__(self
, record
, name
, value
, span
):
1152 self
.__span
= tuple(span
)
1153 return super().__init
__(record
=record
, name
=name
, value
=value
)
1156 yield ("span", self
.__span
)
1157 yield from super().__iter
__()
1164 class POStaticOperand(SpanStaticOperand
):
1165 def __init__(self
, record
, value
):
1166 return super().__init
__(record
=record
, name
="PO",
1167 value
=value
, span
=range(0, 6))
1170 for (key
, value
) in super().__iter
__():
1171 if key
not in {"name", "span"}:
1175 class XOStaticOperand(SpanStaticOperand
):
1176 def __init__(self
, record
, value
, span
):
1177 bits
= record
.section
.bitsel
1178 value
= _SelectableInt(value
=value
, bits
=len(bits
))
1179 span
= dict(zip(bits
, range(len(bits
))))
1180 span_rev
= {value
:key
for (key
, value
) in span
.items()}
1182 # This part is tricky: we cannot use record.operands,
1183 # as this code is called by record.static_operands method.
1184 for (cls
, kwargs
) in record
.mdwn
.operands
:
1185 operand
= cls(record
=record
, **kwargs
)
1186 for idx
in operand
.span
:
1187 rev
= span
.pop(idx
, None)
1189 span_rev
.pop(rev
, None)
1191 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1192 span
= tuple(span
.keys())
1194 return super().__init
__(record
=record
, name
="XO",
1195 value
=value
, span
=span
)
1198 for (key
, value
) in super().__iter
__():
1199 if key
not in {"name"}:
1203 class ImmediateOperand(DynamicOperand
):
1207 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1211 class NonZeroOperand(DynamicOperand
):
1212 def assemble(self
, insn
, value
):
1213 if isinstance(value
, str):
1214 value
= int(value
, 0)
1215 if not isinstance(value
, int):
1216 raise ValueError("non-integer operand")
1218 raise ValueError("non-zero operand")
1220 return super().assemble(value
=value
, insn
=insn
)
1222 def disassemble(self
, insn
,
1223 style
=Style
.NORMAL
, indent
=""):
1227 if style
>= Style
.VERBOSE
:
1228 span
= map(str, span
)
1229 yield f
"{indent}{self.name}"
1230 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1231 yield f
"{indent}{indent}{', '.join(span)}"
1233 yield str(int(value
) + 1)
1236 class ExtendableOperand(DynamicOperand
):
1237 def sv_spec_enter(self
, value
, span
):
1238 return (value
, span
)
1240 def sv_spec(self
, insn
):
1244 span
= tuple(map(str, span
))
1246 if isinstance(insn
, SVP64Instruction
):
1247 (origin_value
, origin_span
) = (value
, span
)
1248 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1250 for extra_idx
in self
.extra_idx
:
1251 if self
.record
.etype
is _SVEType
.EXTRA3
:
1252 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1253 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1254 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1256 raise ValueError(self
.record
.etype
)
1259 vector
= bool(spec
[0])
1260 spec_span
= spec
.__class
__
1261 if self
.record
.etype
is _SVEType
.EXTRA3
:
1262 spec_span
= tuple(map(str, spec_span
[1, 2]))
1264 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1265 spec_span
= tuple(map(str, spec_span
[1,]))
1266 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1269 spec_span
= (spec_span
+ ("{0}",))
1271 spec_span
= (("{0}",) + spec_span
)
1273 raise ValueError(self
.record
.etype
)
1275 vector_shift
= (2 + (5 - value
.bits
))
1276 scalar_shift
= value
.bits
1277 spec_shift
= (5 - value
.bits
)
1279 bits
= (len(span
) + len(spec_span
))
1280 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1281 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1283 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1284 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1286 value
= ((spec
<< scalar_shift
) | value
)
1287 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1289 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1290 origin_value
=origin_value
, origin_span
=origin_span
)
1292 return (vector
, value
, span
)
1294 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1295 return (value
, span
)
1298 def extra_idx(self
):
1299 for (key
, record
) in self
.record
.svp64
.extras
.items():
1300 if record
["reg"].alias
is self
.extra_reg
.alias
:
1304 def extra_reg(self
):
1305 return _Reg(self
.name
)
1307 def remap(self
, value
, vector
):
1308 raise NotImplementedError()
1310 def assemble(self
, value
, insn
, prefix
):
1313 if isinstance(value
, str):
1314 value
= value
.lower()
1315 if value
.startswith("%"):
1317 if value
.startswith("*"):
1318 if not isinstance(insn
, SVP64Instruction
):
1319 raise ValueError(value
)
1322 if value
.startswith(prefix
):
1323 if (self
.extra_reg
.or_zero
and (value
== f
"{prefix}0")):
1324 raise ValueError(value
)
1325 value
= value
[len(prefix
):]
1326 value
= int(value
, 0)
1328 if isinstance(insn
, SVP64Instruction
):
1329 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1331 for extra_idx
in self
.extra_idx
:
1332 if self
.record
.etype
is _SVEType
.EXTRA3
:
1333 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1334 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1335 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1337 raise ValueError(self
.record
.etype
)
1339 return super().assemble(value
=value
, insn
=insn
)
1341 def disassemble(self
, insn
,
1342 style
=Style
.NORMAL
, prefix
="", indent
=""):
1343 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1345 if (self
.extra_reg
.or_zero
and (value
== 0)):
1348 if style
>= Style
.VERBOSE
:
1349 mode
= "vector" if vector
else "scalar"
1350 yield f
"{indent}{self.name} ({mode})"
1351 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1352 yield f
"{indent}{indent}{', '.join(span)}"
1353 if isinstance(insn
, SVP64Instruction
):
1354 for extra_idx
in frozenset(self
.extra_idx
):
1355 if self
.record
.etype
is _SVEType
.NONE
:
1356 yield f
"{indent}{indent}extra[none]"
1358 etype
= repr(self
.record
.etype
).lower()
1359 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1361 vector
= "*" if vector
else ""
1362 yield f
"{vector}{prefix}{int(value)}"
1365 class SimpleRegisterOperand(ExtendableOperand
):
1366 def remap(self
, value
, vector
):
1368 extra
= (value
& 0b11)
1369 value
= (value
>> 2)
1371 extra
= (value
>> 5)
1372 value
= (value
& 0b11111)
1374 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1375 # (and shrink to a single bit if ok)
1376 if self
.record
.etype
is _SVEType
.EXTRA2
:
1378 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1379 assert (extra
& 0b01) == 0, \
1380 ("vector field %s cannot fit into EXTRA2" % value
)
1381 extra
= (0b10 |
(extra
>> 1))
1383 # range is r0-r63 in increments of 1
1384 assert (extra
>> 1) == 0, \
1385 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1387 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1389 # EXTRA3 vector bit needs marking
1392 raise ValueError(self
.record
.etype
)
1394 return (value
, extra
)
1397 class GPROperand(SimpleRegisterOperand
):
1398 def assemble(self
, insn
, value
):
1399 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1401 def disassemble(self
, insn
,
1402 style
=Style
.NORMAL
, indent
=""):
1403 prefix
= "" if (style
<= Style
.SHORT
) else "r"
1404 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1405 style
=style
, indent
=indent
)
1408 class GPRPairOperand(GPROperand
):
1412 class FPROperand(SimpleRegisterOperand
):
1413 def assemble(self
, insn
, value
):
1414 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1416 def disassemble(self
, insn
,
1417 style
=Style
.NORMAL
, indent
=""):
1418 prefix
= "" if (style
<= Style
.SHORT
) else "f"
1419 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1420 style
=style
, indent
=indent
)
1423 class FPRPairOperand(FPROperand
):
1427 class ConditionRegisterFieldOperand(ExtendableOperand
):
1428 def pattern(name_pattern
):
1429 (name
, pattern
) = name_pattern
1430 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1439 CR
= r
"(?:CR|cr)([0-9]+)"
1441 BIT
= rf
"({'|'.join(CONDS.keys())})"
1442 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1443 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1444 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1445 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1446 XCR
= fr
"{CR}\.{BIT}"
1447 PATTERNS
= tuple(map(pattern
, (
1452 ("BIT+CR", (LBIT
+ CR
)),
1453 ("CR+BIT", (CR
+ RBIT
)),
1454 ("BIT+CR*N", (LBIT
+ CRN
)),
1455 ("CR*N+BIT", (CRN
+ RBIT
)),
1456 ("BIT+N*CR", (LBIT
+ NCR
)),
1457 ("N*CR+BIT", (NCR
+ RBIT
)),
1460 def remap(self
, value
, vector
, regtype
):
1461 if regtype
is _RegType
.CR_5BIT
:
1462 subvalue
= (value
& 0b11)
1466 extra
= (value
& 0b1111)
1469 extra
= (value
>> 3)
1472 if self
.record
.etype
is _SVEType
.EXTRA2
:
1474 assert (extra
& 0b111) == 0, \
1475 "vector CR cannot fit into EXTRA2"
1476 extra
= (0b10 |
(extra
>> 3))
1478 assert (extra
>> 1) == 0, \
1479 "scalar CR cannot fit into EXTRA2"
1481 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1483 assert (extra
& 0b11) == 0, \
1484 "vector CR cannot fit into EXTRA3"
1485 extra
= (0b100 |
(extra
>> 2))
1487 assert (extra
>> 2) == 0, \
1488 "scalar CR cannot fit into EXTRA3"
1491 if regtype
is _RegType
.CR_5BIT
:
1492 value
= ((value
<< 2) | subvalue
)
1494 return (value
, extra
)
1496 def assemble(self
, insn
, value
):
1497 if isinstance(value
, str):
1500 if value
.startswith("*"):
1501 if not isinstance(insn
, SVP64Instruction
):
1502 raise ValueError(value
)
1506 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1507 match
= pattern
.match(value
)
1508 if match
is not None:
1509 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1510 values
= match
.groups()
1511 match
= dict(zip(keys
, values
))
1512 CR
= int(match
["CR"])
1516 N
= int(match
.get("N", "1"))
1517 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1518 value
= ((CR
* N
) + BIT
)
1525 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1527 def disassemble(self
, insn
,
1528 style
=Style
.NORMAL
, prefix
="", indent
=""):
1529 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1531 if style
>= Style
.VERBOSE
:
1532 mode
= "vector" if vector
else "scalar"
1533 yield f
"{indent}{self.name} ({mode})"
1534 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1535 yield f
"{indent}{indent}{', '.join(span)}"
1536 if isinstance(insn
, SVP64Instruction
):
1537 for extra_idx
in frozenset(self
.extra_idx
):
1538 if self
.record
.etype
is _SVEType
.NONE
:
1539 yield f
"{indent}{indent}extra[none]"
1541 etype
= repr(self
.record
.etype
).lower()
1542 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1544 vector
= "*" if vector
else ""
1545 CR
= int(value
>> 2)
1547 cond
= ("lt", "gt", "eq", "so")[CC
]
1548 if style
>= Style
.NORMAL
:
1550 if isinstance(insn
, SVP64Instruction
):
1551 yield f
"{vector}cr{CR}.{cond}"
1553 yield f
"4*cr{CR}+{cond}"
1557 yield f
"{vector}{prefix}{int(value)}"
1560 class CR3Operand(ConditionRegisterFieldOperand
):
1561 def remap(self
, value
, vector
):
1562 return super().remap(value
=value
, vector
=vector
,
1563 regtype
=_RegType
.CR_3BIT
)
1566 class CR5Operand(ConditionRegisterFieldOperand
):
1567 def remap(self
, value
, vector
):
1568 return super().remap(value
=value
, vector
=vector
,
1569 regtype
=_RegType
.CR_5BIT
)
1571 def sv_spec_enter(self
, value
, span
):
1572 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1573 return (value
, span
)
1575 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1576 value
= _selectconcat(value
, origin_value
[3:5])
1578 return (value
, span
)
1581 class EXTSOperand(SignedOperand
):
1582 field
: str # real name to report
1583 nz
: int = 0 # number of zeros
1584 fmt
: str = "d" # integer formatter
1586 def __init__(self
, record
, name
, field
, nz
=0, fmt
="d"):
1587 self
.__field
= field
1590 return super().__init
__(record
=record
, name
=name
)
1606 return self
.record
.fields
[self
.field
]
1608 def assemble(self
, insn
, value
):
1610 if isinstance(value
, str):
1611 value
= int(value
, 0)
1612 insn
[span
] = (value
>> self
.nz
)
1614 def disassemble(self
, insn
,
1615 style
=Style
.NORMAL
, indent
=""):
1617 value
= insn
[span
].to_signed_int()
1618 sign
= "-" if (value
< 0) else ""
1619 value
= (abs(value
) << self
.nz
)
1621 if style
>= Style
.VERBOSE
:
1622 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1623 zeros
= ("0" * self
.nz
)
1624 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1625 yield f
"{indent * 1}{hint}"
1626 yield f
"{indent * 2}{self.field}"
1627 yield f
"{indent * 3}{sign}{value:{self.fmt}}"
1628 yield f
"{indent * 3}{', '.join(span)}"
1630 yield f
"{sign}{value:{self.fmt}}"
1633 class TargetAddrOperand(EXTSOperand
):
1634 def __init__(self
, record
, name
, field
):
1635 return super().__init
__(record
=record
, name
=name
, field
=field
,
1639 class TargetAddrOperandLI(TargetAddrOperand
):
1640 def __init__(self
, record
, name
):
1641 return super().__init
__(record
=record
, name
=name
, field
="LI")
1644 class TargetAddrOperandBD(TargetAddrOperand
):
1645 def __init__(self
, record
, name
):
1646 return super().__init
__(record
=record
, name
=name
, field
="BD")
1649 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1650 def __init__(self
, record
, name
):
1651 return super().__init
__(record
=record
, name
=name
, field
="DS", nz
=2)
1654 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1655 def __init__(self
, record
, name
):
1656 return super().__init
__(record
=record
, name
=name
, field
="DQ", nz
=4)
1659 class DOperandDX(SignedOperand
):
1662 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1663 operands
= map(cls
, ("d0", "d1", "d2"))
1664 spans
= map(lambda operand
: operand
.span
, operands
)
1665 return sum(spans
, tuple())
1667 def disassemble(self
, insn
,
1668 style
=Style
.NORMAL
, indent
=""):
1670 value
= insn
[span
].to_signed_int()
1671 sign
= "-" if (value
< 0) else ""
1674 if style
>= Style
.VERBOSE
:
1681 for (subname
, subspan
) in mapping
.items():
1682 operand
= DynamicOperand(name
=subname
)
1684 span
= map(str, span
)
1685 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1686 yield f
"{indent}{indent}{indent}{sign}{value}"
1687 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1689 yield f
"{sign}{value}"
1692 class Instruction(_Mapping
):
1694 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1695 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1696 raise ValueError(bits
)
1698 if isinstance(value
, bytes
):
1699 if ((len(value
) * 8) != bits
):
1700 raise ValueError(f
"bit length mismatch")
1701 value
= int.from_bytes(value
, byteorder
=byteorder
)
1703 if isinstance(value
, int):
1704 value
= _SelectableInt(value
=value
, bits
=bits
)
1705 elif isinstance(value
, Instruction
):
1706 value
= value
.storage
1708 if not isinstance(value
, _SelectableInt
):
1709 raise ValueError(value
)
1712 if len(value
) != bits
:
1713 raise ValueError(value
)
1715 value
= _SelectableInt(value
=value
, bits
=bits
)
1717 return cls(storage
=value
)
1720 return hash(int(self
))
1722 def __getitem__(self
, key
):
1723 return self
.storage
.__getitem
__(key
)
1725 def __setitem__(self
, key
, value
):
1726 return self
.storage
.__setitem
__(key
, value
)
1728 def bytes(self
, byteorder
="little"):
1729 nr_bytes
= (len(self
.__class
__) // 8)
1730 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1733 def record(cls
, db
, entry
):
1736 raise KeyError(entry
)
1740 def operands(cls
, record
):
1741 yield from record
.operands
1744 def static_operands(cls
, record
):
1745 return filter(lambda operand
: isinstance(operand
, StaticOperand
),
1746 cls
.operands(record
=record
))
1749 def dynamic_operands(cls
, record
):
1750 return filter(lambda operand
: isinstance(operand
, DynamicOperand
),
1751 cls
.operands(record
=record
))
1753 def spec(self
, record
, prefix
):
1754 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1755 self
.spec_dynamic_operands(record
=record
)))
1757 static_operands
= []
1758 for (name
, value
) in self
.spec_static_operands(record
=record
):
1759 static_operands
.append(f
"{name}={value}")
1762 if dynamic_operands
:
1764 operands
+= ",".join(dynamic_operands
)
1767 operands
+= " ".join(static_operands
)
1769 return f
"{prefix}{record.name}{operands}"
1771 def spec_static_operands(self
, record
):
1772 for operand
in self
.static_operands(record
=record
):
1773 if not isinstance(operand
, (POStaticOperand
, XOStaticOperand
)):
1774 yield (operand
.name
, operand
.value
)
1776 def spec_dynamic_operands(self
, record
, style
=Style
.NORMAL
):
1780 for operand
in self
.dynamic_operands(record
=record
):
1782 value
= " ".join(operand
.disassemble(insn
=self
,
1783 style
=min(style
, Style
.NORMAL
)))
1785 name
= f
"{imm_name}({name})"
1786 value
= f
"{imm_value}({value})"
1788 if isinstance(operand
, ImmediateOperand
):
1796 def assemble(cls
, record
, arguments
=None):
1797 if arguments
is None:
1800 insn
= cls
.integer(value
=0)
1802 for operand
in cls
.static_operands(record
=record
):
1803 operand
.assemble(insn
=insn
)
1805 arguments
= Arguments(record
=record
,
1806 arguments
=arguments
, operands
=cls
.dynamic_operands(record
=record
))
1807 for (value
, operand
) in arguments
:
1808 operand
.assemble(insn
=insn
, value
=value
)
1812 def disassemble(self
, record
,
1814 style
=Style
.NORMAL
):
1815 raise NotImplementedError()
1818 class WordInstruction(Instruction
):
1819 _
: _Field
= range(0, 32)
1820 PO
: _Field
= range(0, 6)
1823 def integer(cls
, value
, byteorder
="little"):
1824 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1829 for idx
in range(32):
1830 bit
= int(self
[idx
])
1832 return "".join(map(str, bits
))
1834 def disassemble(self
, record
,
1836 style
=Style
.NORMAL
):
1837 if style
<= Style
.SHORT
:
1840 blob
= self
.bytes(byteorder
=byteorder
)
1841 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1845 yield f
"{blob}.long 0x{int(self):08x}"
1848 # awful temporary hack: workaround for ld-update
1849 # https://bugs.libre-soc.org/show_bug.cgi?id=1056#c2
1850 # XXX TODO must check that *EXTENDED* RA != extended-RT
1851 if (record
.svp64
is not None and
1852 record
.mode
== _SVMode
.LDST_IMM
and
1853 'u' in record
.name
):
1854 yield f
"{blob}.long 0x{int(self):08x}"
1858 if style
is Style
.LEGACY
:
1860 for operand
in self
.dynamic_operands(record
=record
):
1861 if isinstance(operand
, (GPRPairOperand
, FPRPairOperand
)):
1864 if style
is Style
.LEGACY
and (paired
or record
.ppc
.unofficial
):
1865 yield f
"{blob}.long 0x{int(self):08x}"
1867 operands
= tuple(map(_operator
.itemgetter(1),
1868 self
.spec_dynamic_operands(record
=record
, style
=style
)))
1870 operands
= ",".join(operands
)
1871 yield f
"{blob}{record.name} {operands}"
1873 yield f
"{blob}{record.name}"
1875 if style
>= Style
.VERBOSE
:
1877 binary
= self
.binary
1878 spec
= self
.spec(record
=record
, prefix
="")
1879 yield f
"{indent}spec"
1880 yield f
"{indent}{indent}{spec}"
1881 yield f
"{indent}pcode"
1882 for stmt
in record
.mdwn
.pcode
:
1883 yield f
"{indent}{indent}{stmt}"
1884 yield f
"{indent}binary"
1885 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1886 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1887 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1888 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1889 yield f
"{indent}opcodes"
1890 for opcode
in record
.opcodes
:
1891 yield f
"{indent}{indent}{opcode!r}"
1892 for operand
in self
.operands(record
=record
):
1893 yield from operand
.disassemble(insn
=self
,
1894 style
=style
, indent
=indent
)
1898 class PrefixedInstruction(Instruction
):
1899 class Prefix(WordInstruction
.remap(range(0, 32))):
1902 class Suffix(WordInstruction
.remap(range(32, 64))):
1905 _
: _Field
= range(64)
1911 def integer(cls
, value
, byteorder
="little"):
1912 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
1915 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
1916 def transform(value
):
1917 return WordInstruction
.integer(value
=value
,
1918 byteorder
=byteorder
)[0:32]
1920 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
1921 value
= _selectconcat(prefix
, suffix
)
1923 return super().integer(bits
=64, value
=value
)
1926 class Mode(_Mapping
):
1927 _
: _Field
= range(0, 5)
1928 sel
: _Field
= (0, 1)
1931 class ExtraRM(_Mapping
):
1932 _
: _Field
= range(0, 9)
1935 class Extra2RM(ExtraRM
):
1936 idx0
: _Field
= range(0, 2)
1937 idx1
: _Field
= range(2, 4)
1938 idx2
: _Field
= range(4, 6)
1939 idx3
: _Field
= range(6, 8)
1941 def __getitem__(self
, key
):
1947 _SVExtra
.Idx0
: self
.idx0
,
1948 _SVExtra
.Idx1
: self
.idx1
,
1949 _SVExtra
.Idx2
: self
.idx2
,
1950 _SVExtra
.Idx3
: self
.idx3
,
1953 def __setitem__(self
, key
, value
):
1954 self
[key
].assign(value
)
1957 class Extra3RM(ExtraRM
):
1958 idx0
: _Field
= range(0, 3)
1959 idx1
: _Field
= range(3, 6)
1960 idx2
: _Field
= range(6, 9)
1962 def __getitem__(self
, key
):
1967 _SVExtra
.Idx0
: self
.idx0
,
1968 _SVExtra
.Idx1
: self
.idx1
,
1969 _SVExtra
.Idx2
: self
.idx2
,
1972 def __setitem__(self
, key
, value
):
1973 self
[key
].assign(value
)
1976 class BaseRM(_Mapping
):
1977 _
: _Field
= range(24)
1978 mmode
: _Field
= (0,)
1979 mask
: _Field
= range(1, 4)
1980 elwidth
: _Field
= range(4, 6)
1981 ewsrc
: _Field
= range(6, 8)
1982 subvl
: _Field
= range(8, 10)
1983 mode
: Mode
.remap(range(19, 24))
1984 smask_extra322
: _Field
= (6,7,18,) # LDST_IDX is EXTRA332
1985 smask
: _Field
= range(16, 19) # everything else use this
1986 extra
: ExtraRM
.remap(range(10, 19))
1987 extra2
: Extra2RM
.remap(range(10, 19))
1988 extra3
: Extra3RM
.remap(range(10, 19))
1989 # XXX extra332 = (extra3[0], extra3[1], extra2[3])
1991 def specifiers(self
, record
):
1992 subvl
= int(self
.subvl
)
2000 def disassemble(self
, style
=Style
.NORMAL
):
2001 if style
>= Style
.VERBOSE
:
2003 for (name
, span
) in self
.traverse(path
="RM"):
2004 value
= self
.storage
[span
]
2006 yield f
"{indent}{int(value):0{value.bits}b}"
2007 yield f
"{indent}{', '.join(map(str, span))}"
2010 class FFRc1BaseRM(BaseRM
):
2011 def specifiers(self
, record
, mode
):
2012 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
2013 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
2014 mask
= int(_selectconcat(CR
, inv
))
2015 predicate
= PredicateBaseRM
.predicate(True, mask
)
2016 yield f
"{mode}={predicate}"
2018 yield from super().specifiers(record
=record
)
2021 class FFRc0BaseRM(BaseRM
):
2022 def specifiers(self
, record
, mode
):
2024 inv
= "~" if self
.inv
else ""
2025 yield f
"{mode}={inv}RC1"
2027 yield from super().specifiers(record
=record
)
2030 class SatBaseRM(BaseRM
):
2031 def specifiers(self
, record
):
2037 yield from super().specifiers(record
=record
)
2040 class ZZBaseRM(BaseRM
):
2041 def specifiers(self
, record
):
2045 yield from super().specifiers(record
=record
)
2048 class ZZCombinedBaseRM(BaseRM
):
2049 def specifiers(self
, record
):
2050 if self
.sz
and self
.dz
:
2057 yield from super().specifiers(record
=record
)
2060 class DZBaseRM(BaseRM
):
2061 def specifiers(self
, record
):
2065 yield from super().specifiers(record
=record
)
2068 class SZBaseRM(BaseRM
):
2069 def specifiers(self
, record
):
2073 yield from super().specifiers(record
=record
)
2076 class MRBaseRM(BaseRM
):
2077 def specifiers(self
, record
):
2083 yield from super().specifiers(record
=record
)
2086 class ElsBaseRM(BaseRM
):
2087 def specifiers(self
, record
):
2091 yield from super().specifiers(record
=record
)
2094 class WidthBaseRM(BaseRM
):
2096 def width(FP
, width
):
2105 width
= ("fp" + width
)
2108 def specifiers(self
, record
):
2109 # elwidths: use "w=" if same otherwise dw/sw
2110 # FIXME this should consider FP instructions
2112 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
2113 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2114 if record
.svp64
.mode
is _SVMode
.CROP
:
2118 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2127 yield from super().specifiers(record
=record
)
2130 class PredicateBaseRM(BaseRM
):
2132 def predicate(CR
, mask
):
2135 (False, 0b001): "1<<r3",
2136 (False, 0b010): "r3",
2137 (False, 0b011): "~r3",
2138 (False, 0b100): "r10",
2139 (False, 0b101): "~r10",
2140 (False, 0b110): "r30",
2141 (False, 0b111): "~r30",
2143 (True, 0b000): "lt",
2144 (True, 0b001): "ge",
2145 (True, 0b010): "gt",
2146 (True, 0b011): "le",
2147 (True, 0b100): "eq",
2148 (True, 0b101): "ne",
2149 (True, 0b110): "so",
2150 (True, 0b111): "ns",
2153 def specifiers(self
, record
):
2154 # predication - single and twin
2155 # use "m=" if same otherwise sm/dm
2156 CR
= (int(self
.mmode
) == 1)
2157 mask
= int(self
.mask
)
2158 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
2159 if record
.svp64
.ptype
is _SVPType
.P2
:
2160 # LDST_IDX smask moving to extra322 but not straight away (False)
2161 if False and record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2162 smask
= int(self
.smask_extra332
)
2164 smask
= int(self
.smask
)
2165 sm
= PredicateBaseRM
.predicate(CR
, smask
)
2174 yield from super().specifiers(record
=record
)
2177 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
2181 class SEABaseRM(BaseRM
):
2182 def specifiers(self
, record
):
2186 yield from super().specifiers(record
=record
)
2189 class VLiBaseRM(BaseRM
):
2190 def specifiers(self
, record
):
2194 yield from super().specifiers(record
=record
)
2197 class NormalBaseRM(PredicateWidthBaseRM
):
2200 https://libre-soc.org/openpower/sv/normal/
2205 class NormalSimpleRM(ZZCombinedBaseRM
, NormalBaseRM
):
2206 """normal: simple mode"""
2210 def specifiers(self
, record
):
2211 yield from super().specifiers(record
=record
)
2214 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
2215 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
2219 class NormalFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, NormalBaseRM
):
2220 """normal: Rc=1: ffirst CR sel"""
2223 CR
: BaseRM
.mode
[3, 4]
2225 def specifiers(self
, record
):
2226 yield from super().specifiers(record
=record
, mode
="ff")
2229 class NormalFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
2230 """normal: Rc=0: ffirst z/nonz"""
2235 def specifiers(self
, record
):
2236 yield from super().specifiers(record
=record
, mode
="ff")
2239 class NormalSatRM(SatBaseRM
, ZZCombinedBaseRM
, NormalBaseRM
):
2240 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2246 class NormalRM(NormalBaseRM
):
2247 simple
: NormalSimpleRM
2249 ffrc1
: NormalFFRc1RM
2250 ffrc0
: NormalFFRc0RM
2254 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2256 LD/ST Immediate mode
2257 https://libre-soc.org/openpower/sv/ldst/
2262 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2263 """ld/st immediate: simple mode"""
2264 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2265 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2271 def specifiers(self
, record
):
2277 yield from super().specifiers(record
=record
)
2280 class LDSTFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2281 """ld/st immediate&indexed: Rc=1: ffirst CR sel"""
2284 CR
: BaseRM
.mode
[3, 4]
2286 def specifiers(self
, record
):
2287 yield from super().specifiers(record
=record
, mode
="ff")
2290 class LDSTFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2291 """ld/st immediate&indexed: Rc=0: ffirst z/nonz"""
2296 def specifiers(self
, record
):
2297 yield from super().specifiers(record
=record
, mode
="ff")
2300 class LDSTImmRM(LDSTImmBaseRM
):
2301 simple
: LDSTImmSimpleRM
2306 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2309 https://libre-soc.org/openpower/sv/ldst/
2314 class LDSTIdxSimpleRM(SEABaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2315 """ld/st index: simple mode (includes element-strided and Signed-EA)"""
2316 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2323 def specifiers(self
, record
):
2329 yield from super().specifiers(record
=record
)
2332 class LDSTIdxRM(LDSTIdxBaseRM
):
2333 simple
: LDSTIdxSimpleRM
2339 class CROpBaseRM(BaseRM
):
2342 https://libre-soc.org/openpower/sv/cr_ops/
2347 class CROpSimpleRM(PredicateBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2348 """crop: simple mode"""
2353 def specifiers(self
, record
):
2355 yield "rg" # simple CR Mode reports /rg
2357 yield from super().specifiers(record
=record
)
2360 class CROpMRRM(MRBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2361 """crop: scalar reduce mode (mapreduce)"""
2367 class CROpFF5RM(FFRc0BaseRM
, PredicateBaseRM
, VLiBaseRM
, DZBaseRM
,
2368 SZBaseRM
, CROpBaseRM
):
2369 """crop: ffirst 5-bit mode"""
2376 def specifiers(self
, record
):
2377 yield from super().specifiers(record
=record
, mode
="ff")
2380 # FIXME: almost everything in this class contradicts the specs (it doesn't)
2381 # The modes however are swapped: 5-bit is 3-bit, 3-bit is 5-bit
2382 class CROpFF3RM(FFRc1BaseRM
, PredicateBaseRM
, VLiBaseRM
, ZZBaseRM
, CROpBaseRM
):
2383 """cr_op: ffirst 3-bit mode"""
2389 def specifiers(self
, record
):
2390 yield from super().specifiers(record
=record
, mode
="ff")
2393 class CROpRM(CROpBaseRM
):
2394 simple
: CROpSimpleRM
2400 # ********************
2402 # https://libre-soc.org/openpower/sv/branches/
2403 class BranchBaseRM(BaseRM
):
2413 def specifiers(self
, record
):
2425 raise ValueError(self
.sz
)
2437 # Branch modes lack source mask.
2438 # Therefore a custom code is needed.
2439 CR
= (int(self
.mmode
) == 1)
2440 mask
= int(self
.mask
)
2441 m
= PredicateBaseRM
.predicate(CR
, mask
)
2445 yield from super().specifiers(record
=record
)
2448 class BranchSimpleRM(BranchBaseRM
):
2449 """branch: simple mode"""
2453 class BranchVLSRM(BranchBaseRM
):
2454 """branch: VLSET mode"""
2458 def specifiers(self
, record
):
2464 }[int(self
.VSb
), int(self
.VLi
)]
2466 yield from super().specifiers(record
=record
)
2469 class BranchCTRRM(BranchBaseRM
):
2470 """branch: CTR-test mode"""
2473 def specifiers(self
, record
):
2479 yield from super().specifiers(record
=record
)
2482 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2483 """branch: CTR-test+VLSET mode"""
2487 class BranchRM(BranchBaseRM
):
2488 simple
: BranchSimpleRM
2491 ctrvls
: BranchCTRVLSRM
2502 @_dataclasses.dataclass(eq
=True, frozen
=True)
2507 def match(cls
, desc
, record
):
2508 raise NotImplementedError()
2510 def validate(self
, others
):
2513 def assemble(self
, insn
):
2514 raise NotImplementedError()
2517 @_dataclasses.dataclass(eq
=True, frozen
=True)
2518 class SpecifierWidth(Specifier
):
2522 def match(cls
, desc
, record
, etalon
):
2523 (mode
, _
, value
) = desc
.partition("=")
2525 value
= value
.strip()
2528 width
= _SVP64Width(value
)
2530 return cls(record
=record
, width
=width
)
2533 @_dataclasses.dataclass(eq
=True, frozen
=True)
2534 class SpecifierW(SpecifierWidth
):
2536 def match(cls
, desc
, record
):
2537 return super().match(desc
=desc
, record
=record
, etalon
="w")
2539 def assemble(self
, insn
):
2540 selector
= insn
.select(record
=self
.record
)
2541 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2542 selector
.ewsrc
= self
.width
.value
2543 selector
.elwidth
= self
.width
.value
2546 @_dataclasses.dataclass(eq
=True, frozen
=True)
2547 class SpecifierSW(SpecifierWidth
):
2549 def match(cls
, desc
, record
):
2550 if record
.svp64
.mode
is _SVMode
.CROP
:
2552 return super().match(desc
=desc
, record
=record
, etalon
="sw")
2554 def assemble(self
, insn
):
2555 selector
= insn
.select(record
=self
.record
)
2556 selector
.ewsrc
= self
.width
.value
2559 @_dataclasses.dataclass(eq
=True, frozen
=True)
2560 class SpecifierDW(SpecifierWidth
):
2562 def match(cls
, desc
, record
):
2563 return super().match(desc
=desc
, record
=record
, etalon
="dw")
2565 def assemble(self
, insn
):
2566 selector
= insn
.select(record
=self
.record
)
2567 selector
.elwidth
= self
.width
.value
2570 @_dataclasses.dataclass(eq
=True, frozen
=True)
2571 class SpecifierSubVL(Specifier
):
2575 def match(cls
, desc
, record
):
2577 value
= _SVP64SubVL(desc
)
2581 return cls(record
=record
, value
=value
)
2583 def assemble(self
, insn
):
2584 selector
= insn
.select(record
=self
.record
)
2585 selector
.subvl
= int(self
.value
.value
)
2588 @_dataclasses.dataclass(eq
=True, frozen
=True)
2589 class SpecifierPredicate(Specifier
):
2594 def match(cls
, desc
, record
, mode_match
, pred_match
):
2595 (mode
, _
, pred
) = desc
.partition("=")
2598 if not mode_match(mode
):
2601 pred
= _SVP64Pred(pred
.strip())
2602 if not pred_match(pred
):
2603 raise ValueError(pred
)
2605 return cls(record
=record
, mode
=mode
, pred
=pred
)
2608 @_dataclasses.dataclass(eq
=True, frozen
=True)
2609 class SpecifierFF(SpecifierPredicate
):
2611 def match(cls
, desc
, record
):
2612 return super().match(desc
=desc
, record
=record
,
2613 mode_match
=lambda mode_arg
: mode_arg
== "ff",
2614 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2619 def assemble(self
, insn
):
2620 selector
= insn
.select(record
=self
.record
)
2621 if selector
.mode
.sel
!= 0:
2622 raise ValueError("cannot override mode")
2623 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2624 selector
.mode
.sel
= 0b01
2625 # HACK: please finally provide correct logic for CRs.
2626 if self
.pred
in (_SVP64Pred
.RC1
, _SVP64Pred
.RC1_N
):
2627 selector
.mode
[2] = (self
.pred
is _SVP64Pred
.RC1_N
)
2629 selector
.mode
[2] = self
.pred
.inv
2630 selector
.mode
[3, 4] = self
.pred
.state
2632 selector
.mode
.sel
= 0b01 if self
.mode
== "ff" else 0b11
2633 selector
.inv
= self
.pred
.inv
2635 selector
.CR
= self
.pred
.state
2637 selector
.RC1
= self
.pred
.state
2640 @_dataclasses.dataclass(eq
=True, frozen
=True)
2641 class SpecifierMask(SpecifierPredicate
):
2643 def match(cls
, desc
, record
, mode
):
2644 return super().match(desc
=desc
, record
=record
,
2645 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2646 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2651 def assemble(self
, insn
):
2652 raise NotImplementedError()
2655 @_dataclasses.dataclass(eq
=True, frozen
=True)
2656 class SpecifierM(SpecifierMask
):
2658 def match(cls
, desc
, record
):
2659 return super().match(desc
=desc
, record
=record
, mode
="m")
2661 def validate(self
, others
):
2663 if isinstance(spec
, SpecifierSM
):
2664 raise ValueError("source-mask and predicate mask conflict")
2665 elif isinstance(spec
, SpecifierDM
):
2666 raise ValueError("dest-mask and predicate mask conflict")
2668 def assemble(self
, insn
):
2669 selector
= insn
.select(record
=self
.record
)
2670 selector
.mask
= int(self
.pred
)
2671 if ((self
.record
.ptype
is _SVPType
.P2
) and
2672 (self
.record
.svp64
.mode
is not _SVMode
.BRANCH
)):
2673 selector
.smask
= int(self
.pred
)
2674 # LDST_IDX smask moving to extra322 but not straight away (False)
2675 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2676 selector
.smask_extra332
= int(self
.pred
)
2678 selector
.smask
= int(self
.pred
)
2680 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2683 @_dataclasses.dataclass(eq
=True, frozen
=True)
2684 class SpecifierSM(SpecifierMask
):
2686 def match(cls
, desc
, record
):
2687 return super().match(desc
=desc
, record
=record
, mode
="sm")
2689 def validate(self
, others
):
2690 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2691 raise ValueError("source-mask on non-twin predicate")
2693 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2696 if isinstance(spec
, SpecifierDM
):
2700 raise ValueError("missing dest-mask in CR twin predication")
2701 if self
.pred
.mode
!= twin
.pred
.mode
:
2702 raise ValueError(f
"predicate masks mismatch: "
2703 f
"{self.pred!r} vs {twin.pred!r}")
2705 def assemble(self
, insn
):
2706 selector
= insn
.select(record
=self
.record
)
2707 # LDST_IDX smask moving to extra322 but not straight away (False)
2708 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2709 selector
.smask_extra332
= int(self
.pred
)
2711 selector
.smask
= int(self
.pred
)
2712 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2715 @_dataclasses.dataclass(eq
=True, frozen
=True)
2716 class SpecifierDM(SpecifierMask
):
2718 def match(cls
, desc
, record
):
2719 return super().match(desc
=desc
, record
=record
, mode
="dm")
2721 def validate(self
, others
):
2722 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2723 raise ValueError("dest-mask on non-twin predicate")
2725 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2728 if isinstance(spec
, SpecifierSM
):
2732 raise ValueError("missing source-mask in CR twin predication")
2733 if self
.pred
.mode
!= twin
.pred
.mode
:
2734 raise ValueError(f
"predicate masks mismatch: "
2735 f
"{self.pred!r} vs {twin.pred!r}")
2737 def assemble(self
, insn
):
2738 selector
= insn
.select(record
=self
.record
)
2739 selector
.mask
= int(self
.pred
)
2740 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2743 @_dataclasses.dataclass(eq
=True, frozen
=True)
2744 class SpecifierZZ(Specifier
):
2746 def match(cls
, desc
, record
):
2750 return cls(record
=record
)
2752 def validate(self
, others
):
2754 # Since zz takes precedence (overrides) sz and dz,
2755 # treat them as mutually exclusive.
2756 if isinstance(spec
, (SpecifierSZ
, SpecifierDZ
)):
2757 raise ValueError("mutually exclusive predicate masks")
2759 def assemble(self
, insn
):
2760 selector
= insn
.select(record
=self
.record
)
2761 if hasattr(selector
, "zz"): # this should be done in a different way
2768 @_dataclasses.dataclass(eq
=True, frozen
=True)
2769 class SpecifierXZ(Specifier
):
2771 hint
: str = _dataclasses
.field(repr=False)
2774 def match(cls
, desc
, record
, etalon
, hint
):
2778 return cls(desc
=desc
, record
=record
, hint
=hint
)
2780 def validate(self
, others
):
2781 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2782 raise ValueError(f
"{self.hint} on non-twin predicate")
2784 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2787 if isinstance(spec
, SpecifierXZ
):
2791 raise ValueError(f
"missing {self.hint} in CR twin predication")
2792 if self
.pred
!= twin
.pred
:
2793 raise ValueError(f
"predicate masks mismatch: "
2794 f
"{self.pred!r} vs {twin.pred!r}")
2796 def assemble(self
, insn
):
2797 selector
= insn
.select(record
=self
.record
)
2798 setattr(selector
, self
.desc
, 1)
2801 @_dataclasses.dataclass(eq
=True, frozen
=True)
2802 class SpecifierSZ(SpecifierXZ
):
2804 def match(cls
, desc
, record
):
2805 return super().match(desc
=desc
, record
=record
,
2806 etalon
="sz", hint
="source-mask")
2808 def validate(self
, others
):
2810 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2811 if isinstance(spec
, SpecifierFF
):
2812 raise ValueError("source-zero not allowed in ff mode")
2815 @_dataclasses.dataclass(eq
=True, frozen
=True)
2816 class SpecifierDZ(SpecifierXZ
):
2818 def match(cls
, desc
, record
):
2819 return super().match(desc
=desc
, record
=record
,
2820 etalon
="dz", hint
="dest-mask")
2822 def validate(self
, others
):
2824 if ((self
.record
.svp64
.mode
is not _SVMode
.CROP
) and
2825 isinstance(spec
, SpecifierFF
) and
2826 (spec
.pred
.mode
is _SVP64PredMode
.RC1
)):
2827 raise ValueError(f
"dest-zero not allowed in ff mode BO")
2830 @_dataclasses.dataclass(eq
=True, frozen
=True)
2831 class SpecifierEls(Specifier
):
2833 def match(cls
, desc
, record
):
2837 if record
.svp64
.mode
not in (_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
):
2838 raise ValueError("els is only valid in ld/st modes, not "
2839 "%s" % str(self
.record
.svp64
.mode
))
2841 return cls(record
=record
)
2843 def assemble(self
, insn
):
2844 if self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
: # stride mode
2845 insn
.prefix
.rm
.mode
[1] = 0
2847 selector
= insn
.select(record
=self
.record
)
2852 @_dataclasses.dataclass(eq
=True, frozen
=True)
2853 class SpecifierSEA(Specifier
):
2855 def match(cls
, desc
, record
):
2859 return cls(record
=record
)
2861 def validate(self
, others
):
2862 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
:
2863 raise ValueError("sea is only valid in ld/st modes, not "
2864 "%s" % str(self
.record
.svp64
.mode
))
2867 if isinstance(spec
, SpecifierFF
):
2868 raise ValueError(f
"sea cannot be used in ff mode")
2870 def assemble(self
, insn
):
2871 selector
= insn
.select(record
=self
.record
)
2872 if selector
.mode
.sel
not in (0b10, 0b00):
2873 raise ValueError("sea is only valid for normal and els modes, "
2874 "not %d" % int(selector
.mode
.sel
))
2878 @_dataclasses.dataclass(eq
=True, frozen
=True)
2879 class SpecifierSat(Specifier
):
2884 def match(cls
, desc
, record
, etalon
, sign
):
2888 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.LDST_IMM
,
2890 raise ValueError("only normal, ld/st imm and "
2891 "ld/st idx modes supported")
2893 return cls(record
=record
, desc
=desc
, sign
=sign
)
2895 def assemble(self
, insn
):
2896 selector
= insn
.select(record
=self
.record
)
2897 selector
.mode
[0] = 0b1
2898 selector
.mode
[1] = 0b0
2899 selector
.N
= int(self
.sign
)
2902 @_dataclasses.dataclass(eq
=True, frozen
=True)
2903 class SpecifierSatS(SpecifierSat
):
2905 def match(cls
, desc
, record
):
2906 return super().match(desc
=desc
, record
=record
,
2907 etalon
="sats", sign
=True)
2910 @_dataclasses.dataclass(eq
=True, frozen
=True)
2911 class SpecifierSatU(SpecifierSat
):
2913 def match(cls
, desc
, record
):
2914 return super().match(desc
=desc
, record
=record
,
2915 etalon
="satu", sign
=False)
2918 @_dataclasses.dataclass(eq
=True, frozen
=True)
2919 class SpecifierMapReduce(Specifier
):
2923 def match(cls
, record
, RG
):
2924 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2925 raise ValueError("only normal and crop modes supported")
2927 return cls(record
=record
, RG
=RG
)
2929 def assemble(self
, insn
):
2930 selector
= insn
.select(record
=self
.record
)
2931 if self
.record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2932 raise ValueError("only normal and crop modes supported")
2933 selector
.mode
[0] = 0
2934 selector
.mode
[1] = 0
2935 selector
.mode
[2] = 1
2936 selector
.RG
= self
.RG
2939 @_dataclasses.dataclass(eq
=True, frozen
=True)
2940 class SpecifierMR(SpecifierMapReduce
):
2942 def match(cls
, desc
, record
):
2946 return super().match(record
=record
, RG
=False)
2949 @_dataclasses.dataclass(eq
=True, frozen
=True)
2950 class SpecifierMRR(SpecifierMapReduce
):
2952 def match(cls
, desc
, record
):
2956 return super().match(record
=record
, RG
=True)
2959 @_dataclasses.dataclass(eq
=True, frozen
=True)
2960 class SpecifierBranch(Specifier
):
2962 def match(cls
, desc
, record
, etalon
):
2966 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
2967 raise ValueError("only branch modes supported")
2969 return cls(record
=record
)
2972 @_dataclasses.dataclass(eq
=True, frozen
=True)
2973 class SpecifierAll(SpecifierBranch
):
2975 def match(cls
, desc
, record
):
2976 return super().match(desc
=desc
, record
=record
, etalon
="all")
2978 def assemble(self
, insn
):
2979 selector
= insn
.select(record
=self
.record
)
2983 @_dataclasses.dataclass(eq
=True, frozen
=True)
2984 class SpecifierSNZ(Specifier
):
2986 def match(cls
, desc
, record
):
2990 if record
.svp64
.mode
not in (_SVMode
.BRANCH
, _SVMode
.CROP
):
2991 raise ValueError("only branch and crop modes supported")
2993 return cls(record
=record
)
2995 def assemble(self
, insn
):
2996 selector
= insn
.select(record
=self
.record
)
2997 if self
.record
.svp64
.mode
in (_SVMode
.CROP
, _SVMode
.BRANCH
):
2999 if self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3002 raise ValueError("only branch and crop modes supported")
3005 @_dataclasses.dataclass(eq
=True, frozen
=True)
3006 class SpecifierSL(SpecifierBranch
):
3008 def match(cls
, desc
, record
):
3009 return super().match(desc
=desc
, record
=record
, etalon
="sl")
3011 def assemble(self
, insn
):
3012 selector
= insn
.select(record
=self
.record
)
3016 @_dataclasses.dataclass(eq
=True, frozen
=True)
3017 class SpecifierSLu(SpecifierBranch
):
3019 def match(cls
, desc
, record
):
3020 return super().match(desc
=desc
, record
=record
, etalon
="slu")
3022 def assemble(self
, insn
):
3023 selector
= insn
.select(record
=self
.record
)
3027 @_dataclasses.dataclass(eq
=True, frozen
=True)
3028 class SpecifierLRu(SpecifierBranch
):
3030 def match(cls
, desc
, record
):
3031 return super().match(desc
=desc
, record
=record
, etalon
="lru")
3033 def assemble(self
, insn
):
3034 selector
= insn
.select(record
=self
.record
)
3038 @_dataclasses.dataclass(eq
=True, frozen
=True)
3039 class SpecifierVSXX(SpecifierBranch
):
3044 def match(cls
, desc
, record
, etalon
, VSb
, VLi
):
3048 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3049 raise ValueError("only branch modes supported")
3051 return cls(record
=record
, VSb
=VSb
, VLi
=VLi
)
3053 def assemble(self
, insn
):
3054 selector
= insn
.select(record
=self
.record
)
3056 selector
.VSb
= int(self
.VSb
)
3057 selector
.VLi
= int(self
.VLi
)
3060 @_dataclasses.dataclass(eq
=True, frozen
=True)
3061 class SpecifierVS(SpecifierVSXX
):
3063 def match(cls
, desc
, record
):
3064 return super().match(desc
=desc
, record
=record
,
3065 etalon
="vs", VSb
=False, VLi
=False)
3068 @_dataclasses.dataclass(eq
=True, frozen
=True)
3069 class SpecifierVSi(SpecifierVSXX
):
3071 def match(cls
, desc
, record
):
3072 return super().match(desc
=desc
, record
=record
,
3073 etalon
="vsi", VSb
=False, VLi
=True)
3076 @_dataclasses.dataclass(eq
=True, frozen
=True)
3077 class SpecifierVSb(SpecifierVSXX
):
3079 def match(cls
, desc
, record
):
3080 return super().match(desc
=desc
, record
=record
,
3081 etalon
="vsb", VSb
=True, VLi
=False)
3084 @_dataclasses.dataclass(eq
=True, frozen
=True)
3085 class SpecifierVSbi(SpecifierVSXX
):
3087 def match(cls
, desc
, record
):
3088 return super().match(desc
=desc
, record
=record
,
3089 etalon
="vsbi", VSb
=True, VLi
=True)
3092 @_dataclasses.dataclass(eq
=True, frozen
=True)
3093 class SpecifierCTX(Specifier
):
3097 def match(cls
, desc
, record
, etalon
, CTi
):
3101 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3102 raise ValueError("only branch modes supported")
3104 return cls(record
=record
, CTi
=CTi
)
3106 def assemble(self
, insn
):
3107 selector
= insn
.select(record
=self
.record
)
3109 selector
.CTi
= int(self
.CTi
)
3112 @_dataclasses.dataclass(eq
=True, frozen
=True)
3113 class SpecifierCTR(SpecifierCTX
):
3115 def match(cls
, desc
, record
):
3116 return super().match(desc
=desc
, record
=record
,
3117 etalon
="ctr", CTi
=False)
3120 @_dataclasses.dataclass(eq
=True, frozen
=True)
3121 class SpecifierCTi(SpecifierCTX
):
3123 def match(cls
, desc
, record
):
3124 return super().match(desc
=desc
, record
=record
,
3125 etalon
="cti", CTi
=True)
3128 @_dataclasses.dataclass(eq
=True, frozen
=True)
3129 class SpecifierPI(Specifier
):
3131 def match(cls
, desc
, record
):
3135 if record
.svp64
.mode
not in [_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
]:
3136 raise ValueError("only ld/st imm/idx mode supported")
3138 return cls(record
=record
)
3140 def assemble(self
, insn
):
3141 selector
= insn
.select(record
=self
.record
)
3142 selector
.mode
[2] = 0b1
3146 @_dataclasses.dataclass(eq
=True, frozen
=True)
3147 class SpecifierLF(Specifier
):
3149 def match(cls
, desc
, record
):
3153 if record
.svp64
.mode
is not _SVMode
.LDST_IMM
:
3154 raise ValueError("only ld/st imm mode supported")
3156 return cls(record
=record
)
3158 def assemble(self
, insn
):
3159 selector
= insn
.select(record
=self
.record
)
3160 selector
.mode
[1] = 0
3164 @_dataclasses.dataclass(eq
=True, frozen
=True)
3165 class SpecifierVLi(Specifier
):
3167 def match(cls
, desc
, record
):
3171 return cls(record
=record
)
3173 def validate(self
, others
):
3175 if isinstance(spec
, SpecifierFF
):
3178 raise ValueError("VLi only allowed in failfirst")
3180 def assemble(self
, insn
):
3181 selector
= insn
.select(record
=self
.record
)
3182 selector
.mode
[1] = 1
3186 class Specifiers(tuple):
3221 def __new__(cls
, items
, record
):
3222 def transform(item
):
3223 for spec_cls
in cls
.SPECS
:
3224 spec
= spec_cls
.match(item
, record
=record
)
3225 if spec
is not None:
3227 raise ValueError(item
)
3229 # TODO: remove this hack
3230 items
= dict.fromkeys(items
)
3234 items
= tuple(items
)
3236 specs
= tuple(map(transform
, items
))
3237 for (index
, spec
) in enumerate(specs
):
3238 head
= specs
[:index
]
3239 tail
= specs
[index
+ 1:]
3240 spec
.validate(others
=(head
+ tail
))
3242 return super().__new
__(cls
, specs
)
3245 class SVP64OperandMeta(type):
3246 class SVP64NonZeroOperand(NonZeroOperand
):
3247 def assemble(self
, insn
, value
):
3248 if isinstance(value
, str):
3249 value
= int(value
, 0)
3250 if not isinstance(value
, int):
3251 raise ValueError("non-integer operand")
3253 # FIXME: this is really weird
3254 if self
.record
.name
in ("svstep", "svstep."):
3255 value
+= 1 # compensation
3257 return super().assemble(value
=value
, insn
=insn
)
3259 class SVP64XOStaticOperand(SpanStaticOperand
):
3260 def __init__(self
, record
, value
, span
):
3261 return super().__init
__(record
=record
, name
="XO",
3262 value
=value
, span
=span
)
3265 NonZeroOperand
: SVP64NonZeroOperand
,
3266 XOStaticOperand
: SVP64XOStaticOperand
,
3269 def __new__(metacls
, name
, bases
, ns
):
3271 for (index
, base_cls
) in enumerate(bases
):
3272 bases
[index
] = metacls
.__TRANSFORM
.get(base_cls
, base_cls
)
3274 bases
= tuple(bases
)
3276 return super().__new
__(metacls
, name
, bases
, ns
)
3279 class SVP64Operand(Operand
, metaclass
=SVP64OperandMeta
):
3282 return tuple(map(lambda bit
: (bit
+ 32), super().span
))
3286 def __init__(self
, insn
, record
):
3288 self
.__record
= record
3289 return super().__init
__()
3292 return self
.rm
.__doc
__
3295 return repr(self
.rm
)
3303 return self
.__record
3307 rm
= getattr(self
.insn
.prefix
.rm
, self
.record
.svp64
.mode
.name
.lower())
3309 # The idea behind these tables is that they are now literally
3310 # in identical format to insndb.csv and minor_xx.csv and can
3311 # be done precisely as that. The only thing to watch out for
3312 # is the insertion of Rc=1 as a "mask/value" bit and likewise
3313 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
3316 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
3317 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3318 # mode Rc mask Rc member
3320 (0b000000, 0b111000, "simple"), # simple (no Rc)
3321 (0b001000, 0b111100, "mr"), # mapreduce (no Rc)
3322 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3323 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3324 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3325 (0b001100, 0b111100, "rsvd"), # reserved
3327 mode
= int(self
.insn
.prefix
.rm
.normal
.mode
)
3328 search
= ((mode
<< 1) | self
.record
.Rc
)
3330 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
3331 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3332 # mode Rc mask Rc member
3333 # ironically/coincidentally this table is identical to NORMAL
3334 # mode except reserved in place of mr
3336 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3337 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3338 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3340 search
= ((int(self
.insn
.prefix
.rm
.ldst_imm
.mode
) << 1) |
3343 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
3344 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3345 # mode Rc mask Rc member
3347 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3348 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3349 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3351 search
= ((int(self
.insn
.prefix
.rm
.ldst_idx
.mode
) << 1) |
3354 elif self
.record
.svp64
.mode
is _SVMode
.CROP
:
3355 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
3356 # mode 3b mask 3b member
3358 (0b000000, 0b111000, "simple"), # simple
3359 (0b001000, 0b111000, "mr"), # mapreduce
3360 (0b010001, 0b010001, "ff3"), # ffirst, 3-bit CR
3361 (0b010000, 0b010000, "ff5"), # ffirst, 5-bit CR
3363 search
= ((int(self
.insn
.prefix
.rm
.crop
.mode
) << 1) |
3364 int(self
.record
.svp64
.extra_CR_3bit
))
3366 elif self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3370 (0b00, 0b11, "simple"), # simple
3371 (0b01, 0b11, "vls"), # VLset
3372 (0b10, 0b11, "ctr"), # CTR mode
3373 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
3375 # slightly weird: doesn't have a 5-bit "mode" field like others
3376 search
= int(self
.insn
.prefix
.rm
.branch
.mode
.sel
)
3379 if table
is not None:
3380 for (value
, mask
, field
) in table
:
3381 if field
.startswith("rsvd"):
3383 if ((value
& mask
) == (search
& mask
)):
3384 return getattr(rm
, field
)
3388 def __getattr__(self
, key
):
3389 if key
.startswith(f
"_{self.__class__.__name__}__"):
3390 return super().__getattribute
__(key
)
3392 return getattr(self
.rm
, key
)
3394 def __setattr__(self
, key
, value
):
3395 if key
.startswith(f
"_{self.__class__.__name__}__"):
3396 return super().__setattr
__(key
, value
)
3399 if not hasattr(rm
, key
):
3400 raise AttributeError(key
)
3402 return setattr(rm
, key
, value
)
3405 class SVP64Instruction(PrefixedInstruction
):
3406 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
3407 class Prefix(PrefixedInstruction
.Prefix
):
3409 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
3413 def select(self
, record
):
3414 return RMSelector(insn
=self
, record
=record
)
3419 for idx
in range(64):
3420 bit
= int(self
[idx
])
3422 return "".join(map(str, bits
))
3425 def assemble(cls
, record
, arguments
=None, specifiers
=None):
3426 insn
= super().assemble(record
=record
, arguments
=arguments
)
3428 specifiers
= Specifiers(items
=specifiers
, record
=record
)
3429 for specifier
in specifiers
:
3430 specifier
.assemble(insn
=insn
)
3432 insn
.prefix
.PO
= 0x1
3433 insn
.prefix
.id = 0x3
3437 def disassemble(self
, record
,
3439 style
=Style
.NORMAL
):
3441 if style
<= Style
.SHORT
:
3444 blob
= insn
.bytes(byteorder
=byteorder
)
3445 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
3448 blob_prefix
= blob(self
.prefix
)
3449 blob_suffix
= blob(self
.suffix
)
3451 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3452 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
3455 assert record
.svp64
is not None
3457 name
= f
"sv.{record.name}"
3459 rm
= self
.select(record
=record
)
3461 # convert specifiers to /x/y/z (sorted lexicographically)
3462 specifiers
= sorted(rm
.specifiers(record
=record
))
3463 if specifiers
: # if any add one extra to get the extra "/"
3464 specifiers
= ([""] + specifiers
)
3465 specifiers
= "/".join(specifiers
)
3467 # convert operands to " ,x,y,z"
3468 operands
= tuple(map(_operator
.itemgetter(1),
3469 self
.spec_dynamic_operands(record
=record
, style
=style
)))
3470 operands
= ",".join(operands
)
3471 if len(operands
) > 0: # if any separate with a space
3472 operands
= (" " + operands
)
3474 if style
<= Style
.LEGACY
:
3475 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3476 suffix
= WordInstruction
.integer(value
=int(self
.suffix
))
3477 yield from suffix
.disassemble(record
=record
,
3478 byteorder
=byteorder
, style
=style
)
3480 yield f
"{blob_prefix}{name}{specifiers}{operands}"
3482 yield f
"{blob_suffix}"
3484 if style
>= Style
.VERBOSE
:
3486 binary
= self
.binary
3487 spec
= self
.spec(record
=record
, prefix
="sv.")
3489 yield f
"{indent}spec"
3490 yield f
"{indent}{indent}{spec}"
3491 yield f
"{indent}pcode"
3492 for stmt
in record
.mdwn
.pcode
:
3493 yield f
"{indent}{indent}{stmt}"
3494 yield f
"{indent}binary"
3495 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
3496 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
3497 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
3498 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
3499 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
3500 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
3501 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
3502 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
3503 yield f
"{indent}opcodes"
3504 for opcode
in record
.opcodes
:
3505 yield f
"{indent}{indent}{opcode!r}"
3506 for operand
in self
.operands(record
=record
):
3507 yield from operand
.disassemble(insn
=self
,
3508 style
=style
, indent
=indent
)
3510 yield f
"{indent}{indent}{str(rm)}"
3511 for line
in rm
.disassemble(style
=style
):
3512 yield f
"{indent}{indent}{line}"
3516 def operands(cls
, record
):
3517 for operand
in super().operands(record
=record
):
3518 parent
= operand
.__class
__
3519 name
= f
"SVP64{parent.__name__}"
3520 bases
= (SVP64Operand
, parent
)
3521 child
= type(name
, bases
, {})
3522 yield child(**dict(operand
))
3525 def parse(stream
, factory
):
3527 return ("TODO" not in frozenset(entry
.values()))
3529 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
3530 entries
= _csv
.DictReader(lines
)
3531 entries
= filter(match
, entries
)
3532 return tuple(map(factory
, entries
))
3535 class MarkdownDatabase
:
3538 for (name
, desc
) in _ISA():
3541 (dynamic
, *static
) = desc
.regs
3542 operands
.extend(dynamic
)
3543 operands
.extend(static
)
3544 pcode
= PCode(iterable
=filter(str.strip
, desc
.pcode
))
3545 operands
= Operands(insn
=name
, operands
=operands
)
3546 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
3548 self
.__db
= dict(sorted(db
.items()))
3550 return super().__init
__()
3553 yield from self
.__db
.items()
3555 def __contains__(self
, key
):
3556 return self
.__db
.__contains
__(key
)
3558 def __getitem__(self
, key
):
3559 return self
.__db
.__getitem
__(key
)
3562 class FieldsDatabase
:
3565 df
= _DecodeFields()
3567 for (form
, fields
) in df
.instrs
.items():
3568 if form
in {"DQE", "TX"}:
3572 db
[_Form
[form
]] = Fields(fields
)
3576 return super().__init
__()
3578 def __getitem__(self
, key
):
3579 return self
.__db
.__getitem
__(key
)
3583 def __init__(self
, root
, mdwndb
):
3584 # The code below groups the instructions by name:section.
3585 # There can be multiple names for the same instruction.
3586 # The point is to capture different opcodes for the same instruction.
3588 records
= _collections
.defaultdict(set)
3589 path
= (root
/ "insndb.csv")
3590 with
open(path
, "r", encoding
="UTF-8") as stream
:
3591 for section
in sorted(parse(stream
, Section
.CSV
)):
3592 path
= (root
/ section
.path
)
3594 section
.Mode
.INTEGER
: IntegerOpcode
,
3595 section
.Mode
.PATTERN
: PatternOpcode
,
3597 factory
= _functools
.partial(
3598 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
3599 with
open(path
, "r", encoding
="UTF-8") as stream
:
3600 for insn
in parse(stream
, factory
):
3601 for name
in insn
.names
:
3602 records
[name
].add(insn
)
3603 sections
[name
] = section
3605 items
= sorted(records
.items())
3607 for (name
, multirecord
) in items
:
3608 records
[name
] = PPCMultiRecord(sorted(multirecord
))
3610 def exact_match(name
):
3611 record
= records
.get(name
)
3617 if not name
.endswith("l"):
3619 alias
= exact_match(name
[:-1])
3622 record
= records
[alias
]
3623 if "lk" not in record
.flags
:
3624 raise ValueError(record
)
3628 if not name
.endswith("a"):
3630 alias
= LK_match(name
[:-1])
3633 record
= records
[alias
]
3634 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
3635 raise ValueError(record
)
3636 if "AA" not in mdwndb
[name
].operands
:
3637 raise ValueError(record
)
3641 if not name
.endswith("."):
3643 alias
= exact_match(name
[:-1])
3646 record
= records
[alias
]
3647 if record
.Rc
is _RCOE
.NONE
:
3648 raise ValueError(record
)
3652 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
3653 for (name
, _
) in mdwndb
:
3654 if name
.startswith("sv."):
3657 for match
in matches
:
3659 if alias
is not None:
3663 section
= sections
[alias
]
3664 record
= records
[alias
]
3665 db
[name
] = (section
, record
)
3667 self
.__db
= dict(sorted(db
.items()))
3669 return super().__init
__()
3671 @_functools.lru_cache(maxsize
=512, typed
=False)
3672 def __getitem__(self
, key
):
3673 return self
.__db
.get(key
, (None, None))
3676 class SVP64Database
:
3677 def __init__(self
, root
, ppcdb
):
3679 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
3680 for (prefix
, _
, names
) in _os
.walk(root
):
3681 prefix
= _pathlib
.Path(prefix
)
3682 for name
in filter(lambda name
: pattern
.match(name
), names
):
3683 path
= (prefix
/ _pathlib
.Path(name
))
3684 with
open(path
, "r", encoding
="UTF-8") as stream
:
3685 db
.update(parse(stream
, SVP64Record
.CSV
))
3686 db
= {record
.name
:record
for record
in db
}
3688 self
.__db
= dict(sorted(db
.items()))
3689 self
.__ppcdb
= ppcdb
3691 return super().__init
__()
3693 def __getitem__(self
, key
):
3694 (_
, record
) = self
.__ppcdb
[key
]
3698 for name
in record
.names
:
3699 record
= self
.__db
.get(name
, None)
3700 if record
is not None:
3707 def __init__(self
, root
):
3708 root
= _pathlib
.Path(root
)
3709 mdwndb
= MarkdownDatabase()
3710 fieldsdb
= FieldsDatabase()
3711 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
3712 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
3716 opcodes
= _collections
.defaultdict(
3717 lambda: _collections
.defaultdict(set))
3719 for (name
, mdwn
) in mdwndb
:
3720 if name
.startswith("sv."):
3722 (section
, ppc
) = ppcdb
[name
]
3725 svp64
= svp64db
[name
]
3726 fields
= fieldsdb
[ppc
.form
]
3727 record
= Record(name
=name
,
3728 section
=section
, ppc
=ppc
, svp64
=svp64
,
3729 mdwn
=mdwn
, fields
=fields
)
3731 names
[record
.name
] = record
3732 opcodes
[section
][record
.PO
].add(record
)
3734 self
.__db
= sorted(db
)
3735 self
.__names
= dict(sorted(names
.items()))
3736 self
.__opcodes
= dict(sorted(opcodes
.items()))
3738 return super().__init
__()
3740 def visit(self
, visitor
):
3741 with visitor
.db(db
=self
) as db
:
3742 for record
in self
.__db
:
3743 record
.visit(visitor
=visitor
)
3746 return repr(self
.__db
)
3749 yield from self
.__db
3751 @_functools.lru_cache(maxsize
=None)
3752 def __contains__(self
, key
):
3753 return self
.__getitem
__(key
) is not None
3755 @_functools.lru_cache(maxsize
=None)
3756 def __getitem__(self
, key
):
3757 if isinstance(key
, SVP64Instruction
):
3760 if isinstance(key
, Instruction
):
3763 sections
= sorted(self
.__opcodes
)
3764 for section
in sections
:
3765 group
= self
.__opcodes
[section
]
3766 for record
in group
[PO
]:
3767 if record
.match(key
=key
):
3772 elif isinstance(key
, str):
3773 return self
.__names
.get(key
)
3775 raise ValueError("instruction or name expected")