1 import collections
as _collections
3 import dataclasses
as _dataclasses
5 import functools
as _functools
7 import operator
as _operator
8 import pathlib
as _pathlib
10 import types
as _types
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 SVMaskSrc
as _SVMaskSrc
,
40 SVP64SubVL
as _SVP64SubVL
,
41 SVP64Pred
as _SVP64Pred
,
42 SVP64PredMode
as _SVP64PredMode
,
43 SVP64Width
as _SVP64Width
,
45 from openpower
.decoder
.selectable_int
import (
46 SelectableInt
as _SelectableInt
,
47 selectconcat
as _selectconcat
,
49 from openpower
.decoder
.power_fields
import (
52 DecodeFields
as _DecodeFields
,
54 from openpower
.decoder
.pseudo
.pagereader
import ISA
as _ISA
57 @_functools.total_ordering
58 class Style(_enum
.Enum
):
62 VERBOSE
= _enum
.auto()
64 def __lt__(self
, other
):
65 if not isinstance(other
, self
.__class
__):
67 return (self
.value
< other
.value
)
70 @_functools.total_ordering
71 class Priority(_enum
.Enum
):
77 def _missing_(cls
, value
):
78 if isinstance(value
, str):
83 return super()._missing
_(value
)
85 def __lt__(self
, other
):
86 if not isinstance(other
, self
.__class
__):
89 # NOTE: the order is inversed, LOW < NORMAL < HIGH
90 return (self
.value
> other
.value
)
93 def dataclass(cls
, record
, keymap
=None, typemap
=None):
97 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
99 def transform(key_value
):
100 (key
, value
) = key_value
101 key
= keymap
.get(key
, key
)
102 hook
= typemap
.get(key
, lambda value
: value
)
103 if hook
is bool and value
in ("", "0"):
109 record
= dict(map(transform
, record
.items()))
110 for key
in frozenset(record
.keys()):
111 if record
[key
] == "":
117 @_functools.total_ordering
118 @_dataclasses.dataclass(eq
=True, frozen
=True)
121 def __new__(cls
, value
):
122 if isinstance(value
, str):
123 value
= int(value
, 0)
124 if not isinstance(value
, int):
125 raise ValueError(value
)
127 if value
.bit_length() > 64:
128 raise ValueError(value
)
130 return super().__new
__(cls
, value
)
133 return self
.__repr
__()
136 return f
"{self:0{self.bit_length()}b}"
138 def bit_length(self
):
139 if super().bit_length() > 32:
143 class Value(Integer
):
152 def __lt__(self
, other
):
153 if not isinstance(other
, Opcode
):
154 return NotImplemented
155 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
158 return (self
.value
& self
.mask
)
161 return int(self
).__index
__()
164 def pattern(value
, mask
, bit_length
):
165 for bit
in range(bit_length
):
166 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
168 elif (value
& (1 << (bit_length
- bit
- 1))):
173 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
175 def match(self
, key
):
176 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
179 @_functools.total_ordering
180 @_dataclasses.dataclass(eq
=True, frozen
=True)
181 class IntegerOpcode(Opcode
):
182 def __init__(self
, value
):
183 if value
.startswith("0b"):
184 mask
= int(("1" * len(value
[2:])), 2)
188 value
= Opcode
.Value(value
)
189 mask
= Opcode
.Mask(mask
)
191 return super().__init
__(value
=value
, mask
=mask
)
194 @_functools.total_ordering
195 @_dataclasses.dataclass(eq
=True, frozen
=True)
196 class PatternOpcode(Opcode
):
197 def __init__(self
, pattern
):
198 if not isinstance(pattern
, str):
199 raise ValueError(pattern
)
201 (value
, mask
) = (0, 0)
202 for symbol
in pattern
:
203 if symbol
not in {"0", "1", "-"}:
204 raise ValueError(pattern
)
205 value |
= (symbol
== "1")
206 mask |
= (symbol
!= "-")
212 value
= Opcode
.Value(value
)
213 mask
= Opcode
.Mask(mask
)
215 return super().__init
__(value
=value
, mask
=mask
)
218 @_dataclasses.dataclass(eq
=True, frozen
=True)
220 class FlagsMeta(type):
235 class Flags(tuple, metaclass
=FlagsMeta
):
236 def __new__(cls
, flags
=frozenset()):
237 flags
= frozenset(flags
)
238 diff
= (flags
- frozenset(cls
))
240 raise ValueError(flags
)
241 return super().__new
__(cls
, sorted(flags
))
245 flags
: Flags
= Flags()
247 function
: _Function
= _Function
.NONE
248 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
249 in1
: _In1Sel
= _In1Sel
.NONE
250 in2
: _In2Sel
= _In2Sel
.NONE
251 in3
: _In3Sel
= _In3Sel
.NONE
252 out
: _OutSel
= _OutSel
.NONE
253 cr_in
: _CRInSel
= _CRInSel
.NONE
254 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
255 cr_out
: _CROutSel
= _CROutSel
.NONE
256 cry_in
: _CryIn
= _CryIn
.ZERO
257 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
258 upd
: _LDSTMode
= _LDSTMode
.NONE
259 Rc
: _RCOE
= _RCOE
.NONE
260 form
: _Form
= _Form
.NONE
262 unofficial
: bool = False
266 "internal op": "intop",
270 "ldst len": "ldst_len",
272 "CONDITIONS": "conditions",
275 def __lt__(self
, other
):
276 if not isinstance(other
, self
.__class
__):
277 return NotImplemented
278 lhs
= (self
.opcode
, self
.comment
)
279 rhs
= (other
.opcode
, other
.comment
)
283 def CSV(cls
, record
, opcode_cls
):
284 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
285 typemap
["opcode"] = opcode_cls
287 if record
["CR in"] == "BA_BB":
288 record
["cr_in"] = "BA"
289 record
["cr_in2"] = "BB"
293 for flag
in frozenset(PPCRecord
.Flags
):
294 if bool(record
.pop(flag
, "")):
296 record
["flags"] = PPCRecord
.Flags(flags
)
298 return dataclass(cls
, record
,
299 keymap
=PPCRecord
.__KEYMAP
,
304 return frozenset(self
.comment
.split("=")[-1].split("/"))
307 class PPCMultiRecord(tuple):
308 def __getattr__(self
, attr
):
311 raise AttributeError(attr
)
312 return getattr(self
[0], attr
)
315 @_dataclasses.dataclass(eq
=True, frozen
=True)
317 class ExtraMap(tuple):
319 @_dataclasses.dataclass(eq
=True, frozen
=True)
321 seltype
: _SelType
= _SelType
.NONE
322 reg
: _Reg
= _Reg
.NONE
325 return f
"{self.seltype.value}:{self.reg.name}"
327 def __new__(cls
, value
="0"):
328 if isinstance(value
, str):
329 def transform(value
):
330 (seltype
, reg
) = value
.split(":")
331 seltype
= _SelType(seltype
)
333 return cls
.Entry(seltype
=seltype
, reg
=reg
)
338 value
= map(transform
, value
.split(";"))
340 return super().__new
__(cls
, value
)
343 return repr(list(self
))
345 def __new__(cls
, value
=tuple()):
349 return super().__new
__(cls
, map(cls
.Extra
, value
))
352 return repr({index
:self
[index
] for index
in range(0, 4)})
355 ptype
: _SVPType
= _SVPType
.NONE
356 etype
: _SVEType
= _SVEType
.NONE
357 msrc
: _SVMaskSrc
= _SVMaskSrc
.NO
# MASK_SRC is active
358 in1
: _In1Sel
= _In1Sel
.NONE
359 in2
: _In2Sel
= _In2Sel
.NONE
360 in3
: _In3Sel
= _In3Sel
.NONE
361 out
: _OutSel
= _OutSel
.NONE
362 out2
: _OutSel
= _OutSel
.NONE
363 cr_in
: _CRInSel
= _CRInSel
.NONE
364 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
365 cr_out
: _CROutSel
= _CROutSel
.NONE
366 extra
: ExtraMap
= ExtraMap()
368 mode
: _SVMode
= _SVMode
.NORMAL
372 "CONDITIONS": "conditions",
381 def CSV(cls
, record
):
382 record
["insn"] = record
["insn"].split("=")[-1]
384 for key
in frozenset({
385 "in1", "in2", "in3", "CR in",
386 "out", "out2", "CR out",
392 if record
["CR in"] == "BA_BB":
393 record
["cr_in"] = "BA"
394 record
["cr_in2"] = "BB"
398 for idx
in range(0, 4):
399 extra
.append(record
.pop(f
"{idx}"))
401 record
["extra"] = cls
.ExtraMap(extra
)
403 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
408 "in1", "in2", "in3", "cr_in", "cr_in2",
409 "out", "out2", "cr_out",
424 for index
in range(0, 4):
425 for entry
in self
.extra
[index
]:
426 extras
[entry
.seltype
][entry
.reg
] = idxmap
[index
]
428 for (seltype
, regs
) in extras
.items():
429 idx
= regs
.get(reg
, _SVExtra
.NONE
)
430 if idx
is not _SVExtra
.NONE
:
431 yield (reg
, seltype
, idx
)
438 sel
= sels
[key
] = getattr(self
, key
)
439 reg
= regs
[key
] = _Reg(sel
)
440 seltypes
[key
] = _SelType
.NONE
441 idxs
[key
] = _SVExtra
.NONE
442 for (reg
, seltype
, idx
) in extra(reg
.alias
):
443 if ((idx
!= idxs
[key
]) and (idxs
[key
] is not _SVExtra
.NONE
)):
444 raise ValueError(idxs
[key
])
447 seltypes
[key
] = seltype
449 if sels
["cr_in"] is _CRInSel
.BA_BB
:
450 sels
["cr_in"] = _CRIn2Sel
.BA
451 sels
["cr_in2"] = _CRIn2Sel
.BB
452 idxs
["cr_in2"] = idxs
["cr_in"]
453 for key
in ("cr_in", "cr_in2"):
454 regs
[key
] = _Reg(sels
[key
])
455 seltype
[key
] = _SelType
.SRC
462 "seltype": seltypes
[key
],
466 return _types
.MappingProxyType(records
)
468 extra_idx_in1
= property(lambda self
: self
.extras
["in1"]["idx"])
469 extra_idx_in2
= property(lambda self
: self
.extras
["in2"]["idx"])
470 extra_idx_in3
= property(lambda self
: self
.extras
["in3"]["idx"])
471 extra_idx_out
= property(lambda self
: self
.extras
["out"]["idx"])
472 extra_idx_out2
= property(lambda self
: self
.extras
["out2"]["idx"])
473 extra_idx_cr_in
= property(lambda self
: self
.extras
["cr_in"]["idx"])
474 extra_idx_cr_in2
= property(lambda self
: self
.extras
["cr_in2"]["idx"])
475 extra_idx_cr_out
= property(lambda self
: self
.extras
["cr_out"]["idx"])
480 for idx
in range(0, 4):
481 for entry
in self
.extra
[idx
]:
482 if entry
.seltype
is _SelType
.DST
:
483 if extra
is not None:
484 raise ValueError(self
.svp64
)
488 if _RegType(extra
.reg
) not in (_RegType
.CR_3BIT
, _RegType
.CR_5BIT
):
489 raise ValueError(self
.svp64
)
494 def extra_CR_3bit(self
):
495 return (_RegType(self
.extra_CR
.reg
) is _RegType
.CR_3BIT
)
499 def __init__(self
, value
=(0, 32)):
500 if isinstance(value
, str):
501 (start
, end
) = map(int, value
.split(":"))
504 if start
< 0 or end
< 0 or start
>= end
:
505 raise ValueError(value
)
510 return super().__init
__()
513 return (self
.__end
- self
.__start
+ 1)
516 return f
"[{self.__start}:{self.__end}]"
519 yield from range(self
.start
, (self
.end
+ 1))
521 def __reversed__(self
):
522 return tuple(reversed(tuple(self
)))
533 @_dataclasses.dataclass(eq
=True, frozen
=True)
535 class Mode(_enum
.Enum
):
536 INTEGER
= _enum
.auto()
537 PATTERN
= _enum
.auto()
540 def _missing_(cls
, value
):
541 if isinstance(value
, str):
542 return cls
[value
.upper()]
543 return super()._missing
_(value
)
546 def __new__(cls
, value
=None):
547 if isinstance(value
, str):
548 if value
.upper() == "NONE":
551 value
= int(value
, 0)
555 return super().__new
__(cls
, value
)
561 return (bin(self
) if self
else "None")
567 opcode
: IntegerOpcode
= None
568 priority
: Priority
= Priority
.NORMAL
570 def __lt__(self
, other
):
571 if not isinstance(other
, self
.__class
__):
572 return NotImplemented
573 return (self
.priority
< other
.priority
)
576 def CSV(cls
, record
):
577 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
578 if record
["opcode"] == "NONE":
579 typemap
["opcode"] = lambda _
: None
581 return dataclass(cls
, record
, typemap
=typemap
)
585 def __init__(self
, items
):
586 if isinstance(items
, dict):
587 items
= items
.items()
590 (name
, bitrange
) = item
591 return (name
, tuple(bitrange
.values()))
593 self
.__mapping
= dict(map(transform
, items
))
595 return super().__init
__()
598 return repr(self
.__mapping
)
601 yield from self
.__mapping
.items()
603 def __contains__(self
, key
):
604 return self
.__mapping
.__contains
__(key
)
606 def __getitem__(self
, key
):
607 return self
.__mapping
.get(key
, None)
622 def __init__(self
, insn
, operands
):
624 "b": {"target_addr": TargetAddrOperandLI
},
625 "ba": {"target_addr": TargetAddrOperandLI
},
626 "bl": {"target_addr": TargetAddrOperandLI
},
627 "bla": {"target_addr": TargetAddrOperandLI
},
628 "bc": {"target_addr": TargetAddrOperandBD
},
629 "bca": {"target_addr": TargetAddrOperandBD
},
630 "bcl": {"target_addr": TargetAddrOperandBD
},
631 "bcla": {"target_addr": TargetAddrOperandBD
},
632 "addpcis": {"D": DOperandDX
},
633 "fishmv": {"D": DOperandDX
},
634 "fmvis": {"D": DOperandDX
},
637 "SVi": NonZeroOperand
,
638 "SVd": NonZeroOperand
,
639 "SVxd": NonZeroOperand
,
640 "SVyd": NonZeroOperand
,
641 "SVzd": NonZeroOperand
,
643 "D": SignedImmediateOperand
,
647 "SIM": SignedOperand
,
648 "SVD": SignedOperand
,
649 "SVDS": SignedOperand
,
650 "RSp": GPRPairOperand
,
651 "RTp": GPRPairOperand
,
652 "FRAp": FPRPairOperand
,
653 "FRBp": FPRPairOperand
,
654 "FRSp": FPRPairOperand
,
655 "FRTp": FPRPairOperand
,
657 custom_immediates
= {
663 for operand
in operands
:
667 (name
, value
) = operand
.split("=")
668 mapping
[name
] = (StaticOperand
, {
674 if name
.endswith(")"):
675 name
= name
.replace("(", " ").replace(")", "")
676 (imm_name
, _
, name
) = name
.partition(" ")
680 if imm_name
is not None:
681 imm_cls
= custom_immediates
.get(imm_name
, ImmediateOperand
)
683 if insn
in custom_insns
and name
in custom_insns
[insn
]:
684 cls
= custom_insns
[insn
][name
]
685 elif name
in custom_fields
:
686 cls
= custom_fields
[name
]
687 elif name
in _Reg
.__members
__:
689 if reg
in self
.__class
__.__GPR
_PAIRS
:
691 elif reg
in self
.__class
__.__FPR
_PAIRS
:
694 regtype
= _RegType
[name
]
695 if regtype
is _RegType
.GPR
:
697 elif regtype
is _RegType
.FPR
:
699 elif regtype
is _RegType
.CR_3BIT
:
701 elif regtype
is _RegType
.CR_5BIT
:
704 if imm_name
is not None:
705 mapping
[imm_name
] = (imm_cls
, {"name": imm_name
})
706 mapping
[name
] = (cls
, {"name": name
})
710 for (name
, (cls
, kwargs
)) in mapping
.items():
711 kwargs
= dict(kwargs
)
712 kwargs
["name"] = name
713 if issubclass(cls
, StaticOperand
):
714 static
.append((cls
, kwargs
))
715 elif issubclass(cls
, DynamicOperand
):
716 dynamic
.append((cls
, kwargs
))
718 raise ValueError(name
)
720 self
.__mapping
= mapping
721 self
.__static
= tuple(static
)
722 self
.__dynamic
= tuple(dynamic
)
724 return super().__init
__()
727 for (_
, items
) in self
.__mapping
.items():
728 (cls
, kwargs
) = items
732 return self
.__mapping
.__repr
__()
734 def __contains__(self
, key
):
735 return self
.__mapping
.__contains
__(key
)
737 def __getitem__(self
, key
):
738 return self
.__mapping
.__getitem
__(key
)
746 return self
.__dynamic
749 class Arguments(tuple):
750 def __new__(cls
, record
, arguments
, operands
):
751 operands
= iter(tuple(operands
))
752 arguments
= iter(tuple(arguments
))
757 operand
= next(operands
)
758 except StopIteration:
762 argument
= next(arguments
)
763 except StopIteration:
764 raise ValueError("operands count mismatch")
766 if isinstance(operand
, ImmediateOperand
):
767 argument
= argument
.replace("(", " ").replace(")", "")
768 (imm_argument
, _
, argument
) = argument
.partition(" ")
770 (imm_operand
, operand
) = (operand
, next(operands
))
771 except StopIteration:
772 raise ValueError("operands count mismatch")
773 items
.append((imm_argument
, imm_operand
))
774 items
.append((argument
, operand
))
778 except StopIteration:
781 raise ValueError("operands count mismatch")
783 return super().__new
__(cls
, items
)
787 def __init__(self
, iterable
):
788 self
.__pcode
= tuple(iterable
)
789 return super().__init
__()
792 yield from self
.__pcode
795 return self
.__pcode
.__repr
__()
798 @_dataclasses.dataclass(eq
=True, frozen
=True)
799 class MarkdownRecord
:
804 @_functools.total_ordering
805 @_dataclasses.dataclass(eq
=True, frozen
=True)
812 svp64
: SVP64Record
= None
814 def __lt__(self
, other
):
815 if not isinstance(other
, Record
):
816 return NotImplemented
817 lhs
= (min(self
.opcodes
), self
.name
)
818 rhs
= (min(other
.opcodes
), other
.name
)
823 return (self
.static_operands
+ self
.dynamic_operands
)
826 def static_operands(self
):
828 operands
.append(POStaticOperand(record
=self
, value
=self
.PO
))
830 operands
.append(XOStaticOperand(
832 value
=ppc
.opcode
.value
,
833 span
=self
.section
.bitsel
,
835 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
836 operands
.append(cls(record
=self
, **kwargs
))
837 return tuple(operands
)
840 def dynamic_operands(self
):
842 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
843 operands
.append(cls(record
=self
, **kwargs
))
844 return tuple(operands
)
849 return int("".join(str(int(mapping
[bit
])) \
850 for bit
in sorted(mapping
)), 2)
852 def PO_XO(value
, mask
, opcode
, bits
):
855 for (src
, dst
) in enumerate(reversed(bits
)):
856 value
[dst
] = ((opcode
.value
& (1 << src
)) != 0)
857 mask
[dst
] = ((opcode
.mask
& (1 << src
)) != 0)
860 def PO(value
, mask
, opcode
, bits
):
861 return PO_XO(value
=value
, mask
=mask
, opcode
=opcode
, bits
=bits
)
863 def XO(value
, mask
, opcode
, bits
):
864 (value
, mask
) = PO_XO(value
=value
, mask
=mask
,
865 opcode
=opcode
, bits
=bits
)
866 for (op_cls
, op_kwargs
) in self
.mdwn
.operands
.static
:
867 operand
= op_cls(record
=self
, **op_kwargs
)
868 for (src
, dst
) in enumerate(reversed(operand
.span
)):
869 value
[dst
] = ((operand
.value
& (1 << src
)) != 0)
874 value
= {bit
:False for bit
in range(32)}
875 mask
= {bit
:False for bit
in range(32)}
876 if self
.section
.opcode
is not None:
877 (value
, mask
) = PO(value
=value
, mask
=mask
,
878 opcode
=self
.section
.opcode
, bits
=range(0, 6))
880 pairs
.append(XO(value
=value
, mask
=mask
,
881 opcode
=ppc
.opcode
, bits
=self
.section
.bitsel
))
884 for (value
, mask
) in pairs
:
885 value
= Opcode
.Value(binary(value
))
886 mask
= Opcode
.Mask(binary(mask
))
887 result
.append(Opcode(value
=value
, mask
=mask
))
893 opcode
= self
.section
.opcode
895 opcode
= self
.ppc
[0].opcode
896 if isinstance(opcode
, PatternOpcode
):
897 value
= int(opcode
.value
)
898 bits
= opcode
.value
.bit_length()
899 return int(_SelectableInt(value
=value
, bits
=bits
)[0:6])
901 return int(opcode
.value
)
905 return tuple(ppc
.opcode
for ppc
in self
.ppc
)
907 def match(self
, key
):
908 for opcode
in self
.opcodes
:
909 if opcode
.match(key
):
916 return self
.svp64
.mode
936 if self
.svp64
is None:
942 return self
.ppc
.cr_in
946 return self
.ppc
.cr_in2
950 return self
.ppc
.cr_out
952 ptype
= property(lambda self
: self
.svp64
.ptype
)
953 etype
= property(lambda self
: self
.svp64
.etype
)
955 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
956 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
957 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
958 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
959 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
960 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
961 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
962 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
964 def __contains__(self
, key
):
965 return self
.mdwn
.operands
.__contains
__(key
)
967 def __getitem__(self
, key
):
968 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
969 return cls(record
=self
, **kwargs
)
975 return self
["Rc"].value
979 def __init__(self
, record
, name
):
980 self
.__record
= record
984 yield ("record", self
.record
)
985 yield ("name", self
.__name
)
988 return f
"{self.__class__.__name__}({self.name})"
1000 return self
.record
.fields
[self
.name
]
1002 def assemble(self
, insn
):
1003 raise NotImplementedError()
1005 def disassemble(self
, insn
,
1006 style
=Style
.NORMAL
, indent
=""):
1007 raise NotImplementedError()
1010 class DynamicOperand(Operand
):
1011 def assemble(self
, insn
, value
):
1013 if isinstance(value
, str):
1014 value
= int(value
, 0)
1016 raise ValueError("signed operands not allowed")
1019 def disassemble(self
, insn
,
1020 style
=Style
.NORMAL
, indent
=""):
1024 if style
>= Style
.VERBOSE
:
1025 span
= map(str, span
)
1026 yield f
"{indent}{self.name}"
1027 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1028 yield f
"{indent}{indent}{', '.join(span)}"
1030 yield str(int(value
))
1033 class SignedOperand(DynamicOperand
):
1034 def assemble(self
, insn
, value
):
1035 if isinstance(value
, str):
1036 value
= int(value
, 0)
1037 return super().assemble(value
=value
, insn
=insn
)
1039 def assemble(self
, insn
, value
):
1041 if isinstance(value
, str):
1042 value
= int(value
, 0)
1045 def disassemble(self
, insn
,
1046 style
=Style
.NORMAL
, indent
=""):
1048 value
= insn
[span
].to_signed_int()
1049 sign
= "-" if (value
< 0) else ""
1052 if style
>= Style
.VERBOSE
:
1053 span
= map(str, span
)
1054 yield f
"{indent}{self.name}"
1055 yield f
"{indent}{indent}{sign}{value}"
1056 yield f
"{indent}{indent}{', '.join(span)}"
1058 yield f
"{sign}{value}"
1061 class StaticOperand(Operand
):
1062 def __init__(self
, record
, name
, value
):
1063 self
.__value
= value
1064 return super().__init
__(record
=record
, name
=name
)
1067 yield ("value", self
.__value
)
1068 yield from super().__iter
__()
1071 return f
"{self.__class__.__name__}({self.name}, value={self.value})"
1077 def assemble(self
, insn
):
1078 insn
[self
.span
] = self
.value
1080 def disassemble(self
, insn
,
1081 style
=Style
.NORMAL
, indent
=""):
1085 if style
>= Style
.VERBOSE
:
1086 span
= map(str, span
)
1087 yield f
"{indent}{self.name}"
1088 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1089 yield f
"{indent}{indent}{', '.join(span)}"
1091 yield str(int(value
))
1094 class SpanStaticOperand(StaticOperand
):
1095 def __init__(self
, record
, name
, value
, span
):
1096 self
.__span
= tuple(span
)
1097 return super().__init
__(record
=record
, name
=name
, value
=value
)
1100 yield ("span", self
.__span
)
1101 yield from super().__iter
__()
1108 class POStaticOperand(SpanStaticOperand
):
1109 def __init__(self
, record
, value
):
1110 return super().__init
__(record
=record
, name
="PO",
1111 value
=value
, span
=range(0, 6))
1114 for (key
, value
) in super().__iter
__():
1115 if key
not in {"name", "span"}:
1119 class XOStaticOperand(SpanStaticOperand
):
1120 def __init__(self
, record
, value
, span
):
1121 bits
= record
.section
.bitsel
1122 value
= _SelectableInt(value
=value
, bits
=len(bits
))
1123 span
= dict(zip(bits
, range(len(bits
))))
1124 span_rev
= {value
:key
for (key
, value
) in span
.items()}
1126 # This part is tricky: we cannot use record.operands,
1127 # as this code is called by record.static_operands method.
1128 for (cls
, kwargs
) in record
.mdwn
.operands
:
1129 operand
= cls(record
=record
, **kwargs
)
1130 for idx
in operand
.span
:
1131 rev
= span
.pop(idx
, None)
1133 span_rev
.pop(rev
, None)
1135 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1136 span
= tuple(span
.keys())
1138 return super().__init
__(record
=record
, name
="XO",
1139 value
=value
, span
=span
)
1142 for (key
, value
) in super().__iter
__():
1143 if key
not in {"name"}:
1147 class ImmediateOperand(DynamicOperand
):
1151 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1155 class NonZeroOperand(DynamicOperand
):
1156 def assemble(self
, insn
, value
):
1157 if isinstance(value
, str):
1158 value
= int(value
, 0)
1159 if not isinstance(value
, int):
1160 raise ValueError("non-integer operand")
1162 raise ValueError("non-zero operand")
1164 return super().assemble(value
=value
, insn
=insn
)
1166 def disassemble(self
, insn
,
1167 style
=Style
.NORMAL
, indent
=""):
1171 if style
>= Style
.VERBOSE
:
1172 span
= map(str, span
)
1173 yield f
"{indent}{self.name}"
1174 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1175 yield f
"{indent}{indent}{', '.join(span)}"
1177 yield str(int(value
) + 1)
1180 class ExtendableOperand(DynamicOperand
):
1181 def sv_spec_enter(self
, value
, span
):
1182 return (value
, span
)
1184 def sv_spec(self
, insn
):
1188 span
= tuple(map(str, span
))
1190 if isinstance(insn
, SVP64Instruction
):
1191 (origin_value
, origin_span
) = (value
, span
)
1192 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1194 for extra_idx
in self
.extra_idx
:
1195 if self
.record
.etype
is _SVEType
.EXTRA3
:
1196 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1197 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1198 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1200 raise ValueError(self
.record
.etype
)
1203 vector
= bool(spec
[0])
1204 spec_span
= spec
.__class
__
1205 if self
.record
.etype
is _SVEType
.EXTRA3
:
1206 spec_span
= tuple(map(str, spec_span
[1, 2]))
1208 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1209 spec_span
= tuple(map(str, spec_span
[1,]))
1210 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1213 spec_span
= (spec_span
+ ("{0}",))
1215 spec_span
= (("{0}",) + spec_span
)
1217 raise ValueError(self
.record
.etype
)
1219 vector_shift
= (2 + (5 - value
.bits
))
1220 scalar_shift
= value
.bits
1221 spec_shift
= (5 - value
.bits
)
1223 bits
= (len(span
) + len(spec_span
))
1224 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1225 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1227 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1228 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1230 value
= ((spec
<< scalar_shift
) | value
)
1231 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1233 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1234 origin_value
=origin_value
, origin_span
=origin_span
)
1236 return (vector
, value
, span
)
1238 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1239 return (value
, span
)
1242 def extra_idx(self
):
1243 for (key
, record
) in self
.record
.svp64
.extras
.items():
1244 if record
["reg"].alias
is self
.extra_reg
.alias
:
1248 def extra_reg(self
):
1249 return _Reg(self
.name
)
1251 def remap(self
, value
, vector
):
1252 raise NotImplementedError()
1254 def assemble(self
, value
, insn
, prefix
):
1257 if isinstance(value
, str):
1258 value
= value
.lower()
1259 if value
.startswith("%"):
1261 if value
.startswith("*"):
1262 if not isinstance(insn
, SVP64Instruction
):
1263 raise ValueError(value
)
1266 if value
.startswith(prefix
):
1267 if (self
.extra_reg
.or_zero
and (value
== f
"{prefix}0")):
1268 raise ValueError(value
)
1269 value
= value
[len(prefix
):]
1270 value
= int(value
, 0)
1272 if isinstance(insn
, SVP64Instruction
):
1273 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1275 for extra_idx
in self
.extra_idx
:
1276 if self
.record
.etype
is _SVEType
.EXTRA3
:
1277 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1278 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1279 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1281 raise ValueError(self
.record
.etype
)
1283 return super().assemble(value
=value
, insn
=insn
)
1285 def disassemble(self
, insn
,
1286 style
=Style
.NORMAL
, prefix
="", indent
=""):
1287 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1289 if (self
.extra_reg
.or_zero
and (value
== 0)):
1292 if style
>= Style
.VERBOSE
:
1293 mode
= "vector" if vector
else "scalar"
1294 yield f
"{indent}{self.name} ({mode})"
1295 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1296 yield f
"{indent}{indent}{', '.join(span)}"
1297 if isinstance(insn
, SVP64Instruction
):
1298 for extra_idx
in frozenset(self
.extra_idx
):
1299 if self
.record
.etype
is _SVEType
.NONE
:
1300 yield f
"{indent}{indent}extra[none]"
1302 etype
= repr(self
.record
.etype
).lower()
1303 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1305 vector
= "*" if vector
else ""
1306 yield f
"{vector}{prefix}{int(value)}"
1309 class SimpleRegisterOperand(ExtendableOperand
):
1310 def remap(self
, value
, vector
):
1312 extra
= (value
& 0b11)
1313 value
= (value
>> 2)
1315 extra
= (value
>> 5)
1316 value
= (value
& 0b11111)
1318 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1319 # (and shrink to a single bit if ok)
1320 if self
.record
.etype
is _SVEType
.EXTRA2
:
1322 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1323 assert (extra
& 0b01) == 0, \
1324 ("vector field %s cannot fit into EXTRA2" % value
)
1325 extra
= (0b10 |
(extra
>> 1))
1327 # range is r0-r63 in increments of 1
1328 assert (extra
>> 1) == 0, \
1329 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1331 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1333 # EXTRA3 vector bit needs marking
1336 raise ValueError(self
.record
.etype
)
1338 return (value
, extra
)
1341 class GPROperand(SimpleRegisterOperand
):
1342 def assemble(self
, insn
, value
):
1343 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1345 def disassemble(self
, insn
,
1346 style
=Style
.NORMAL
, indent
=""):
1347 prefix
= "" if (style
<= Style
.SHORT
) else "r"
1348 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1349 style
=style
, indent
=indent
)
1352 class GPRPairOperand(GPROperand
):
1356 class FPROperand(SimpleRegisterOperand
):
1357 def assemble(self
, insn
, value
):
1358 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1360 def disassemble(self
, insn
,
1361 style
=Style
.NORMAL
, indent
=""):
1362 prefix
= "" if (style
<= Style
.SHORT
) else "f"
1363 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1364 style
=style
, indent
=indent
)
1367 class FPRPairOperand(FPROperand
):
1371 class ConditionRegisterFieldOperand(ExtendableOperand
):
1372 def pattern(name_pattern
):
1373 (name
, pattern
) = name_pattern
1374 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1383 CR
= r
"(?:CR|cr)([0-9]+)"
1385 BIT
= rf
"({'|'.join(CONDS.keys())})"
1386 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1387 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1388 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1389 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1390 XCR
= fr
"{CR}\.{BIT}"
1391 PATTERNS
= tuple(map(pattern
, (
1396 ("BIT+CR", (LBIT
+ CR
)),
1397 ("CR+BIT", (CR
+ RBIT
)),
1398 ("BIT+CR*N", (LBIT
+ CRN
)),
1399 ("CR*N+BIT", (CRN
+ RBIT
)),
1400 ("BIT+N*CR", (LBIT
+ NCR
)),
1401 ("N*CR+BIT", (NCR
+ RBIT
)),
1404 def remap(self
, value
, vector
, regtype
):
1405 if regtype
is _RegType
.CR_5BIT
:
1406 subvalue
= (value
& 0b11)
1410 extra
= (value
& 0b1111)
1413 extra
= (value
>> 3)
1416 if self
.record
.etype
is _SVEType
.EXTRA2
:
1418 assert (extra
& 0b111) == 0, \
1419 "vector CR cannot fit into EXTRA2"
1420 extra
= (0b10 |
(extra
>> 3))
1422 assert (extra
>> 1) == 0, \
1423 "scalar CR cannot fit into EXTRA2"
1425 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1427 assert (extra
& 0b11) == 0, \
1428 "vector CR cannot fit into EXTRA3"
1429 extra
= (0b100 |
(extra
>> 2))
1431 assert (extra
>> 2) == 0, \
1432 "scalar CR cannot fit into EXTRA3"
1435 if regtype
is _RegType
.CR_5BIT
:
1436 value
= ((value
<< 2) | subvalue
)
1438 return (value
, extra
)
1440 def assemble(self
, insn
, value
):
1441 if isinstance(value
, str):
1444 if value
.startswith("*"):
1445 if not isinstance(insn
, SVP64Instruction
):
1446 raise ValueError(value
)
1450 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1451 match
= pattern
.match(value
)
1452 if match
is not None:
1453 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1454 values
= match
.groups()
1455 match
= dict(zip(keys
, values
))
1456 CR
= int(match
["CR"])
1460 N
= int(match
.get("N", "1"))
1461 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1462 value
= ((CR
* N
) + BIT
)
1469 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1471 def disassemble(self
, insn
,
1472 style
=Style
.NORMAL
, prefix
="", indent
=""):
1473 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1475 if style
>= Style
.VERBOSE
:
1476 mode
= "vector" if vector
else "scalar"
1477 yield f
"{indent}{self.name} ({mode})"
1478 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1479 yield f
"{indent}{indent}{', '.join(span)}"
1480 if isinstance(insn
, SVP64Instruction
):
1481 for extra_idx
in frozenset(self
.extra_idx
):
1482 if self
.record
.etype
is _SVEType
.NONE
:
1483 yield f
"{indent}{indent}extra[none]"
1485 etype
= repr(self
.record
.etype
).lower()
1486 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1488 vector
= "*" if vector
else ""
1489 CR
= int(value
>> 2)
1491 cond
= ("lt", "gt", "eq", "so")[CC
]
1492 if style
>= Style
.NORMAL
:
1494 if isinstance(insn
, SVP64Instruction
):
1495 yield f
"{vector}cr{CR}.{cond}"
1497 yield f
"4*cr{CR}+{cond}"
1501 yield f
"{vector}{prefix}{int(value)}"
1504 class CR3Operand(ConditionRegisterFieldOperand
):
1505 def remap(self
, value
, vector
):
1506 return super().remap(value
=value
, vector
=vector
,
1507 regtype
=_RegType
.CR_3BIT
)
1510 class CR5Operand(ConditionRegisterFieldOperand
):
1511 def remap(self
, value
, vector
):
1512 return super().remap(value
=value
, vector
=vector
,
1513 regtype
=_RegType
.CR_5BIT
)
1515 def sv_spec_enter(self
, value
, span
):
1516 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1517 return (value
, span
)
1519 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1520 value
= _selectconcat(value
, origin_value
[3:5])
1522 return (value
, span
)
1525 class EXTSOperand(SignedOperand
):
1526 field
: str # real name to report
1527 nz
: int = 0 # number of zeros
1528 fmt
: str = "d" # integer formatter
1530 def __init__(self
, record
, name
, field
, nz
=0, fmt
="d"):
1531 self
.__field
= field
1534 return super().__init
__(record
=record
, name
=name
)
1550 return self
.record
.fields
[self
.field
]
1552 def assemble(self
, insn
, value
):
1554 if isinstance(value
, str):
1555 value
= int(value
, 0)
1556 insn
[span
] = (value
>> self
.nz
)
1558 def disassemble(self
, insn
,
1559 style
=Style
.NORMAL
, indent
=""):
1561 value
= insn
[span
].to_signed_int()
1562 sign
= "-" if (value
< 0) else ""
1563 value
= (abs(value
) << self
.nz
)
1565 if style
>= Style
.VERBOSE
:
1566 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1567 zeros
= ("0" * self
.nz
)
1568 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1569 yield f
"{indent * 1}{hint}"
1570 yield f
"{indent * 2}{self.field}"
1571 yield f
"{indent * 3}{sign}{value:{self.fmt}}"
1572 yield f
"{indent * 3}{', '.join(span)}"
1574 yield f
"{sign}{value:{self.fmt}}"
1577 class TargetAddrOperand(EXTSOperand
):
1578 def __init__(self
, record
, name
, field
):
1579 return super().__init
__(record
=record
, name
=name
, field
=field
,
1583 class TargetAddrOperandLI(TargetAddrOperand
):
1584 def __init__(self
, record
, name
):
1585 return super().__init
__(record
=record
, name
=name
, field
="LI")
1588 class TargetAddrOperandBD(TargetAddrOperand
):
1589 def __init__(self
, record
, name
):
1590 return super().__init
__(record
=record
, name
=name
, field
="BD")
1593 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1594 def __init__(self
, record
, name
):
1595 return super().__init
__(record
=record
, name
=name
, field
="DS", nz
=2)
1598 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1599 def __init__(self
, record
, name
):
1600 return super().__init
__(record
=record
, name
=name
, field
="DQ", nz
=4)
1603 class DOperandDX(SignedOperand
):
1606 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1607 operands
= map(cls
, ("d0", "d1", "d2"))
1608 spans
= map(lambda operand
: operand
.span
, operands
)
1609 return sum(spans
, tuple())
1611 def disassemble(self
, insn
,
1612 style
=Style
.NORMAL
, indent
=""):
1614 value
= insn
[span
].to_signed_int()
1615 sign
= "-" if (value
< 0) else ""
1618 if style
>= Style
.VERBOSE
:
1625 for (subname
, subspan
) in mapping
.items():
1626 operand
= DynamicOperand(name
=subname
)
1628 span
= map(str, span
)
1629 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1630 yield f
"{indent}{indent}{indent}{sign}{value}"
1631 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1633 yield f
"{sign}{value}"
1636 class Instruction(_Mapping
):
1638 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1639 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1640 raise ValueError(bits
)
1642 if isinstance(value
, bytes
):
1643 if ((len(value
) * 8) != bits
):
1644 raise ValueError(f
"bit length mismatch")
1645 value
= int.from_bytes(value
, byteorder
=byteorder
)
1647 if isinstance(value
, int):
1648 value
= _SelectableInt(value
=value
, bits
=bits
)
1649 elif isinstance(value
, Instruction
):
1650 value
= value
.storage
1652 if not isinstance(value
, _SelectableInt
):
1653 raise ValueError(value
)
1656 if len(value
) != bits
:
1657 raise ValueError(value
)
1659 value
= _SelectableInt(value
=value
, bits
=bits
)
1661 return cls(storage
=value
)
1664 return hash(int(self
))
1666 def __getitem__(self
, key
):
1667 return self
.storage
.__getitem
__(key
)
1669 def __setitem__(self
, key
, value
):
1670 return self
.storage
.__setitem
__(key
, value
)
1672 def bytes(self
, byteorder
="little"):
1673 nr_bytes
= (len(self
.__class
__) // 8)
1674 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1677 def record(cls
, db
, entry
):
1680 raise KeyError(entry
)
1684 def operands(cls
, record
):
1685 yield from record
.operands
1688 def static_operands(cls
, record
):
1689 return filter(lambda operand
: isinstance(operand
, StaticOperand
),
1690 cls
.operands(record
=record
))
1693 def dynamic_operands(cls
, record
):
1694 return filter(lambda operand
: isinstance(operand
, DynamicOperand
),
1695 cls
.operands(record
=record
))
1697 def spec(self
, record
, prefix
):
1698 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1699 self
.spec_dynamic_operands(record
=record
)))
1701 static_operands
= []
1702 for (name
, value
) in self
.spec_static_operands(record
=record
):
1703 static_operands
.append(f
"{name}={value}")
1706 if dynamic_operands
:
1708 operands
+= ",".join(dynamic_operands
)
1711 operands
+= " ".join(static_operands
)
1713 return f
"{prefix}{record.name}{operands}"
1715 def spec_static_operands(self
, record
):
1716 for operand
in self
.static_operands(record
=record
):
1717 if not isinstance(operand
, (POStaticOperand
, XOStaticOperand
)):
1718 yield (operand
.name
, operand
.value
)
1720 def spec_dynamic_operands(self
, record
, style
=Style
.NORMAL
):
1724 for operand
in self
.dynamic_operands(record
=record
):
1726 value
= " ".join(operand
.disassemble(insn
=self
,
1727 style
=min(style
, Style
.NORMAL
)))
1729 name
= f
"{imm_name}({name})"
1730 value
= f
"{imm_value}({value})"
1732 if isinstance(operand
, ImmediateOperand
):
1740 def assemble(cls
, record
, arguments
=None):
1741 if arguments
is None:
1744 insn
= cls
.integer(value
=0)
1746 for operand
in cls
.static_operands(record
=record
):
1747 operand
.assemble(insn
=insn
)
1749 arguments
= Arguments(record
=record
,
1750 arguments
=arguments
, operands
=cls
.dynamic_operands(record
=record
))
1751 for (value
, operand
) in arguments
:
1752 operand
.assemble(insn
=insn
, value
=value
)
1756 def disassemble(self
, record
,
1758 style
=Style
.NORMAL
):
1759 raise NotImplementedError()
1762 class WordInstruction(Instruction
):
1763 _
: _Field
= range(0, 32)
1764 PO
: _Field
= range(0, 6)
1767 def integer(cls
, value
, byteorder
="little"):
1768 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1773 for idx
in range(32):
1774 bit
= int(self
[idx
])
1776 return "".join(map(str, bits
))
1778 def disassemble(self
, record
,
1780 style
=Style
.NORMAL
):
1781 if style
<= Style
.SHORT
:
1784 blob
= self
.bytes(byteorder
=byteorder
)
1785 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1789 yield f
"{blob}.long 0x{int(self):08x}"
1792 # awful temporary hack: workaround for ld-update
1793 # https://bugs.libre-soc.org/show_bug.cgi?id=1056#c2
1794 # XXX TODO must check that *EXTENDED* RA != extended-RT
1795 if (record
.svp64
is not None and
1796 record
.mode
== _SVMode
.LDST_IMM
and
1797 'u' in record
.name
):
1798 yield f
"{blob}.long 0x{int(self):08x}"
1802 if style
is Style
.LEGACY
:
1804 for operand
in self
.dynamic_operands(record
=record
):
1805 if isinstance(operand
, (GPRPairOperand
, FPRPairOperand
)):
1808 if style
is Style
.LEGACY
and (paired
or record
.ppc
.unofficial
):
1809 yield f
"{blob}.long 0x{int(self):08x}"
1811 operands
= tuple(map(_operator
.itemgetter(1),
1812 self
.spec_dynamic_operands(record
=record
, style
=style
)))
1814 operands
= ",".join(operands
)
1815 yield f
"{blob}{record.name} {operands}"
1817 yield f
"{blob}{record.name}"
1819 if style
>= Style
.VERBOSE
:
1821 binary
= self
.binary
1822 spec
= self
.spec(record
=record
, prefix
="")
1823 yield f
"{indent}spec"
1824 yield f
"{indent}{indent}{spec}"
1825 yield f
"{indent}pcode"
1826 for stmt
in record
.mdwn
.pcode
:
1827 yield f
"{indent}{indent}{stmt}"
1828 yield f
"{indent}binary"
1829 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1830 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1831 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1832 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1833 yield f
"{indent}opcodes"
1834 for opcode
in record
.opcodes
:
1835 yield f
"{indent}{indent}{opcode!r}"
1836 for operand
in self
.operands(record
=record
):
1837 yield from operand
.disassemble(insn
=self
,
1838 style
=style
, indent
=indent
)
1842 class PrefixedInstruction(Instruction
):
1843 class Prefix(WordInstruction
.remap(range(0, 32))):
1846 class Suffix(WordInstruction
.remap(range(32, 64))):
1849 _
: _Field
= range(64)
1855 def integer(cls
, value
, byteorder
="little"):
1856 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
1859 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
1860 def transform(value
):
1861 return WordInstruction
.integer(value
=value
,
1862 byteorder
=byteorder
)[0:32]
1864 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
1865 value
= _selectconcat(prefix
, suffix
)
1867 return super().integer(bits
=64, value
=value
)
1870 class Mode(_Mapping
):
1871 _
: _Field
= range(0, 5)
1872 sel
: _Field
= (0, 1)
1875 class Extra(_Mapping
):
1876 _
: _Field
= range(0, 9)
1879 class Extra2(Extra
):
1880 idx0
: _Field
= range(0, 2)
1881 idx1
: _Field
= range(2, 4)
1882 idx2
: _Field
= range(4, 6)
1883 idx3
: _Field
= range(6, 8)
1885 def __getitem__(self
, key
):
1891 _SVExtra
.Idx0
: self
.idx0
,
1892 _SVExtra
.Idx1
: self
.idx1
,
1893 _SVExtra
.Idx2
: self
.idx2
,
1894 _SVExtra
.Idx3
: self
.idx3
,
1897 def __setitem__(self
, key
, value
):
1898 self
[key
].assign(value
)
1901 class Extra3(Extra
):
1902 idx0
: _Field
= range(0, 3)
1903 idx1
: _Field
= range(3, 6)
1904 idx2
: _Field
= range(6, 9)
1906 def __getitem__(self
, key
):
1911 _SVExtra
.Idx0
: self
.idx0
,
1912 _SVExtra
.Idx1
: self
.idx1
,
1913 _SVExtra
.Idx2
: self
.idx2
,
1916 def __setitem__(self
, key
, value
):
1917 self
[key
].assign(value
)
1920 class BaseRM(_Mapping
):
1921 _
: _Field
= range(24)
1922 mmode
: _Field
= (0,)
1923 mask
: _Field
= range(1, 4)
1924 elwidth
: _Field
= range(4, 6)
1925 ewsrc
: _Field
= range(6, 8)
1926 subvl
: _Field
= range(8, 10)
1927 mode
: Mode
.remap(range(19, 24))
1928 smask
: _Field
= range(16, 19)
1929 extra
: Extra
.remap(range(10, 19))
1930 extra2
: Extra2
.remap(range(10, 19))
1931 extra3
: Extra3
.remap(range(10, 19))
1933 def specifiers(self
, record
):
1934 subvl
= int(self
.subvl
)
1942 def disassemble(self
, style
=Style
.NORMAL
):
1943 if style
>= Style
.VERBOSE
:
1945 for (name
, span
) in self
.traverse(path
="RM"):
1946 value
= self
.storage
[span
]
1948 yield f
"{indent}{int(value):0{value.bits}b}"
1949 yield f
"{indent}{', '.join(map(str, span))}"
1952 class FFRc1BaseRM(BaseRM
):
1953 def specifiers(self
, record
, mode
):
1954 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
1955 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
1956 mask
= int(_selectconcat(CR
, inv
))
1957 predicate
= PredicateBaseRM
.predicate(True, mask
)
1958 yield f
"{mode}={predicate}"
1960 yield from super().specifiers(record
=record
)
1963 class FFRc0BaseRM(BaseRM
):
1964 def specifiers(self
, record
, mode
):
1966 inv
= "~" if self
.inv
else ""
1967 yield f
"{mode}={inv}RC1"
1969 yield from super().specifiers(record
=record
)
1972 class SatBaseRM(BaseRM
):
1973 def specifiers(self
, record
):
1979 yield from super().specifiers(record
=record
)
1982 class ZZBaseRM(BaseRM
):
1983 def specifiers(self
, record
):
1987 yield from super().specifiers(record
=record
)
1990 class ZZCombinedBaseRM(BaseRM
):
1991 def specifiers(self
, record
):
1992 if self
.sz
and self
.dz
:
1999 yield from super().specifiers(record
=record
)
2002 class DZBaseRM(BaseRM
):
2003 def specifiers(self
, record
):
2007 yield from super().specifiers(record
=record
)
2010 class SZBaseRM(BaseRM
):
2011 def specifiers(self
, record
):
2015 yield from super().specifiers(record
=record
)
2018 class MRBaseRM(BaseRM
):
2019 def specifiers(self
, record
):
2025 yield from super().specifiers(record
=record
)
2028 class ElsBaseRM(BaseRM
):
2029 def specifiers(self
, record
):
2033 yield from super().specifiers(record
=record
)
2036 class WidthBaseRM(BaseRM
):
2038 def width(FP
, width
):
2047 width
= ("fp" + width
)
2050 def specifiers(self
, record
):
2051 # elwidths: use "w=" if same otherwise dw/sw
2052 # FIXME this should consider FP instructions
2054 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
2055 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2056 if record
.svp64
.mode
is _SVMode
.CROP
:
2060 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2069 yield from super().specifiers(record
=record
)
2072 class PredicateBaseRM(BaseRM
):
2074 def predicate(CR
, mask
):
2077 (False, 0b001): "1<<r3",
2078 (False, 0b010): "r3",
2079 (False, 0b011): "~r3",
2080 (False, 0b100): "r10",
2081 (False, 0b101): "~r10",
2082 (False, 0b110): "r30",
2083 (False, 0b111): "~r30",
2085 (True, 0b000): "lt",
2086 (True, 0b001): "ge",
2087 (True, 0b010): "gt",
2088 (True, 0b011): "le",
2089 (True, 0b100): "eq",
2090 (True, 0b101): "ne",
2091 (True, 0b110): "so",
2092 (True, 0b111): "ns",
2095 def specifiers(self
, record
):
2096 # predication - single and twin
2097 # use "m=" if same otherwise sm/dm
2098 CR
= (int(self
.mmode
) == 1)
2099 mask
= int(self
.mask
)
2100 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
2101 if record
.svp64
.ptype
is _SVPType
.P2
:
2102 smask
= int(self
.smask
)
2103 sm
= PredicateBaseRM
.predicate(CR
, smask
)
2112 yield from super().specifiers(record
=record
)
2115 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
2119 class SEABaseRM(BaseRM
):
2120 def specifiers(self
, record
):
2124 yield from super().specifiers(record
=record
)
2127 class VLiBaseRM(BaseRM
):
2128 def specifiers(self
, record
):
2132 yield from super().specifiers(record
=record
)
2135 class NormalBaseRM(PredicateWidthBaseRM
):
2138 https://libre-soc.org/openpower/sv/normal/
2143 class NormalSimpleRM(ZZCombinedBaseRM
, NormalBaseRM
):
2144 """normal: simple mode"""
2148 def specifiers(self
, record
):
2149 yield from super().specifiers(record
=record
)
2152 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
2153 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
2157 class NormalFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, NormalBaseRM
):
2158 """normal: Rc=1: ffirst CR sel"""
2161 CR
: BaseRM
.mode
[3, 4]
2163 def specifiers(self
, record
):
2164 yield from super().specifiers(record
=record
, mode
="ff")
2167 class NormalFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
2168 """normal: Rc=0: ffirst z/nonz"""
2173 def specifiers(self
, record
):
2174 yield from super().specifiers(record
=record
, mode
="ff")
2177 class NormalSatRM(SatBaseRM
, ZZCombinedBaseRM
, NormalBaseRM
):
2178 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2184 class NormalRM(NormalBaseRM
):
2185 simple
: NormalSimpleRM
2187 ffrc1
: NormalFFRc1RM
2188 ffrc0
: NormalFFRc0RM
2192 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2194 LD/ST Immediate mode
2195 https://libre-soc.org/openpower/sv/ldst/
2200 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2201 """ld/st immediate: simple mode"""
2202 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2203 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2209 def specifiers(self
, record
):
2215 yield from super().specifiers(record
=record
)
2218 class LDSTFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2219 """ld/st immediate&indexed: Rc=1: ffirst CR sel"""
2222 CR
: BaseRM
.mode
[3, 4]
2224 def specifiers(self
, record
):
2225 yield from super().specifiers(record
=record
, mode
="ff")
2228 class LDSTFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2229 """ld/st immediate&indexed: Rc=0: ffirst z/nonz"""
2234 def specifiers(self
, record
):
2235 yield from super().specifiers(record
=record
, mode
="ff")
2238 class LDSTImmRM(LDSTImmBaseRM
):
2239 simple
: LDSTImmSimpleRM
2244 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2247 https://libre-soc.org/openpower/sv/ldst/
2252 class LDSTIdxSimpleRM(SEABaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2253 """ld/st index: simple mode (includes element-strided and Signed-EA)"""
2254 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2261 def specifiers(self
, record
):
2267 yield from super().specifiers(record
=record
)
2270 class LDSTIdxRM(LDSTIdxBaseRM
):
2271 simple
: LDSTIdxSimpleRM
2277 class CROpBaseRM(BaseRM
):
2280 https://libre-soc.org/openpower/sv/cr_ops/
2285 class CROpSimpleRM(PredicateBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2286 """crop: simple mode"""
2291 def specifiers(self
, record
):
2293 yield "rg" # simple CR Mode reports /rg
2295 yield from super().specifiers(record
=record
)
2298 class CROpMRRM(MRBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2299 """crop: scalar reduce mode (mapreduce)"""
2305 class CROpFF5RM(FFRc0BaseRM
, PredicateBaseRM
, VLiBaseRM
, DZBaseRM
,
2306 SZBaseRM
, CROpBaseRM
):
2307 """crop: ffirst 5-bit mode"""
2314 def specifiers(self
, record
):
2315 yield from super().specifiers(record
=record
, mode
="ff")
2318 # FIXME: almost everything in this class contradicts the specs (it doesn't)
2319 # The modes however are swapped: 5-bit is 3-bit, 3-bit is 5-bit
2320 class CROpFF3RM(FFRc1BaseRM
, PredicateBaseRM
, VLiBaseRM
, ZZBaseRM
, CROpBaseRM
):
2321 """cr_op: ffirst 3-bit mode"""
2327 def specifiers(self
, record
):
2328 yield from super().specifiers(record
=record
, mode
="ff")
2331 class CROpRM(CROpBaseRM
):
2332 simple
: CROpSimpleRM
2338 # ********************
2340 # https://libre-soc.org/openpower/sv/branches/
2341 class BranchBaseRM(BaseRM
):
2351 def specifiers(self
, record
):
2363 raise ValueError(self
.sz
)
2375 # Branch modes lack source mask.
2376 # Therefore a custom code is needed.
2377 CR
= (int(self
.mmode
) == 1)
2378 mask
= int(self
.mask
)
2379 m
= PredicateBaseRM
.predicate(CR
, mask
)
2383 yield from super().specifiers(record
=record
)
2386 class BranchSimpleRM(BranchBaseRM
):
2387 """branch: simple mode"""
2391 class BranchVLSRM(BranchBaseRM
):
2392 """branch: VLSET mode"""
2396 def specifiers(self
, record
):
2402 }[int(self
.VSb
), int(self
.VLi
)]
2404 yield from super().specifiers(record
=record
)
2407 class BranchCTRRM(BranchBaseRM
):
2408 """branch: CTR-test mode"""
2411 def specifiers(self
, record
):
2417 yield from super().specifiers(record
=record
)
2420 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2421 """branch: CTR-test+VLSET mode"""
2425 class BranchRM(BranchBaseRM
):
2426 simple
: BranchSimpleRM
2429 ctrvls
: BranchCTRVLSRM
2440 @_dataclasses.dataclass(eq
=True, frozen
=True)
2445 def match(cls
, desc
, record
):
2446 raise NotImplementedError()
2448 def validate(self
, others
):
2451 def assemble(self
, insn
):
2452 raise NotImplementedError()
2455 @_dataclasses.dataclass(eq
=True, frozen
=True)
2456 class SpecifierWidth(Specifier
):
2460 def match(cls
, desc
, record
, etalon
):
2461 (mode
, _
, value
) = desc
.partition("=")
2463 value
= value
.strip()
2466 width
= _SVP64Width(value
)
2468 return cls(record
=record
, width
=width
)
2471 @_dataclasses.dataclass(eq
=True, frozen
=True)
2472 class SpecifierW(SpecifierWidth
):
2474 def match(cls
, desc
, record
):
2475 return super().match(desc
=desc
, record
=record
, etalon
="w")
2477 def assemble(self
, insn
):
2478 selector
= insn
.select(record
=self
.record
)
2479 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2480 selector
.ewsrc
= self
.width
.value
2481 selector
.elwidth
= self
.width
.value
2484 @_dataclasses.dataclass(eq
=True, frozen
=True)
2485 class SpecifierSW(SpecifierWidth
):
2487 def match(cls
, desc
, record
):
2488 if record
.svp64
.mode
is _SVMode
.CROP
:
2490 return super().match(desc
=desc
, record
=record
, etalon
="sw")
2492 def assemble(self
, insn
):
2493 selector
= insn
.select(record
=self
.record
)
2494 selector
.ewsrc
= self
.width
.value
2497 @_dataclasses.dataclass(eq
=True, frozen
=True)
2498 class SpecifierDW(SpecifierWidth
):
2500 def match(cls
, desc
, record
):
2501 return super().match(desc
=desc
, record
=record
, etalon
="dw")
2503 def assemble(self
, insn
):
2504 selector
= insn
.select(record
=self
.record
)
2505 selector
.elwidth
= self
.width
.value
2508 @_dataclasses.dataclass(eq
=True, frozen
=True)
2509 class SpecifierSubVL(Specifier
):
2513 def match(cls
, desc
, record
):
2515 value
= _SVP64SubVL(desc
)
2519 return cls(record
=record
, value
=value
)
2521 def assemble(self
, insn
):
2522 selector
= insn
.select(record
=self
.record
)
2523 selector
.subvl
= int(self
.value
.value
)
2526 @_dataclasses.dataclass(eq
=True, frozen
=True)
2527 class SpecifierPredicate(Specifier
):
2532 def match(cls
, desc
, record
, mode_match
, pred_match
):
2533 (mode
, _
, pred
) = desc
.partition("=")
2536 if not mode_match(mode
):
2539 pred
= _SVP64Pred(pred
.strip())
2540 if not pred_match(pred
):
2541 raise ValueError(pred
)
2543 return cls(record
=record
, mode
=mode
, pred
=pred
)
2546 @_dataclasses.dataclass(eq
=True, frozen
=True)
2547 class SpecifierFF(SpecifierPredicate
):
2549 def match(cls
, desc
, record
):
2550 return super().match(desc
=desc
, record
=record
,
2551 mode_match
=lambda mode_arg
: mode_arg
== "ff",
2552 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2557 def assemble(self
, insn
):
2558 selector
= insn
.select(record
=self
.record
)
2559 if selector
.mode
.sel
!= 0:
2560 raise ValueError("cannot override mode")
2561 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2562 selector
.mode
.sel
= 0b01
2563 # HACK: please finally provide correct logic for CRs.
2564 if self
.pred
in (_SVP64Pred
.RC1
, _SVP64Pred
.RC1_N
):
2565 selector
.mode
[2] = (self
.pred
is _SVP64Pred
.RC1_N
)
2567 selector
.mode
[2] = self
.pred
.inv
2568 selector
.mode
[3, 4] = self
.pred
.state
2570 selector
.mode
.sel
= 0b01 if self
.mode
== "ff" else 0b11
2571 selector
.inv
= self
.pred
.inv
2573 selector
.CR
= self
.pred
.state
2575 selector
.RC1
= self
.pred
.state
2578 @_dataclasses.dataclass(eq
=True, frozen
=True)
2579 class SpecifierMask(SpecifierPredicate
):
2581 def match(cls
, desc
, record
, mode
):
2582 return super().match(desc
=desc
, record
=record
,
2583 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2584 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2589 def assemble(self
, insn
):
2590 raise NotImplementedError()
2593 @_dataclasses.dataclass(eq
=True, frozen
=True)
2594 class SpecifierM(SpecifierMask
):
2596 def match(cls
, desc
, record
):
2597 return super().match(desc
=desc
, record
=record
, mode
="m")
2599 def validate(self
, others
):
2601 if isinstance(spec
, SpecifierSM
):
2602 raise ValueError("source-mask and predicate mask conflict")
2603 elif isinstance(spec
, SpecifierDM
):
2604 raise ValueError("dest-mask and predicate mask conflict")
2606 def assemble(self
, insn
):
2607 selector
= insn
.select(record
=self
.record
)
2608 selector
.mask
= int(self
.pred
)
2609 if ((self
.record
.ptype
is _SVPType
.P2
) and
2610 (self
.record
.svp64
.mode
is not _SVMode
.BRANCH
)):
2611 selector
.smask
= int(self
.pred
)
2612 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2615 @_dataclasses.dataclass(eq
=True, frozen
=True)
2616 class SpecifierSM(SpecifierMask
):
2618 def match(cls
, desc
, record
):
2619 return super().match(desc
=desc
, record
=record
, mode
="sm")
2621 def validate(self
, others
):
2622 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2623 raise ValueError("source-mask on non-twin predicate")
2625 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2628 if isinstance(spec
, SpecifierDM
):
2632 raise ValueError("missing dest-mask in CR twin predication")
2633 if self
.pred
.mode
!= twin
.pred
.mode
:
2634 raise ValueError(f
"predicate masks mismatch: "
2635 f
"{self.pred!r} vs {twin.pred!r}")
2637 def assemble(self
, insn
):
2638 selector
= insn
.select(record
=self
.record
)
2639 selector
.smask
= int(self
.pred
)
2640 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2643 @_dataclasses.dataclass(eq
=True, frozen
=True)
2644 class SpecifierDM(SpecifierMask
):
2646 def match(cls
, desc
, record
):
2647 return super().match(desc
=desc
, record
=record
, mode
="dm")
2649 def validate(self
, others
):
2650 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2651 raise ValueError("dest-mask on non-twin predicate")
2653 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2656 if isinstance(spec
, SpecifierSM
):
2660 raise ValueError("missing source-mask in CR twin predication")
2661 if self
.pred
.mode
!= twin
.pred
.mode
:
2662 raise ValueError(f
"predicate masks mismatch: "
2663 f
"{self.pred!r} vs {twin.pred!r}")
2665 def assemble(self
, insn
):
2666 selector
= insn
.select(record
=self
.record
)
2667 selector
.mask
= int(self
.pred
)
2668 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2671 @_dataclasses.dataclass(eq
=True, frozen
=True)
2672 class SpecifierZZ(Specifier
):
2674 def match(cls
, desc
, record
):
2678 return cls(record
=record
)
2680 def validate(self
, others
):
2682 # Since zz takes precedence (overrides) sz and dz,
2683 # treat them as mutually exclusive.
2684 if isinstance(spec
, (SpecifierSZ
, SpecifierDZ
)):
2685 raise ValueError("mutually exclusive predicate masks")
2687 def assemble(self
, insn
):
2688 selector
= insn
.select(record
=self
.record
)
2689 if hasattr(selector
, "zz"): # this should be done in a different way
2696 @_dataclasses.dataclass(eq
=True, frozen
=True)
2697 class SpecifierXZ(Specifier
):
2699 hint
: str = _dataclasses
.field(repr=False)
2702 def match(cls
, desc
, record
, etalon
, hint
):
2706 return cls(desc
=desc
, record
=record
, hint
=hint
)
2708 def validate(self
, others
):
2709 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2710 raise ValueError(f
"{self.hint} on non-twin predicate")
2712 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2715 if isinstance(spec
, SpecifierXZ
):
2719 raise ValueError(f
"missing {self.hint} in CR twin predication")
2720 if self
.pred
!= twin
.pred
:
2721 raise ValueError(f
"predicate masks mismatch: "
2722 f
"{self.pred!r} vs {twin.pred!r}")
2724 def assemble(self
, insn
):
2725 selector
= insn
.select(record
=self
.record
)
2726 setattr(selector
, self
.desc
, 1)
2729 @_dataclasses.dataclass(eq
=True, frozen
=True)
2730 class SpecifierSZ(SpecifierXZ
):
2732 def match(cls
, desc
, record
):
2733 return super().match(desc
=desc
, record
=record
,
2734 etalon
="sz", hint
="source-mask")
2736 def validate(self
, others
):
2738 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2739 if isinstance(spec
, SpecifierFF
):
2740 raise ValueError("source-zero not allowed in ff mode")
2743 @_dataclasses.dataclass(eq
=True, frozen
=True)
2744 class SpecifierDZ(SpecifierXZ
):
2746 def match(cls
, desc
, record
):
2747 return super().match(desc
=desc
, record
=record
,
2748 etalon
="dz", hint
="dest-mask")
2750 def validate(self
, others
):
2752 if ((self
.record
.svp64
.mode
is not _SVMode
.CROP
) and
2753 isinstance(spec
, SpecifierFF
) and
2754 (spec
.pred
.mode
is _SVP64PredMode
.RC1
)):
2755 raise ValueError(f
"dest-zero not allowed in ff mode BO")
2758 @_dataclasses.dataclass(eq
=True, frozen
=True)
2759 class SpecifierEls(Specifier
):
2761 def match(cls
, desc
, record
):
2765 if record
.svp64
.mode
not in (_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
):
2766 raise ValueError("els is only valid in ld/st modes, not "
2767 "%s" % str(self
.record
.svp64
.mode
))
2769 return cls(record
=record
)
2771 def assemble(self
, insn
):
2772 if self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
: # stride mode
2773 insn
.prefix
.rm
.mode
[1] = 0
2775 selector
= insn
.select(record
=self
.record
)
2780 @_dataclasses.dataclass(eq
=True, frozen
=True)
2781 class SpecifierSEA(Specifier
):
2783 def match(cls
, desc
, record
):
2787 return cls(record
=record
)
2789 def validate(self
, others
):
2790 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
:
2791 raise ValueError("sea is only valid in ld/st modes, not "
2792 "%s" % str(self
.record
.svp64
.mode
))
2795 if isinstance(spec
, SpecifierFF
):
2796 raise ValueError(f
"sea cannot be used in ff mode")
2798 def assemble(self
, insn
):
2799 selector
= insn
.select(record
=self
.record
)
2800 if selector
.mode
.sel
not in (0b10, 0b00):
2801 raise ValueError("sea is only valid for normal and els modes, "
2802 "not %d" % int(selector
.mode
.sel
))
2806 @_dataclasses.dataclass(eq
=True, frozen
=True)
2807 class SpecifierSat(Specifier
):
2812 def match(cls
, desc
, record
, etalon
, sign
):
2816 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.LDST_IMM
,
2818 raise ValueError("only normal, ld/st imm and "
2819 "ld/st idx modes supported")
2821 return cls(record
=record
, desc
=desc
, sign
=sign
)
2823 def assemble(self
, insn
):
2824 selector
= insn
.select(record
=self
.record
)
2825 selector
.mode
[0] = 0b1
2826 selector
.mode
[1] = 0b0
2827 selector
.N
= int(self
.sign
)
2830 @_dataclasses.dataclass(eq
=True, frozen
=True)
2831 class SpecifierSatS(SpecifierSat
):
2833 def match(cls
, desc
, record
):
2834 return super().match(desc
=desc
, record
=record
,
2835 etalon
="sats", sign
=True)
2838 @_dataclasses.dataclass(eq
=True, frozen
=True)
2839 class SpecifierSatU(SpecifierSat
):
2841 def match(cls
, desc
, record
):
2842 return super().match(desc
=desc
, record
=record
,
2843 etalon
="satu", sign
=False)
2846 @_dataclasses.dataclass(eq
=True, frozen
=True)
2847 class SpecifierMapReduce(Specifier
):
2851 def match(cls
, record
, RG
):
2852 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2853 raise ValueError("only normal and crop modes supported")
2855 return cls(record
=record
, RG
=RG
)
2857 def assemble(self
, insn
):
2858 selector
= insn
.select(record
=self
.record
)
2859 if self
.record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2860 raise ValueError("only normal and crop modes supported")
2861 selector
.mode
[0] = 0
2862 selector
.mode
[1] = 0
2863 selector
.mode
[2] = 1
2864 selector
.RG
= self
.RG
2867 @_dataclasses.dataclass(eq
=True, frozen
=True)
2868 class SpecifierMR(SpecifierMapReduce
):
2870 def match(cls
, desc
, record
):
2874 return super().match(record
=record
, RG
=False)
2877 @_dataclasses.dataclass(eq
=True, frozen
=True)
2878 class SpecifierMRR(SpecifierMapReduce
):
2880 def match(cls
, desc
, record
):
2884 return super().match(record
=record
, RG
=True)
2887 @_dataclasses.dataclass(eq
=True, frozen
=True)
2888 class SpecifierBranch(Specifier
):
2890 def match(cls
, desc
, record
, etalon
):
2894 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
2895 raise ValueError("only branch modes supported")
2897 return cls(record
=record
)
2900 @_dataclasses.dataclass(eq
=True, frozen
=True)
2901 class SpecifierAll(SpecifierBranch
):
2903 def match(cls
, desc
, record
):
2904 return super().match(desc
=desc
, record
=record
, etalon
="all")
2906 def assemble(self
, insn
):
2907 selector
= insn
.select(record
=self
.record
)
2911 @_dataclasses.dataclass(eq
=True, frozen
=True)
2912 class SpecifierSNZ(Specifier
):
2914 def match(cls
, desc
, record
):
2918 if record
.svp64
.mode
not in (_SVMode
.BRANCH
, _SVMode
.CROP
):
2919 raise ValueError("only branch and crop modes supported")
2921 return cls(record
=record
)
2923 def assemble(self
, insn
):
2924 selector
= insn
.select(record
=self
.record
)
2925 if self
.record
.svp64
.mode
in (_SVMode
.CROP
, _SVMode
.BRANCH
):
2927 if self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
2930 raise ValueError("only branch and crop modes supported")
2933 @_dataclasses.dataclass(eq
=True, frozen
=True)
2934 class SpecifierSL(SpecifierBranch
):
2936 def match(cls
, desc
, record
):
2937 return super().match(desc
=desc
, record
=record
, etalon
="sl")
2939 def assemble(self
, insn
):
2940 selector
= insn
.select(record
=self
.record
)
2944 @_dataclasses.dataclass(eq
=True, frozen
=True)
2945 class SpecifierSLu(SpecifierBranch
):
2947 def match(cls
, desc
, record
):
2948 return super().match(desc
=desc
, record
=record
, etalon
="slu")
2950 def assemble(self
, insn
):
2951 selector
= insn
.select(record
=self
.record
)
2955 @_dataclasses.dataclass(eq
=True, frozen
=True)
2956 class SpecifierLRu(SpecifierBranch
):
2958 def match(cls
, desc
, record
):
2959 return super().match(desc
=desc
, record
=record
, etalon
="lru")
2961 def assemble(self
, insn
):
2962 selector
= insn
.select(record
=self
.record
)
2966 @_dataclasses.dataclass(eq
=True, frozen
=True)
2967 class SpecifierVSXX(SpecifierBranch
):
2972 def match(cls
, desc
, record
, etalon
, VSb
, VLi
):
2976 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
2977 raise ValueError("only branch modes supported")
2979 return cls(record
=record
, VSb
=VSb
, VLi
=VLi
)
2981 def assemble(self
, insn
):
2982 selector
= insn
.select(record
=self
.record
)
2984 selector
.VSb
= int(self
.VSb
)
2985 selector
.VLi
= int(self
.VLi
)
2988 @_dataclasses.dataclass(eq
=True, frozen
=True)
2989 class SpecifierVS(SpecifierVSXX
):
2991 def match(cls
, desc
, record
):
2992 return super().match(desc
=desc
, record
=record
,
2993 etalon
="vs", VSb
=False, VLi
=False)
2996 @_dataclasses.dataclass(eq
=True, frozen
=True)
2997 class SpecifierVSi(SpecifierVSXX
):
2999 def match(cls
, desc
, record
):
3000 return super().match(desc
=desc
, record
=record
,
3001 etalon
="vsi", VSb
=False, VLi
=True)
3004 @_dataclasses.dataclass(eq
=True, frozen
=True)
3005 class SpecifierVSb(SpecifierVSXX
):
3007 def match(cls
, desc
, record
):
3008 return super().match(desc
=desc
, record
=record
,
3009 etalon
="vsb", VSb
=True, VLi
=False)
3012 @_dataclasses.dataclass(eq
=True, frozen
=True)
3013 class SpecifierVSbi(SpecifierVSXX
):
3015 def match(cls
, desc
, record
):
3016 return super().match(desc
=desc
, record
=record
,
3017 etalon
="vsbi", VSb
=True, VLi
=True)
3020 @_dataclasses.dataclass(eq
=True, frozen
=True)
3021 class SpecifierCTX(Specifier
):
3025 def match(cls
, desc
, record
, etalon
, CTi
):
3029 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3030 raise ValueError("only branch modes supported")
3032 return cls(record
=record
, CTi
=CTi
)
3034 def assemble(self
, insn
):
3035 selector
= insn
.select(record
=self
.record
)
3037 selector
.CTi
= int(self
.CTi
)
3040 @_dataclasses.dataclass(eq
=True, frozen
=True)
3041 class SpecifierCTR(SpecifierCTX
):
3043 def match(cls
, desc
, record
):
3044 return super().match(desc
=desc
, record
=record
,
3045 etalon
="ctr", CTi
=False)
3048 @_dataclasses.dataclass(eq
=True, frozen
=True)
3049 class SpecifierCTi(SpecifierCTX
):
3051 def match(cls
, desc
, record
):
3052 return super().match(desc
=desc
, record
=record
,
3053 etalon
="cti", CTi
=True)
3056 @_dataclasses.dataclass(eq
=True, frozen
=True)
3057 class SpecifierPI(Specifier
):
3059 def match(cls
, desc
, record
):
3063 if record
.svp64
.mode
not in [_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
]:
3064 raise ValueError("only ld/st imm/idx mode supported")
3066 return cls(record
=record
)
3068 def assemble(self
, insn
):
3069 selector
= insn
.select(record
=self
.record
)
3070 selector
.mode
[2] = 0b1
3074 @_dataclasses.dataclass(eq
=True, frozen
=True)
3075 class SpecifierLF(Specifier
):
3077 def match(cls
, desc
, record
):
3081 if record
.svp64
.mode
is not _SVMode
.LDST_IMM
:
3082 raise ValueError("only ld/st imm mode supported")
3084 return cls(record
=record
)
3086 def assemble(self
, insn
):
3087 selector
= insn
.select(record
=self
.record
)
3088 selector
.mode
[1] = 0
3092 @_dataclasses.dataclass(eq
=True, frozen
=True)
3093 class SpecifierVLi(Specifier
):
3095 def match(cls
, desc
, record
):
3099 return cls(record
=record
)
3101 def validate(self
, others
):
3103 if isinstance(spec
, SpecifierFF
):
3106 raise ValueError("VLi only allowed in failfirst")
3108 def assemble(self
, insn
):
3109 selector
= insn
.select(record
=self
.record
)
3110 selector
.mode
[1] = 1
3114 class Specifiers(tuple):
3149 def __new__(cls
, items
, record
):
3150 def transform(item
):
3151 for spec_cls
in cls
.SPECS
:
3152 spec
= spec_cls
.match(item
, record
=record
)
3153 if spec
is not None:
3155 raise ValueError(item
)
3157 # TODO: remove this hack
3158 items
= dict.fromkeys(items
)
3162 items
= tuple(items
)
3164 specs
= tuple(map(transform
, items
))
3165 for (index
, spec
) in enumerate(specs
):
3166 head
= specs
[:index
]
3167 tail
= specs
[index
+ 1:]
3168 spec
.validate(others
=(head
+ tail
))
3170 return super().__new
__(cls
, specs
)
3173 class SVP64OperandMeta(type):
3174 class SVP64NonZeroOperand(NonZeroOperand
):
3175 def assemble(self
, insn
, value
):
3176 if isinstance(value
, str):
3177 value
= int(value
, 0)
3178 if not isinstance(value
, int):
3179 raise ValueError("non-integer operand")
3181 # FIXME: this is really weird
3182 if self
.record
.name
in ("svstep", "svstep."):
3183 value
+= 1 # compensation
3185 return super().assemble(value
=value
, insn
=insn
)
3187 class SVP64XOStaticOperand(SpanStaticOperand
):
3188 def __init__(self
, record
, value
, span
):
3189 return super().__init
__(record
=record
, name
="XO",
3190 value
=value
, span
=span
)
3193 NonZeroOperand
: SVP64NonZeroOperand
,
3194 XOStaticOperand
: SVP64XOStaticOperand
,
3197 def __new__(metacls
, name
, bases
, ns
):
3199 for (index
, base_cls
) in enumerate(bases
):
3200 bases
[index
] = metacls
.__TRANSFORM
.get(base_cls
, base_cls
)
3202 bases
= tuple(bases
)
3204 return super().__new
__(metacls
, name
, bases
, ns
)
3207 class SVP64Operand(Operand
, metaclass
=SVP64OperandMeta
):
3210 return tuple(map(lambda bit
: (bit
+ 32), super().span
))
3214 def __init__(self
, insn
, record
):
3216 self
.__record
= record
3217 return super().__init
__()
3220 return self
.rm
.__doc
__
3223 return repr(self
.rm
)
3231 return self
.__record
3235 rm
= getattr(self
.insn
.prefix
.rm
, self
.record
.svp64
.mode
.name
.lower())
3237 # The idea behind these tables is that they are now literally
3238 # in identical format to insndb.csv and minor_xx.csv and can
3239 # be done precisely as that. The only thing to watch out for
3240 # is the insertion of Rc=1 as a "mask/value" bit and likewise
3241 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
3244 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
3245 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3246 # mode Rc mask Rc member
3248 (0b000000, 0b111000, "simple"), # simple (no Rc)
3249 (0b001000, 0b111100, "mr"), # mapreduce (no Rc)
3250 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3251 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3252 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3253 (0b001100, 0b111100, "rsvd"), # reserved
3255 mode
= int(self
.insn
.prefix
.rm
.normal
.mode
)
3256 search
= ((mode
<< 1) | self
.record
.Rc
)
3258 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
3259 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3260 # mode Rc mask Rc member
3261 # ironically/coincidentally this table is identical to NORMAL
3262 # mode except reserved in place of mr
3264 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3265 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3266 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3268 search
= ((int(self
.insn
.prefix
.rm
.ldst_imm
.mode
) << 1) |
3271 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
3272 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3273 # mode Rc mask Rc member
3275 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3276 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3277 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3279 search
= ((int(self
.insn
.prefix
.rm
.ldst_idx
.mode
) << 1) |
3282 elif self
.record
.svp64
.mode
is _SVMode
.CROP
:
3283 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
3284 # mode 3b mask 3b member
3286 (0b000000, 0b111000, "simple"), # simple
3287 (0b001000, 0b111000, "mr"), # mapreduce
3288 (0b010001, 0b010001, "ff3"), # ffirst, 3-bit CR
3289 (0b010000, 0b010000, "ff5"), # ffirst, 5-bit CR
3291 search
= ((int(self
.insn
.prefix
.rm
.crop
.mode
) << 1) |
3292 int(self
.record
.svp64
.extra_CR_3bit
))
3294 elif self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3298 (0b00, 0b11, "simple"), # simple
3299 (0b01, 0b11, "vls"), # VLset
3300 (0b10, 0b11, "ctr"), # CTR mode
3301 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
3303 # slightly weird: doesn't have a 5-bit "mode" field like others
3304 search
= int(self
.insn
.prefix
.rm
.branch
.mode
.sel
)
3307 if table
is not None:
3308 for (value
, mask
, field
) in table
:
3309 if field
.startswith("rsvd"):
3311 if ((value
& mask
) == (search
& mask
)):
3312 return getattr(rm
, field
)
3316 def __getattr__(self
, key
):
3317 if key
.startswith(f
"_{self.__class__.__name__}__"):
3318 return super().__getattribute
__(key
)
3320 return getattr(self
.rm
, key
)
3322 def __setattr__(self
, key
, value
):
3323 if key
.startswith(f
"_{self.__class__.__name__}__"):
3324 return super().__setattr
__(key
, value
)
3327 if not hasattr(rm
, key
):
3328 raise AttributeError(key
)
3330 return setattr(rm
, key
, value
)
3333 class SVP64Instruction(PrefixedInstruction
):
3334 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
3335 class Prefix(PrefixedInstruction
.Prefix
):
3337 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
3341 def select(self
, record
):
3342 return RMSelector(insn
=self
, record
=record
)
3347 for idx
in range(64):
3348 bit
= int(self
[idx
])
3350 return "".join(map(str, bits
))
3353 def assemble(cls
, record
, arguments
=None, specifiers
=None):
3354 insn
= super().assemble(record
=record
, arguments
=arguments
)
3356 specifiers
= Specifiers(items
=specifiers
, record
=record
)
3357 for specifier
in specifiers
:
3358 specifier
.assemble(insn
=insn
)
3360 insn
.prefix
.PO
= 0x1
3361 insn
.prefix
.id = 0x3
3365 def disassemble(self
, record
,
3367 style
=Style
.NORMAL
):
3369 if style
<= Style
.SHORT
:
3372 blob
= insn
.bytes(byteorder
=byteorder
)
3373 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
3376 blob_prefix
= blob(self
.prefix
)
3377 blob_suffix
= blob(self
.suffix
)
3379 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3380 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
3383 assert record
.svp64
is not None
3385 name
= f
"sv.{record.name}"
3387 rm
= self
.select(record
=record
)
3389 # convert specifiers to /x/y/z (sorted lexicographically)
3390 specifiers
= sorted(rm
.specifiers(record
=record
))
3391 if specifiers
: # if any add one extra to get the extra "/"
3392 specifiers
= ([""] + specifiers
)
3393 specifiers
= "/".join(specifiers
)
3395 # convert operands to " ,x,y,z"
3396 operands
= tuple(map(_operator
.itemgetter(1),
3397 self
.spec_dynamic_operands(record
=record
, style
=style
)))
3398 operands
= ",".join(operands
)
3399 if len(operands
) > 0: # if any separate with a space
3400 operands
= (" " + operands
)
3402 if style
<= Style
.LEGACY
:
3403 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3404 suffix
= WordInstruction
.integer(value
=int(self
.suffix
))
3405 yield from suffix
.disassemble(record
=record
,
3406 byteorder
=byteorder
, style
=style
)
3408 yield f
"{blob_prefix}{name}{specifiers}{operands}"
3410 yield f
"{blob_suffix}"
3412 if style
>= Style
.VERBOSE
:
3414 binary
= self
.binary
3415 spec
= self
.spec(record
=record
, prefix
="sv.")
3417 yield f
"{indent}spec"
3418 yield f
"{indent}{indent}{spec}"
3419 yield f
"{indent}pcode"
3420 for stmt
in record
.mdwn
.pcode
:
3421 yield f
"{indent}{indent}{stmt}"
3422 yield f
"{indent}binary"
3423 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
3424 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
3425 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
3426 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
3427 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
3428 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
3429 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
3430 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
3431 yield f
"{indent}opcodes"
3432 for opcode
in record
.opcodes
:
3433 yield f
"{indent}{indent}{opcode!r}"
3434 for operand
in self
.operands(record
=record
):
3435 yield from operand
.disassemble(insn
=self
,
3436 style
=style
, indent
=indent
)
3438 yield f
"{indent}{indent}{str(rm)}"
3439 for line
in rm
.disassemble(style
=style
):
3440 yield f
"{indent}{indent}{line}"
3444 def operands(cls
, record
):
3445 for operand
in super().operands(record
=record
):
3446 parent
= operand
.__class
__
3447 name
= f
"SVP64{parent.__name__}"
3448 bases
= (SVP64Operand
, parent
)
3449 child
= type(name
, bases
, {})
3450 yield child(**dict(operand
))
3453 def parse(stream
, factory
):
3455 return ("TODO" not in frozenset(entry
.values()))
3457 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
3458 entries
= _csv
.DictReader(lines
)
3459 entries
= filter(match
, entries
)
3460 return tuple(map(factory
, entries
))
3463 class MarkdownDatabase
:
3466 for (name
, desc
) in _ISA():
3469 (dynamic
, *static
) = desc
.regs
3470 operands
.extend(dynamic
)
3471 operands
.extend(static
)
3472 pcode
= PCode(iterable
=filter(str.strip
, desc
.pcode
))
3473 operands
= Operands(insn
=name
, operands
=operands
)
3474 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
3476 self
.__db
= dict(sorted(db
.items()))
3478 return super().__init
__()
3481 yield from self
.__db
.items()
3483 def __contains__(self
, key
):
3484 return self
.__db
.__contains
__(key
)
3486 def __getitem__(self
, key
):
3487 return self
.__db
.__getitem
__(key
)
3490 class FieldsDatabase
:
3493 df
= _DecodeFields()
3495 for (form
, fields
) in df
.instrs
.items():
3496 if form
in {"DQE", "TX"}:
3500 db
[_Form
[form
]] = Fields(fields
)
3504 return super().__init
__()
3506 def __getitem__(self
, key
):
3507 return self
.__db
.__getitem
__(key
)
3511 def __init__(self
, root
, mdwndb
):
3512 # The code below groups the instructions by name:section.
3513 # There can be multiple names for the same instruction.
3514 # The point is to capture different opcodes for the same instruction.
3516 records
= _collections
.defaultdict(set)
3517 path
= (root
/ "insndb.csv")
3518 with
open(path
, "r", encoding
="UTF-8") as stream
:
3519 for section
in sorted(parse(stream
, Section
.CSV
)):
3520 path
= (root
/ section
.path
)
3522 section
.Mode
.INTEGER
: IntegerOpcode
,
3523 section
.Mode
.PATTERN
: PatternOpcode
,
3525 factory
= _functools
.partial(
3526 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
3527 with
open(path
, "r", encoding
="UTF-8") as stream
:
3528 for insn
in parse(stream
, factory
):
3529 for name
in insn
.names
:
3530 records
[name
].add(insn
)
3531 sections
[name
] = section
3533 items
= sorted(records
.items())
3535 for (name
, multirecord
) in items
:
3536 records
[name
] = PPCMultiRecord(sorted(multirecord
))
3538 def exact_match(name
):
3539 record
= records
.get(name
)
3545 if not name
.endswith("l"):
3547 alias
= exact_match(name
[:-1])
3550 record
= records
[alias
]
3551 if "lk" not in record
.flags
:
3552 raise ValueError(record
)
3556 if not name
.endswith("a"):
3558 alias
= LK_match(name
[:-1])
3561 record
= records
[alias
]
3562 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
3563 raise ValueError(record
)
3564 if "AA" not in mdwndb
[name
].operands
:
3565 raise ValueError(record
)
3569 if not name
.endswith("."):
3571 alias
= exact_match(name
[:-1])
3574 record
= records
[alias
]
3575 if record
.Rc
is _RCOE
.NONE
:
3576 raise ValueError(record
)
3580 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
3581 for (name
, _
) in mdwndb
:
3582 if name
.startswith("sv."):
3585 for match
in matches
:
3587 if alias
is not None:
3591 section
= sections
[alias
]
3592 record
= records
[alias
]
3593 db
[name
] = (section
, record
)
3595 self
.__db
= dict(sorted(db
.items()))
3597 return super().__init
__()
3599 @_functools.lru_cache(maxsize
=512, typed
=False)
3600 def __getitem__(self
, key
):
3601 return self
.__db
.get(key
, (None, None))
3604 class SVP64Database
:
3605 def __init__(self
, root
, ppcdb
):
3607 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
3608 for (prefix
, _
, names
) in _os
.walk(root
):
3609 prefix
= _pathlib
.Path(prefix
)
3610 for name
in filter(lambda name
: pattern
.match(name
), names
):
3611 path
= (prefix
/ _pathlib
.Path(name
))
3612 with
open(path
, "r", encoding
="UTF-8") as stream
:
3613 db
.update(parse(stream
, SVP64Record
.CSV
))
3614 db
= {record
.name
:record
for record
in db
}
3616 self
.__db
= dict(sorted(db
.items()))
3617 self
.__ppcdb
= ppcdb
3619 return super().__init
__()
3621 def __getitem__(self
, key
):
3622 (_
, record
) = self
.__ppcdb
[key
]
3626 for name
in record
.names
:
3627 record
= self
.__db
.get(name
, None)
3628 if record
is not None:
3635 def __init__(self
, root
):
3636 root
= _pathlib
.Path(root
)
3637 mdwndb
= MarkdownDatabase()
3638 fieldsdb
= FieldsDatabase()
3639 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
3640 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
3644 opcodes
= _collections
.defaultdict(
3645 lambda: _collections
.defaultdict(set))
3647 for (name
, mdwn
) in mdwndb
:
3648 if name
.startswith("sv."):
3650 (section
, ppc
) = ppcdb
[name
]
3653 svp64
= svp64db
[name
]
3654 fields
= fieldsdb
[ppc
.form
]
3655 record
= Record(name
=name
,
3656 section
=section
, ppc
=ppc
, svp64
=svp64
,
3657 mdwn
=mdwn
, fields
=fields
)
3659 names
[record
.name
] = record
3660 opcodes
[section
][record
.PO
].add(record
)
3662 self
.__db
= sorted(db
)
3663 self
.__names
= dict(sorted(names
.items()))
3664 self
.__opcodes
= dict(sorted(opcodes
.items()))
3666 return super().__init
__()
3669 return repr(self
.__db
)
3672 yield from self
.__db
3674 @_functools.lru_cache(maxsize
=None)
3675 def __contains__(self
, key
):
3676 return self
.__getitem
__(key
) is not None
3678 @_functools.lru_cache(maxsize
=None)
3679 def __getitem__(self
, key
):
3680 if isinstance(key
, SVP64Instruction
):
3683 if isinstance(key
, Instruction
):
3686 sections
= sorted(self
.__opcodes
)
3687 for section
in sections
:
3688 group
= self
.__opcodes
[section
]
3689 for record
in group
[PO
]:
3690 if record
.match(key
=key
):
3695 elif isinstance(key
, str):
3696 return self
.__names
.get(key
)
3698 raise ValueError("instruction or name expected")