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 def subnodes(self
, match
=None):
64 @_dataclasses.dataclass(eq
=True, frozen
=True)
66 def subnodes(self
, match
=None):
68 match
= lambda subnode
: True
71 return getattr(self
, field
.name
)
73 yield from filter(match
, map(subnode
, _dataclasses
.fields()))
77 @_contextlib.contextmanager
78 def __call__(self
, node
):
82 def walk(root
, match
=None):
83 nodes
= _collections
.deque([root
])
85 node
= nodes
.popleft()
86 nodes
.extend(node
.subnodes(match
=match
))
90 def visit(visitor
, node
):
91 with
visitor(node
=node
):
92 for subnode
in node
.subnodes():
93 visit(visitor
=visitor
, node
=subnode
)
96 @_functools.total_ordering
97 class Style(_enum
.Enum
):
100 NORMAL
= _enum
.auto()
101 VERBOSE
= _enum
.auto()
103 def __lt__(self
, other
):
104 if not isinstance(other
, self
.__class
__):
105 return NotImplemented
106 return (self
.value
< other
.value
)
109 @_functools.total_ordering
110 class Priority(_enum
.Enum
):
116 def _missing_(cls
, value
):
117 if isinstance(value
, str):
118 value
= value
.upper()
122 return super()._missing
_(value
)
124 def __lt__(self
, other
):
125 if not isinstance(other
, self
.__class
__):
126 return NotImplemented
128 # NOTE: the order is inversed, LOW < NORMAL < HIGH
129 return (self
.value
> other
.value
)
132 def dataclass(cls
, record
, keymap
=None, typemap
=None):
136 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
138 def transform(key_value
):
139 (key
, value
) = key_value
140 key
= keymap
.get(key
, key
)
141 hook
= typemap
.get(key
, lambda value
: value
)
142 if hook
is bool and value
in ("", "0"):
148 record
= dict(map(transform
, record
.items()))
149 for key
in frozenset(record
.keys()):
150 if record
[key
] == "":
156 @_functools.total_ordering
157 @_dataclasses.dataclass(eq
=True, frozen
=True)
160 def __new__(cls
, value
):
161 if isinstance(value
, str):
162 value
= int(value
, 0)
163 if not isinstance(value
, int):
164 raise ValueError(value
)
166 if value
.bit_length() > 64:
167 raise ValueError(value
)
169 return super().__new
__(cls
, value
)
172 return self
.__repr
__()
175 return f
"{self:0{self.bit_length()}b}"
177 def bit_length(self
):
178 if super().bit_length() > 32:
182 class Value(Integer
):
191 def __lt__(self
, other
):
192 if not isinstance(other
, Opcode
):
193 return NotImplemented
194 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
197 return (self
.value
& self
.mask
)
200 return int(self
).__index
__()
203 def pattern(value
, mask
, bit_length
):
204 for bit
in range(bit_length
):
205 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
207 elif (value
& (1 << (bit_length
- bit
- 1))):
212 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
214 def match(self
, key
):
215 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
218 @_functools.total_ordering
219 @_dataclasses.dataclass(eq
=True, frozen
=True)
220 class IntegerOpcode(Opcode
):
221 def __init__(self
, value
):
222 if value
.startswith("0b"):
223 mask
= int(("1" * len(value
[2:])), 2)
227 value
= Opcode
.Value(value
)
228 mask
= Opcode
.Mask(mask
)
230 return super().__init
__(value
=value
, mask
=mask
)
233 @_functools.total_ordering
234 @_dataclasses.dataclass(eq
=True, frozen
=True)
235 class PatternOpcode(Opcode
):
236 def __init__(self
, pattern
):
237 if not isinstance(pattern
, str):
238 raise ValueError(pattern
)
240 (value
, mask
) = (0, 0)
241 for symbol
in pattern
:
242 if symbol
not in {"0", "1", "-"}:
243 raise ValueError(pattern
)
244 value |
= (symbol
== "1")
245 mask |
= (symbol
!= "-")
251 value
= Opcode
.Value(value
)
252 mask
= Opcode
.Mask(mask
)
254 return super().__init
__(value
=value
, mask
=mask
)
257 @_dataclasses.dataclass(eq
=True, frozen
=True)
259 class FlagsMeta(type):
274 class Flags(tuple, metaclass
=FlagsMeta
):
275 def __new__(cls
, flags
=frozenset()):
276 flags
= frozenset(flags
)
277 diff
= (flags
- frozenset(cls
))
279 raise ValueError(flags
)
280 return super().__new
__(cls
, sorted(flags
))
284 flags
: Flags
= Flags()
286 function
: _Function
= _Function
.NONE
287 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
288 in1
: _In1Sel
= _In1Sel
.NONE
289 in2
: _In2Sel
= _In2Sel
.NONE
290 in3
: _In3Sel
= _In3Sel
.NONE
291 out
: _OutSel
= _OutSel
.NONE
292 cr_in
: _CRInSel
= _CRInSel
.NONE
293 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
294 cr_out
: _CROutSel
= _CROutSel
.NONE
295 cry_in
: _CryIn
= _CryIn
.ZERO
296 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
297 upd
: _LDSTMode
= _LDSTMode
.NONE
298 Rc
: _RCOE
= _RCOE
.NONE
299 form
: _Form
= _Form
.NONE
301 unofficial
: bool = False
305 "internal op": "intop",
309 "ldst len": "ldst_len",
311 "CONDITIONS": "conditions",
314 def __lt__(self
, other
):
315 if not isinstance(other
, self
.__class
__):
316 return NotImplemented
317 lhs
= (self
.opcode
, self
.comment
)
318 rhs
= (other
.opcode
, other
.comment
)
322 def CSV(cls
, record
, opcode_cls
):
323 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
324 typemap
["opcode"] = opcode_cls
326 if record
["CR in"] == "BA_BB":
327 record
["cr_in"] = "BA"
328 record
["cr_in2"] = "BB"
332 for flag
in frozenset(PPCRecord
.Flags
):
333 if bool(record
.pop(flag
, "")):
335 record
["flags"] = PPCRecord
.Flags(flags
)
337 return dataclass(cls
, record
,
338 keymap
=PPCRecord
.__KEYMAP
,
343 return frozenset(self
.comment
.split("=")[-1].split("/"))
346 class PPCMultiRecord(tuple):
347 def __getattr__(self
, attr
):
350 raise AttributeError(attr
)
351 return getattr(self
[0], attr
)
354 @_dataclasses.dataclass(eq
=True, frozen
=True)
356 class ExtraMap(tuple):
358 @_dataclasses.dataclass(eq
=True, frozen
=True)
360 seltype
: _SelType
= _SelType
.NONE
361 reg
: _Reg
= _Reg
.NONE
364 return f
"{self.seltype.value}:{self.reg.name}"
366 def __new__(cls
, value
="0"):
367 if isinstance(value
, str):
368 def transform(value
):
369 (seltype
, reg
) = value
.split(":")
370 seltype
= _SelType(seltype
)
372 return cls
.Entry(seltype
=seltype
, reg
=reg
)
377 value
= map(transform
, value
.split(";"))
379 return super().__new
__(cls
, value
)
382 return repr(list(self
))
384 def __new__(cls
, value
=tuple()):
388 return super().__new
__(cls
, map(cls
.Extra
, value
))
391 return repr({index
:self
[index
] for index
in range(0, 4)})
394 ptype
: _SVPType
= _SVPType
.NONE
395 etype
: _SVEType
= _SVEType
.NONE
396 msrc
: _SVMaskSrc
= _SVMaskSrc
.NO
# MASK_SRC is active
397 in1
: _In1Sel
= _In1Sel
.NONE
398 in2
: _In2Sel
= _In2Sel
.NONE
399 in3
: _In3Sel
= _In3Sel
.NONE
400 out
: _OutSel
= _OutSel
.NONE
401 out2
: _OutSel
= _OutSel
.NONE
402 cr_in
: _CRInSel
= _CRInSel
.NONE
403 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
404 cr_out
: _CROutSel
= _CROutSel
.NONE
405 extra
: ExtraMap
= ExtraMap()
407 mode
: _SVMode
= _SVMode
.NORMAL
411 "CONDITIONS": "conditions",
420 def CSV(cls
, record
):
421 record
["insn"] = record
["insn"].split("=")[-1]
423 for key
in frozenset({
424 "in1", "in2", "in3", "CR in",
425 "out", "out2", "CR out",
431 if record
["CR in"] == "BA_BB":
432 record
["cr_in"] = "BA"
433 record
["cr_in2"] = "BB"
437 for idx
in range(0, 4):
438 extra
.append(record
.pop(f
"{idx}"))
440 record
["extra"] = cls
.ExtraMap(extra
)
442 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
447 "in1", "in2", "in3", "cr_in", "cr_in2",
448 "out", "out2", "cr_out",
463 for index
in range(0, 4):
464 for entry
in self
.extra
[index
]:
465 extras
[entry
.seltype
][entry
.reg
] = idxmap
[index
]
467 for (seltype
, regs
) in extras
.items():
468 idx
= regs
.get(reg
, _SVExtra
.NONE
)
469 if idx
is not _SVExtra
.NONE
:
470 yield (reg
, seltype
, idx
)
477 # has the word "in", it is a SelType.SRC "out" -> DST
478 # in1/2/3 and CR in are SRC, and must match only against "s:NN"
479 # out/out1 and CR out are DST, and must match only against "d:NN"
480 keytype
= _SelType
.SRC
if ("in" in key
) else _SelType
.DST
481 sel
= sels
[key
] = getattr(self
, key
)
482 reg
= regs
[key
] = _Reg(sel
)
483 seltypes
[key
] = _SelType
.NONE
484 idxs
[key
] = _SVExtra
.NONE
485 for (reg
, seltype
, idx
) in extra(reg
.alias
):
486 if keytype
!= seltype
: # only check SRC-to-SRC and DST-to-DST
488 if idx
!= idxs
[key
] and idxs
[key
] is not _SVExtra
.NONE
:
489 raise ValueError(idx
)
492 seltypes
[key
] = seltype
494 if sels
["cr_in"] is _CRInSel
.BA_BB
:
495 sels
["cr_in"] = _CRIn2Sel
.BA
496 sels
["cr_in2"] = _CRIn2Sel
.BB
497 idxs
["cr_in2"] = idxs
["cr_in"]
498 for key
in ("cr_in", "cr_in2"):
499 regs
[key
] = _Reg(sels
[key
])
500 seltype
[key
] = _SelType
.SRC
507 "seltype": seltypes
[key
],
511 return _types
.MappingProxyType(records
)
513 extra_idx_in1
= property(lambda self
: self
.extras
["in1"]["idx"])
514 extra_idx_in2
= property(lambda self
: self
.extras
["in2"]["idx"])
515 extra_idx_in3
= property(lambda self
: self
.extras
["in3"]["idx"])
516 extra_idx_out
= property(lambda self
: self
.extras
["out"]["idx"])
517 extra_idx_out2
= property(lambda self
: self
.extras
["out2"]["idx"])
518 extra_idx_cr_in
= property(lambda self
: self
.extras
["cr_in"]["idx"])
519 extra_idx_cr_in2
= property(lambda self
: self
.extras
["cr_in2"]["idx"])
520 extra_idx_cr_out
= property(lambda self
: self
.extras
["cr_out"]["idx"])
525 for idx
in range(0, 4):
526 for entry
in self
.extra
[idx
]:
527 if entry
.seltype
is _SelType
.DST
:
528 if extra
is not None:
529 raise ValueError(self
.svp64
)
533 if _RegType(extra
.reg
) not in (_RegType
.CR_3BIT
, _RegType
.CR_5BIT
):
534 raise ValueError(self
.svp64
)
539 def extra_CR_3bit(self
):
540 return (_RegType(self
.extra_CR
.reg
) is _RegType
.CR_3BIT
)
544 def __init__(self
, value
=(0, 32)):
545 if isinstance(value
, str):
546 (start
, end
) = map(int, value
.split(":"))
549 if start
< 0 or end
< 0 or start
>= end
:
550 raise ValueError(value
)
555 return super().__init
__()
558 return (self
.__end
- self
.__start
+ 1)
561 return f
"[{self.__start}:{self.__end}]"
564 yield from range(self
.start
, (self
.end
+ 1))
566 def __reversed__(self
):
567 return tuple(reversed(tuple(self
)))
578 @_dataclasses.dataclass(eq
=True, frozen
=True)
580 class Mode(_enum
.Enum
):
581 INTEGER
= _enum
.auto()
582 PATTERN
= _enum
.auto()
585 def _missing_(cls
, value
):
586 if isinstance(value
, str):
587 return cls
[value
.upper()]
588 return super()._missing
_(value
)
591 def __new__(cls
, value
=None):
592 if isinstance(value
, str):
593 if value
.upper() == "NONE":
596 value
= int(value
, 0)
600 return super().__new
__(cls
, value
)
606 return (bin(self
) if self
else "None")
612 opcode
: IntegerOpcode
= None
613 priority
: Priority
= Priority
.NORMAL
615 def __lt__(self
, other
):
616 if not isinstance(other
, self
.__class
__):
617 return NotImplemented
618 return (self
.priority
< other
.priority
)
621 def CSV(cls
, record
):
622 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
623 if record
["opcode"] == "NONE":
624 typemap
["opcode"] = lambda _
: None
626 return dataclass(cls
, record
, typemap
=typemap
)
630 def __init__(self
, items
):
631 if isinstance(items
, dict):
632 items
= items
.items()
635 (name
, bitrange
) = item
636 return (name
, tuple(bitrange
.values()))
638 self
.__mapping
= dict(map(transform
, items
))
640 return super().__init
__()
643 return repr(self
.__mapping
)
646 yield from self
.__mapping
.items()
648 def __contains__(self
, key
):
649 return self
.__mapping
.__contains
__(key
)
651 def __getitem__(self
, key
):
652 return self
.__mapping
.get(key
, None)
667 def __init__(self
, insn
, operands
):
669 "b": {"target_addr": TargetAddrOperandLI
},
670 "ba": {"target_addr": TargetAddrOperandLI
},
671 "bl": {"target_addr": TargetAddrOperandLI
},
672 "bla": {"target_addr": TargetAddrOperandLI
},
673 "bc": {"target_addr": TargetAddrOperandBD
},
674 "bca": {"target_addr": TargetAddrOperandBD
},
675 "bcl": {"target_addr": TargetAddrOperandBD
},
676 "bcla": {"target_addr": TargetAddrOperandBD
},
677 "addpcis": {"D": DOperandDX
},
678 "fishmv": {"D": DOperandDX
},
679 "fmvis": {"D": DOperandDX
},
682 "SVi": NonZeroOperand
,
683 "SVd": NonZeroOperand
,
684 "SVxd": NonZeroOperand
,
685 "SVyd": NonZeroOperand
,
686 "SVzd": NonZeroOperand
,
688 "D": SignedImmediateOperand
,
692 "SIM": SignedOperand
,
693 "SVD": SignedOperand
,
694 "SVDS": SignedOperand
,
695 "RSp": GPRPairOperand
,
696 "RTp": GPRPairOperand
,
697 "FRAp": FPRPairOperand
,
698 "FRBp": FPRPairOperand
,
699 "FRSp": FPRPairOperand
,
700 "FRTp": FPRPairOperand
,
702 custom_immediates
= {
708 for operand
in operands
:
712 (name
, value
) = operand
.split("=")
713 mapping
[name
] = (StaticOperand
, {
719 if name
.endswith(")"):
720 name
= name
.replace("(", " ").replace(")", "")
721 (imm_name
, _
, name
) = name
.partition(" ")
725 if imm_name
is not None:
726 imm_cls
= custom_immediates
.get(imm_name
, ImmediateOperand
)
728 if insn
in custom_insns
and name
in custom_insns
[insn
]:
729 cls
= custom_insns
[insn
][name
]
730 elif name
in custom_fields
:
731 cls
= custom_fields
[name
]
732 elif name
in _Reg
.__members
__:
734 if reg
in self
.__class
__.__GPR
_PAIRS
:
736 elif reg
in self
.__class
__.__FPR
_PAIRS
:
739 regtype
= _RegType
[name
]
740 if regtype
is _RegType
.GPR
:
742 elif regtype
is _RegType
.FPR
:
744 elif regtype
is _RegType
.CR_3BIT
:
746 elif regtype
is _RegType
.CR_5BIT
:
749 if imm_name
is not None:
750 mapping
[imm_name
] = (imm_cls
, {"name": imm_name
})
751 mapping
[name
] = (cls
, {"name": name
})
755 for (name
, (cls
, kwargs
)) in mapping
.items():
756 kwargs
= dict(kwargs
)
757 kwargs
["name"] = name
758 if issubclass(cls
, StaticOperand
):
759 static
.append((cls
, kwargs
))
760 elif issubclass(cls
, DynamicOperand
):
761 dynamic
.append((cls
, kwargs
))
763 raise ValueError(name
)
765 self
.__mapping
= mapping
766 self
.__static
= tuple(static
)
767 self
.__dynamic
= tuple(dynamic
)
769 return super().__init
__()
772 for (_
, items
) in self
.__mapping
.items():
773 (cls
, kwargs
) = items
777 return self
.__mapping
.__repr
__()
779 def __contains__(self
, key
):
780 return self
.__mapping
.__contains
__(key
)
782 def __getitem__(self
, key
):
783 return self
.__mapping
.__getitem
__(key
)
791 return self
.__dynamic
794 class Arguments(tuple):
795 def __new__(cls
, record
, arguments
, operands
):
796 operands
= iter(tuple(operands
))
797 arguments
= iter(tuple(arguments
))
802 operand
= next(operands
)
803 except StopIteration:
807 argument
= next(arguments
)
808 except StopIteration:
809 raise ValueError("operands count mismatch")
811 if isinstance(operand
, ImmediateOperand
):
812 argument
= argument
.replace("(", " ").replace(")", "")
813 (imm_argument
, _
, argument
) = argument
.partition(" ")
815 (imm_operand
, operand
) = (operand
, next(operands
))
816 except StopIteration:
817 raise ValueError("operands count mismatch")
818 items
.append((imm_argument
, imm_operand
))
819 items
.append((argument
, operand
))
823 except StopIteration:
826 raise ValueError("operands count mismatch")
828 return super().__new
__(cls
, items
)
832 def __init__(self
, iterable
):
833 self
.__pcode
= tuple(iterable
)
834 return super().__init
__()
837 yield from self
.__pcode
840 return self
.__pcode
.__repr
__()
843 @_dataclasses.dataclass(eq
=True, frozen
=True)
844 class MarkdownRecord
:
849 @_dataclasses.dataclass(eq
=True, frozen
=True)
853 _In1Sel
, _In2Sel
, _In3Sel
, _CRInSel
, _CRIn2Sel
,
861 @_functools.total_ordering
862 @_dataclasses.dataclass(eq
=True, frozen
=True)
869 svp64
: SVP64Record
= None
871 def subnodes(self
, match
=None):
873 for (name
, fields
) in self
.extras
.items():
874 extras
.append(Extra(name
=name
, **fields
))
875 yield from filter(match
, extras
)
879 if self
.svp64
is not None:
880 return self
.svp64
.extras
882 return _types
.MappingProxyType({})
886 return self
.mdwn
.pcode
888 def __lt__(self
, other
):
889 if not isinstance(other
, Record
):
890 return NotImplemented
891 lhs
= (min(self
.opcodes
), self
.name
)
892 rhs
= (min(other
.opcodes
), other
.name
)
897 return (self
.static_operands
+ self
.dynamic_operands
)
900 def static_operands(self
):
902 operands
.append(POStaticOperand(record
=self
, value
=self
.PO
))
904 operands
.append(XOStaticOperand(
906 value
=ppc
.opcode
.value
,
907 span
=self
.section
.bitsel
,
909 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
910 operands
.append(cls(record
=self
, **kwargs
))
911 return tuple(operands
)
914 def dynamic_operands(self
):
916 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
917 operands
.append(cls(record
=self
, **kwargs
))
918 return tuple(operands
)
923 return int("".join(str(int(mapping
[bit
])) \
924 for bit
in sorted(mapping
)), 2)
926 def PO_XO(value
, mask
, opcode
, bits
):
929 for (src
, dst
) in enumerate(reversed(bits
)):
930 value
[dst
] = ((opcode
.value
& (1 << src
)) != 0)
931 mask
[dst
] = ((opcode
.mask
& (1 << src
)) != 0)
934 def PO(value
, mask
, opcode
, bits
):
935 return PO_XO(value
=value
, mask
=mask
, opcode
=opcode
, bits
=bits
)
937 def XO(value
, mask
, opcode
, bits
):
938 (value
, mask
) = PO_XO(value
=value
, mask
=mask
,
939 opcode
=opcode
, bits
=bits
)
940 for (op_cls
, op_kwargs
) in self
.mdwn
.operands
.static
:
941 operand
= op_cls(record
=self
, **op_kwargs
)
942 for (src
, dst
) in enumerate(reversed(operand
.span
)):
943 value
[dst
] = ((operand
.value
& (1 << src
)) != 0)
948 value
= {bit
:False for bit
in range(32)}
949 mask
= {bit
:False for bit
in range(32)}
950 if self
.section
.opcode
is not None:
951 (value
, mask
) = PO(value
=value
, mask
=mask
,
952 opcode
=self
.section
.opcode
, bits
=range(0, 6))
954 pairs
.append(XO(value
=value
, mask
=mask
,
955 opcode
=ppc
.opcode
, bits
=self
.section
.bitsel
))
958 for (value
, mask
) in pairs
:
959 value
= Opcode
.Value(binary(value
))
960 mask
= Opcode
.Mask(binary(mask
))
961 result
.append(Opcode(value
=value
, mask
=mask
))
967 opcode
= self
.section
.opcode
969 opcode
= self
.ppc
[0].opcode
970 if isinstance(opcode
, PatternOpcode
):
971 value
= int(opcode
.value
)
972 bits
= opcode
.value
.bit_length()
973 return int(_SelectableInt(value
=value
, bits
=bits
)[0:6])
975 return int(opcode
.value
)
979 return tuple(ppc
.opcode
for ppc
in self
.ppc
)
981 def match(self
, key
):
982 for opcode
in self
.opcodes
:
983 if opcode
.match(key
):
990 return self
.svp64
.mode
1010 if self
.svp64
is None:
1016 return self
.ppc
.cr_in
1020 return self
.ppc
.cr_in2
1024 return self
.ppc
.cr_out
1026 ptype
= property(lambda self
: self
.svp64
.ptype
)
1027 etype
= property(lambda self
: self
.svp64
.etype
)
1029 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
1030 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
1031 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
1032 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
1033 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
1034 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
1035 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
1036 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
1038 def __contains__(self
, key
):
1039 return self
.mdwn
.operands
.__contains
__(key
)
1041 def __getitem__(self
, key
):
1042 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
1043 return cls(record
=self
, **kwargs
)
1047 if "Rc" not in self
:
1049 return self
["Rc"].value
1053 def __init__(self
, record
, name
):
1054 self
.__record
= record
1058 yield ("record", self
.record
)
1059 yield ("name", self
.__name
)
1062 return f
"{self.__class__.__name__}({self.name})"
1070 return self
.__record
1074 return self
.record
.fields
[self
.name
]
1076 def assemble(self
, insn
):
1077 raise NotImplementedError()
1079 def disassemble(self
, insn
,
1080 style
=Style
.NORMAL
, indent
=""):
1081 raise NotImplementedError()
1084 class DynamicOperand(Operand
):
1085 def assemble(self
, insn
, value
):
1087 if isinstance(value
, str):
1088 value
= int(value
, 0)
1090 raise ValueError("signed operands not allowed")
1093 def disassemble(self
, insn
,
1094 style
=Style
.NORMAL
, indent
=""):
1098 if style
>= Style
.VERBOSE
:
1099 span
= map(str, span
)
1100 yield f
"{indent}{self.name}"
1101 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1102 yield f
"{indent}{indent}{', '.join(span)}"
1104 yield str(int(value
))
1107 class SignedOperand(DynamicOperand
):
1108 def assemble(self
, insn
, value
):
1109 if isinstance(value
, str):
1110 value
= int(value
, 0)
1111 return super().assemble(value
=value
, insn
=insn
)
1113 def assemble(self
, insn
, value
):
1115 if isinstance(value
, str):
1116 value
= int(value
, 0)
1119 def disassemble(self
, insn
,
1120 style
=Style
.NORMAL
, indent
=""):
1122 value
= insn
[span
].to_signed_int()
1123 sign
= "-" if (value
< 0) else ""
1126 if style
>= Style
.VERBOSE
:
1127 span
= map(str, span
)
1128 yield f
"{indent}{self.name}"
1129 yield f
"{indent}{indent}{sign}{value}"
1130 yield f
"{indent}{indent}{', '.join(span)}"
1132 yield f
"{sign}{value}"
1135 class StaticOperand(Operand
):
1136 def __init__(self
, record
, name
, value
):
1137 self
.__value
= value
1138 return super().__init
__(record
=record
, name
=name
)
1141 yield ("value", self
.__value
)
1142 yield from super().__iter
__()
1145 return f
"{self.__class__.__name__}({self.name}, value={self.value})"
1151 def assemble(self
, insn
):
1152 insn
[self
.span
] = self
.value
1154 def disassemble(self
, insn
,
1155 style
=Style
.NORMAL
, indent
=""):
1159 if style
>= Style
.VERBOSE
:
1160 span
= map(str, span
)
1161 yield f
"{indent}{self.name}"
1162 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1163 yield f
"{indent}{indent}{', '.join(span)}"
1165 yield str(int(value
))
1168 class SpanStaticOperand(StaticOperand
):
1169 def __init__(self
, record
, name
, value
, span
):
1170 self
.__span
= tuple(span
)
1171 return super().__init
__(record
=record
, name
=name
, value
=value
)
1174 yield ("span", self
.__span
)
1175 yield from super().__iter
__()
1182 class POStaticOperand(SpanStaticOperand
):
1183 def __init__(self
, record
, value
):
1184 return super().__init
__(record
=record
, name
="PO",
1185 value
=value
, span
=range(0, 6))
1188 for (key
, value
) in super().__iter
__():
1189 if key
not in {"name", "span"}:
1193 class XOStaticOperand(SpanStaticOperand
):
1194 def __init__(self
, record
, value
, span
):
1195 bits
= record
.section
.bitsel
1196 value
= _SelectableInt(value
=value
, bits
=len(bits
))
1197 span
= dict(zip(bits
, range(len(bits
))))
1198 span_rev
= {value
:key
for (key
, value
) in span
.items()}
1200 # This part is tricky: we cannot use record.operands,
1201 # as this code is called by record.static_operands method.
1202 for (cls
, kwargs
) in record
.mdwn
.operands
:
1203 operand
= cls(record
=record
, **kwargs
)
1204 for idx
in operand
.span
:
1205 rev
= span
.pop(idx
, None)
1207 span_rev
.pop(rev
, None)
1209 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1210 span
= tuple(span
.keys())
1212 return super().__init
__(record
=record
, name
="XO",
1213 value
=value
, span
=span
)
1216 for (key
, value
) in super().__iter
__():
1217 if key
not in {"name"}:
1221 class ImmediateOperand(DynamicOperand
):
1225 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1229 class NonZeroOperand(DynamicOperand
):
1230 def assemble(self
, insn
, value
):
1231 if isinstance(value
, str):
1232 value
= int(value
, 0)
1233 if not isinstance(value
, int):
1234 raise ValueError("non-integer operand")
1236 raise ValueError("non-zero operand")
1238 return super().assemble(value
=value
, insn
=insn
)
1240 def disassemble(self
, insn
,
1241 style
=Style
.NORMAL
, indent
=""):
1245 if style
>= Style
.VERBOSE
:
1246 span
= map(str, span
)
1247 yield f
"{indent}{self.name}"
1248 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1249 yield f
"{indent}{indent}{', '.join(span)}"
1251 yield str(int(value
) + 1)
1254 class ExtendableOperand(DynamicOperand
):
1255 def sv_spec_enter(self
, value
, span
):
1256 return (value
, span
)
1258 def sv_spec(self
, insn
):
1262 span
= tuple(map(str, span
))
1264 if isinstance(insn
, SVP64Instruction
):
1265 (origin_value
, origin_span
) = (value
, span
)
1266 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1268 for extra_idx
in self
.extra_idx
:
1269 if self
.record
.etype
is _SVEType
.EXTRA3
:
1270 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1271 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1272 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1274 raise ValueError(self
.record
.etype
)
1277 vector
= bool(spec
[0])
1278 spec_span
= spec
.__class
__
1279 if self
.record
.etype
is _SVEType
.EXTRA3
:
1280 spec_span
= tuple(map(str, spec_span
[1, 2]))
1282 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1283 spec_span
= tuple(map(str, spec_span
[1,]))
1284 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1287 spec_span
= (spec_span
+ ("{0}",))
1289 spec_span
= (("{0}",) + spec_span
)
1291 raise ValueError(self
.record
.etype
)
1293 vector_shift
= (2 + (5 - value
.bits
))
1294 scalar_shift
= value
.bits
1295 spec_shift
= (5 - value
.bits
)
1297 bits
= (len(span
) + len(spec_span
))
1298 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1299 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1301 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1302 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1304 value
= ((spec
<< scalar_shift
) | value
)
1305 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1307 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1308 origin_value
=origin_value
, origin_span
=origin_span
)
1310 return (vector
, value
, span
)
1312 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1313 return (value
, span
)
1316 def extra_idx(self
):
1317 for (key
, record
) in self
.record
.svp64
.extras
.items():
1318 if record
["reg"].alias
is self
.extra_reg
.alias
:
1322 def extra_reg(self
):
1323 return _Reg(self
.name
)
1325 def remap(self
, value
, vector
):
1326 raise NotImplementedError()
1328 def assemble(self
, value
, insn
, prefix
):
1331 if isinstance(value
, str):
1332 value
= value
.lower()
1333 if value
.startswith("%"):
1335 if value
.startswith("*"):
1336 if not isinstance(insn
, SVP64Instruction
):
1337 raise ValueError(value
)
1340 if value
.startswith(prefix
):
1341 if (self
.extra_reg
.or_zero
and (value
== f
"{prefix}0")):
1342 raise ValueError(value
)
1343 value
= value
[len(prefix
):]
1344 value
= int(value
, 0)
1346 if isinstance(insn
, SVP64Instruction
):
1347 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1349 for extra_idx
in self
.extra_idx
:
1350 if self
.record
.etype
is _SVEType
.EXTRA3
:
1351 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1352 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1353 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1355 raise ValueError(self
.record
.etype
)
1357 return super().assemble(value
=value
, insn
=insn
)
1359 def disassemble(self
, insn
,
1360 style
=Style
.NORMAL
, prefix
="", indent
=""):
1361 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1363 if (self
.extra_reg
.or_zero
and (value
== 0)):
1366 if style
>= Style
.VERBOSE
:
1367 mode
= "vector" if vector
else "scalar"
1368 yield f
"{indent}{self.name} ({mode})"
1369 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1370 yield f
"{indent}{indent}{', '.join(span)}"
1371 if isinstance(insn
, SVP64Instruction
):
1372 for extra_idx
in frozenset(self
.extra_idx
):
1373 if self
.record
.etype
is _SVEType
.NONE
:
1374 yield f
"{indent}{indent}extra[none]"
1376 etype
= repr(self
.record
.etype
).lower()
1377 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1379 vector
= "*" if vector
else ""
1380 yield f
"{vector}{prefix}{int(value)}"
1383 class SimpleRegisterOperand(ExtendableOperand
):
1384 def remap(self
, value
, vector
):
1386 extra
= (value
& 0b11)
1387 value
= (value
>> 2)
1389 extra
= (value
>> 5)
1390 value
= (value
& 0b11111)
1392 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1393 # (and shrink to a single bit if ok)
1394 if self
.record
.etype
is _SVEType
.EXTRA2
:
1396 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1397 assert (extra
& 0b01) == 0, \
1398 ("vector field %s cannot fit into EXTRA2" % value
)
1399 extra
= (0b10 |
(extra
>> 1))
1401 # range is r0-r63 in increments of 1
1402 assert (extra
>> 1) == 0, \
1403 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1405 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1407 # EXTRA3 vector bit needs marking
1410 raise ValueError(self
.record
.etype
)
1412 return (value
, extra
)
1415 class GPROperand(SimpleRegisterOperand
):
1416 def assemble(self
, insn
, value
):
1417 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1419 def disassemble(self
, insn
,
1420 style
=Style
.NORMAL
, indent
=""):
1421 prefix
= "" if (style
<= Style
.SHORT
) else "r"
1422 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1423 style
=style
, indent
=indent
)
1426 class GPRPairOperand(GPROperand
):
1430 class FPROperand(SimpleRegisterOperand
):
1431 def assemble(self
, insn
, value
):
1432 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1434 def disassemble(self
, insn
,
1435 style
=Style
.NORMAL
, indent
=""):
1436 prefix
= "" if (style
<= Style
.SHORT
) else "f"
1437 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1438 style
=style
, indent
=indent
)
1441 class FPRPairOperand(FPROperand
):
1445 class ConditionRegisterFieldOperand(ExtendableOperand
):
1446 def pattern(name_pattern
):
1447 (name
, pattern
) = name_pattern
1448 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1457 CR
= r
"(?:CR|cr)([0-9]+)"
1459 BIT
= rf
"({'|'.join(CONDS.keys())})"
1460 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1461 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1462 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1463 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1464 XCR
= fr
"{CR}\.{BIT}"
1465 PATTERNS
= tuple(map(pattern
, (
1470 ("BIT+CR", (LBIT
+ CR
)),
1471 ("CR+BIT", (CR
+ RBIT
)),
1472 ("BIT+CR*N", (LBIT
+ CRN
)),
1473 ("CR*N+BIT", (CRN
+ RBIT
)),
1474 ("BIT+N*CR", (LBIT
+ NCR
)),
1475 ("N*CR+BIT", (NCR
+ RBIT
)),
1478 def remap(self
, value
, vector
, regtype
):
1479 if regtype
is _RegType
.CR_5BIT
:
1480 subvalue
= (value
& 0b11)
1484 extra
= (value
& 0b1111)
1487 extra
= (value
>> 3)
1490 if self
.record
.etype
is _SVEType
.EXTRA2
:
1492 assert (extra
& 0b111) == 0, \
1493 "vector CR cannot fit into EXTRA2"
1494 extra
= (0b10 |
(extra
>> 3))
1496 assert (extra
>> 1) == 0, \
1497 "scalar CR cannot fit into EXTRA2"
1499 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1501 assert (extra
& 0b11) == 0, \
1502 "vector CR cannot fit into EXTRA3"
1503 extra
= (0b100 |
(extra
>> 2))
1505 assert (extra
>> 2) == 0, \
1506 "scalar CR cannot fit into EXTRA3"
1509 if regtype
is _RegType
.CR_5BIT
:
1510 value
= ((value
<< 2) | subvalue
)
1512 return (value
, extra
)
1514 def assemble(self
, insn
, value
):
1515 if isinstance(value
, str):
1518 if value
.startswith("*"):
1519 if not isinstance(insn
, SVP64Instruction
):
1520 raise ValueError(value
)
1524 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1525 match
= pattern
.match(value
)
1526 if match
is not None:
1527 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1528 values
= match
.groups()
1529 match
= dict(zip(keys
, values
))
1530 CR
= int(match
["CR"])
1534 N
= int(match
.get("N", "1"))
1535 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1536 value
= ((CR
* N
) + BIT
)
1543 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1545 def disassemble(self
, insn
,
1546 style
=Style
.NORMAL
, prefix
="", indent
=""):
1547 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1549 if style
>= Style
.VERBOSE
:
1550 mode
= "vector" if vector
else "scalar"
1551 yield f
"{indent}{self.name} ({mode})"
1552 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1553 yield f
"{indent}{indent}{', '.join(span)}"
1554 if isinstance(insn
, SVP64Instruction
):
1555 for extra_idx
in frozenset(self
.extra_idx
):
1556 if self
.record
.etype
is _SVEType
.NONE
:
1557 yield f
"{indent}{indent}extra[none]"
1559 etype
= repr(self
.record
.etype
).lower()
1560 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1562 vector
= "*" if vector
else ""
1563 CR
= int(value
>> 2)
1565 cond
= ("lt", "gt", "eq", "so")[CC
]
1566 if style
>= Style
.NORMAL
:
1568 if isinstance(insn
, SVP64Instruction
):
1569 yield f
"{vector}cr{CR}.{cond}"
1571 yield f
"4*cr{CR}+{cond}"
1575 yield f
"{vector}{prefix}{int(value)}"
1578 class CR3Operand(ConditionRegisterFieldOperand
):
1579 def remap(self
, value
, vector
):
1580 return super().remap(value
=value
, vector
=vector
,
1581 regtype
=_RegType
.CR_3BIT
)
1584 class CR5Operand(ConditionRegisterFieldOperand
):
1585 def remap(self
, value
, vector
):
1586 return super().remap(value
=value
, vector
=vector
,
1587 regtype
=_RegType
.CR_5BIT
)
1589 def sv_spec_enter(self
, value
, span
):
1590 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1591 return (value
, span
)
1593 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1594 value
= _selectconcat(value
, origin_value
[3:5])
1596 return (value
, span
)
1599 class EXTSOperand(SignedOperand
):
1600 field
: str # real name to report
1601 nz
: int = 0 # number of zeros
1602 fmt
: str = "d" # integer formatter
1604 def __init__(self
, record
, name
, field
, nz
=0, fmt
="d"):
1605 self
.__field
= field
1608 return super().__init
__(record
=record
, name
=name
)
1624 return self
.record
.fields
[self
.field
]
1626 def assemble(self
, insn
, value
):
1628 if isinstance(value
, str):
1629 value
= int(value
, 0)
1630 insn
[span
] = (value
>> self
.nz
)
1632 def disassemble(self
, insn
,
1633 style
=Style
.NORMAL
, indent
=""):
1635 value
= insn
[span
].to_signed_int()
1636 sign
= "-" if (value
< 0) else ""
1637 value
= (abs(value
) << self
.nz
)
1639 if style
>= Style
.VERBOSE
:
1640 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1641 zeros
= ("0" * self
.nz
)
1642 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1643 yield f
"{indent * 1}{hint}"
1644 yield f
"{indent * 2}{self.field}"
1645 yield f
"{indent * 3}{sign}{value:{self.fmt}}"
1646 yield f
"{indent * 3}{', '.join(span)}"
1648 yield f
"{sign}{value:{self.fmt}}"
1651 class TargetAddrOperand(EXTSOperand
):
1652 def __init__(self
, record
, name
, field
):
1653 return super().__init
__(record
=record
, name
=name
, field
=field
,
1657 class TargetAddrOperandLI(TargetAddrOperand
):
1658 def __init__(self
, record
, name
):
1659 return super().__init
__(record
=record
, name
=name
, field
="LI")
1662 class TargetAddrOperandBD(TargetAddrOperand
):
1663 def __init__(self
, record
, name
):
1664 return super().__init
__(record
=record
, name
=name
, field
="BD")
1667 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1668 def __init__(self
, record
, name
):
1669 return super().__init
__(record
=record
, name
=name
, field
="DS", nz
=2)
1672 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1673 def __init__(self
, record
, name
):
1674 return super().__init
__(record
=record
, name
=name
, field
="DQ", nz
=4)
1677 class DOperandDX(SignedOperand
):
1680 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1681 operands
= map(cls
, ("d0", "d1", "d2"))
1682 spans
= map(lambda operand
: operand
.span
, operands
)
1683 return sum(spans
, tuple())
1685 def disassemble(self
, insn
,
1686 style
=Style
.NORMAL
, indent
=""):
1688 value
= insn
[span
].to_signed_int()
1689 sign
= "-" if (value
< 0) else ""
1692 if style
>= Style
.VERBOSE
:
1699 for (subname
, subspan
) in mapping
.items():
1700 operand
= DynamicOperand(name
=subname
)
1702 span
= map(str, span
)
1703 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1704 yield f
"{indent}{indent}{indent}{sign}{value}"
1705 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1707 yield f
"{sign}{value}"
1710 class Instruction(_Mapping
):
1712 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1713 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1714 raise ValueError(bits
)
1716 if isinstance(value
, bytes
):
1717 if ((len(value
) * 8) != bits
):
1718 raise ValueError(f
"bit length mismatch")
1719 value
= int.from_bytes(value
, byteorder
=byteorder
)
1721 if isinstance(value
, int):
1722 value
= _SelectableInt(value
=value
, bits
=bits
)
1723 elif isinstance(value
, Instruction
):
1724 value
= value
.storage
1726 if not isinstance(value
, _SelectableInt
):
1727 raise ValueError(value
)
1730 if len(value
) != bits
:
1731 raise ValueError(value
)
1733 value
= _SelectableInt(value
=value
, bits
=bits
)
1735 return cls(storage
=value
)
1738 return hash(int(self
))
1740 def __getitem__(self
, key
):
1741 return self
.storage
.__getitem
__(key
)
1743 def __setitem__(self
, key
, value
):
1744 return self
.storage
.__setitem
__(key
, value
)
1746 def bytes(self
, byteorder
="little"):
1747 nr_bytes
= (len(self
.__class
__) // 8)
1748 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1751 def record(cls
, db
, entry
):
1754 raise KeyError(entry
)
1758 def operands(cls
, record
):
1759 yield from record
.operands
1762 def static_operands(cls
, record
):
1763 return filter(lambda operand
: isinstance(operand
, StaticOperand
),
1764 cls
.operands(record
=record
))
1767 def dynamic_operands(cls
, record
):
1768 return filter(lambda operand
: isinstance(operand
, DynamicOperand
),
1769 cls
.operands(record
=record
))
1771 def spec(self
, record
, prefix
):
1772 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1773 self
.spec_dynamic_operands(record
=record
)))
1775 static_operands
= []
1776 for (name
, value
) in self
.spec_static_operands(record
=record
):
1777 static_operands
.append(f
"{name}={value}")
1780 if dynamic_operands
:
1782 operands
+= ",".join(dynamic_operands
)
1785 operands
+= " ".join(static_operands
)
1787 return f
"{prefix}{record.name}{operands}"
1789 def spec_static_operands(self
, record
):
1790 for operand
in self
.static_operands(record
=record
):
1791 if not isinstance(operand
, (POStaticOperand
, XOStaticOperand
)):
1792 yield (operand
.name
, operand
.value
)
1794 def spec_dynamic_operands(self
, record
, style
=Style
.NORMAL
):
1798 for operand
in self
.dynamic_operands(record
=record
):
1800 value
= " ".join(operand
.disassemble(insn
=self
,
1801 style
=min(style
, Style
.NORMAL
)))
1803 name
= f
"{imm_name}({name})"
1804 value
= f
"{imm_value}({value})"
1806 if isinstance(operand
, ImmediateOperand
):
1814 def assemble(cls
, record
, arguments
=None):
1815 if arguments
is None:
1818 insn
= cls
.integer(value
=0)
1820 for operand
in cls
.static_operands(record
=record
):
1821 operand
.assemble(insn
=insn
)
1823 arguments
= Arguments(record
=record
,
1824 arguments
=arguments
, operands
=cls
.dynamic_operands(record
=record
))
1825 for (value
, operand
) in arguments
:
1826 operand
.assemble(insn
=insn
, value
=value
)
1830 def disassemble(self
, record
,
1832 style
=Style
.NORMAL
):
1833 raise NotImplementedError()
1836 class WordInstruction(Instruction
):
1837 _
: _Field
= range(0, 32)
1838 PO
: _Field
= range(0, 6)
1841 def integer(cls
, value
, byteorder
="little"):
1842 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1847 for idx
in range(32):
1848 bit
= int(self
[idx
])
1850 return "".join(map(str, bits
))
1852 def disassemble(self
, record
,
1854 style
=Style
.NORMAL
):
1855 if style
<= Style
.SHORT
:
1858 blob
= self
.bytes(byteorder
=byteorder
)
1859 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1863 yield f
"{blob}.long 0x{int(self):08x}"
1866 # awful temporary hack: workaround for ld-update
1867 # https://bugs.libre-soc.org/show_bug.cgi?id=1056#c2
1868 # XXX TODO must check that *EXTENDED* RA != extended-RT
1869 if (record
.svp64
is not None and
1870 record
.mode
== _SVMode
.LDST_IMM
and
1871 'u' in record
.name
):
1872 yield f
"{blob}.long 0x{int(self):08x}"
1876 if style
is Style
.LEGACY
:
1878 for operand
in self
.dynamic_operands(record
=record
):
1879 if isinstance(operand
, (GPRPairOperand
, FPRPairOperand
)):
1882 if style
is Style
.LEGACY
and (paired
or record
.ppc
.unofficial
):
1883 yield f
"{blob}.long 0x{int(self):08x}"
1885 operands
= tuple(map(_operator
.itemgetter(1),
1886 self
.spec_dynamic_operands(record
=record
, style
=style
)))
1888 operands
= ",".join(operands
)
1889 yield f
"{blob}{record.name} {operands}"
1891 yield f
"{blob}{record.name}"
1893 if style
>= Style
.VERBOSE
:
1895 binary
= self
.binary
1896 spec
= self
.spec(record
=record
, prefix
="")
1897 yield f
"{indent}spec"
1898 yield f
"{indent}{indent}{spec}"
1899 yield f
"{indent}pcode"
1900 for stmt
in record
.mdwn
.pcode
:
1901 yield f
"{indent}{indent}{stmt}"
1902 yield f
"{indent}binary"
1903 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1904 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1905 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1906 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1907 yield f
"{indent}opcodes"
1908 for opcode
in record
.opcodes
:
1909 yield f
"{indent}{indent}{opcode!r}"
1910 for operand
in self
.operands(record
=record
):
1911 yield from operand
.disassemble(insn
=self
,
1912 style
=style
, indent
=indent
)
1916 class PrefixedInstruction(Instruction
):
1917 class Prefix(WordInstruction
.remap(range(0, 32))):
1920 class Suffix(WordInstruction
.remap(range(32, 64))):
1923 _
: _Field
= range(64)
1929 def integer(cls
, value
, byteorder
="little"):
1930 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
1933 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
1934 def transform(value
):
1935 return WordInstruction
.integer(value
=value
,
1936 byteorder
=byteorder
)[0:32]
1938 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
1939 value
= _selectconcat(prefix
, suffix
)
1941 return super().integer(bits
=64, value
=value
)
1944 class Mode(_Mapping
):
1945 _
: _Field
= range(0, 5)
1946 sel
: _Field
= (0, 1)
1949 class ExtraRM(_Mapping
):
1950 _
: _Field
= range(0, 9)
1953 class Extra2RM(ExtraRM
):
1954 idx0
: _Field
= range(0, 2)
1955 idx1
: _Field
= range(2, 4)
1956 idx2
: _Field
= range(4, 6)
1957 idx3
: _Field
= range(6, 8)
1959 def __getitem__(self
, key
):
1965 _SVExtra
.Idx0
: self
.idx0
,
1966 _SVExtra
.Idx1
: self
.idx1
,
1967 _SVExtra
.Idx2
: self
.idx2
,
1968 _SVExtra
.Idx3
: self
.idx3
,
1971 def __setitem__(self
, key
, value
):
1972 self
[key
].assign(value
)
1975 class Extra3RM(ExtraRM
):
1976 idx0
: _Field
= range(0, 3)
1977 idx1
: _Field
= range(3, 6)
1978 idx2
: _Field
= range(6, 9)
1980 def __getitem__(self
, key
):
1985 _SVExtra
.Idx0
: self
.idx0
,
1986 _SVExtra
.Idx1
: self
.idx1
,
1987 _SVExtra
.Idx2
: self
.idx2
,
1990 def __setitem__(self
, key
, value
):
1991 self
[key
].assign(value
)
1994 class BaseRM(_Mapping
):
1995 _
: _Field
= range(24)
1996 mmode
: _Field
= (0,)
1997 mask
: _Field
= range(1, 4)
1998 elwidth
: _Field
= range(4, 6)
1999 ewsrc
: _Field
= range(6, 8)
2000 subvl
: _Field
= range(8, 10)
2001 mode
: Mode
.remap(range(19, 24))
2002 smask_extra322
: _Field
= (6,7,18,) # LDST_IDX is EXTRA332
2003 smask
: _Field
= range(16, 19) # everything else use this
2004 extra
: ExtraRM
.remap(range(10, 19))
2005 extra2
: Extra2RM
.remap(range(10, 19))
2006 extra3
: Extra3RM
.remap(range(10, 19))
2007 # XXX extra332 = (extra3[0], extra3[1], extra2[3])
2009 def specifiers(self
, record
):
2010 subvl
= int(self
.subvl
)
2018 def disassemble(self
, style
=Style
.NORMAL
):
2019 if style
>= Style
.VERBOSE
:
2021 for (name
, span
) in self
.traverse(path
="RM"):
2022 value
= self
.storage
[span
]
2024 yield f
"{indent}{int(value):0{value.bits}b}"
2025 yield f
"{indent}{', '.join(map(str, span))}"
2028 class FFRc1BaseRM(BaseRM
):
2029 def specifiers(self
, record
, mode
):
2030 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
2031 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
2032 mask
= int(_selectconcat(CR
, inv
))
2033 predicate
= PredicateBaseRM
.predicate(True, mask
)
2034 yield f
"{mode}={predicate}"
2036 yield from super().specifiers(record
=record
)
2039 class FFRc0BaseRM(BaseRM
):
2040 def specifiers(self
, record
, mode
):
2042 inv
= "~" if self
.inv
else ""
2043 yield f
"{mode}={inv}RC1"
2045 yield from super().specifiers(record
=record
)
2048 class SatBaseRM(BaseRM
):
2049 def specifiers(self
, record
):
2055 yield from super().specifiers(record
=record
)
2058 class ZZBaseRM(BaseRM
):
2059 def specifiers(self
, record
):
2063 yield from super().specifiers(record
=record
)
2066 class ZZCombinedBaseRM(BaseRM
):
2067 def specifiers(self
, record
):
2068 if self
.sz
and self
.dz
:
2075 yield from super().specifiers(record
=record
)
2078 class DZBaseRM(BaseRM
):
2079 def specifiers(self
, record
):
2083 yield from super().specifiers(record
=record
)
2086 class SZBaseRM(BaseRM
):
2087 def specifiers(self
, record
):
2091 yield from super().specifiers(record
=record
)
2094 class MRBaseRM(BaseRM
):
2095 def specifiers(self
, record
):
2101 yield from super().specifiers(record
=record
)
2104 class ElsBaseRM(BaseRM
):
2105 def specifiers(self
, record
):
2109 yield from super().specifiers(record
=record
)
2112 class WidthBaseRM(BaseRM
):
2114 def width(FP
, width
):
2123 width
= ("fp" + width
)
2126 def specifiers(self
, record
):
2127 # elwidths: use "w=" if same otherwise dw/sw
2128 # FIXME this should consider FP instructions
2130 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
2131 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2132 if record
.svp64
.mode
is _SVMode
.CROP
:
2136 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2145 yield from super().specifiers(record
=record
)
2148 class PredicateBaseRM(BaseRM
):
2150 def predicate(CR
, mask
):
2153 (False, 0b001): "1<<r3",
2154 (False, 0b010): "r3",
2155 (False, 0b011): "~r3",
2156 (False, 0b100): "r10",
2157 (False, 0b101): "~r10",
2158 (False, 0b110): "r30",
2159 (False, 0b111): "~r30",
2161 (True, 0b000): "lt",
2162 (True, 0b001): "ge",
2163 (True, 0b010): "gt",
2164 (True, 0b011): "le",
2165 (True, 0b100): "eq",
2166 (True, 0b101): "ne",
2167 (True, 0b110): "so",
2168 (True, 0b111): "ns",
2171 def specifiers(self
, record
):
2172 # predication - single and twin
2173 # use "m=" if same otherwise sm/dm
2174 CR
= (int(self
.mmode
) == 1)
2175 mask
= int(self
.mask
)
2176 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
2177 if record
.svp64
.ptype
is _SVPType
.P2
:
2178 # LDST_IDX smask moving to extra322 but not straight away (False)
2179 if False and record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2180 smask
= int(self
.smask_extra332
)
2182 smask
= int(self
.smask
)
2183 sm
= PredicateBaseRM
.predicate(CR
, smask
)
2192 yield from super().specifiers(record
=record
)
2195 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
2199 class SEABaseRM(BaseRM
):
2200 def specifiers(self
, record
):
2204 yield from super().specifiers(record
=record
)
2207 class VLiBaseRM(BaseRM
):
2208 def specifiers(self
, record
):
2212 yield from super().specifiers(record
=record
)
2215 class NormalBaseRM(PredicateWidthBaseRM
):
2218 https://libre-soc.org/openpower/sv/normal/
2223 class NormalSimpleRM(ZZCombinedBaseRM
, NormalBaseRM
):
2224 """normal: simple mode"""
2228 def specifiers(self
, record
):
2229 yield from super().specifiers(record
=record
)
2232 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
2233 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
2237 class NormalFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, NormalBaseRM
):
2238 """normal: Rc=1: ffirst CR sel"""
2241 CR
: BaseRM
.mode
[3, 4]
2243 def specifiers(self
, record
):
2244 yield from super().specifiers(record
=record
, mode
="ff")
2247 class NormalFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
2248 """normal: Rc=0: ffirst z/nonz"""
2253 def specifiers(self
, record
):
2254 yield from super().specifiers(record
=record
, mode
="ff")
2257 class NormalSatRM(SatBaseRM
, ZZCombinedBaseRM
, NormalBaseRM
):
2258 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2264 class NormalRM(NormalBaseRM
):
2265 simple
: NormalSimpleRM
2267 ffrc1
: NormalFFRc1RM
2268 ffrc0
: NormalFFRc0RM
2272 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2274 LD/ST Immediate mode
2275 https://libre-soc.org/openpower/sv/ldst/
2280 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2281 """ld/st immediate: simple mode"""
2282 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2283 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2289 def specifiers(self
, record
):
2295 yield from super().specifiers(record
=record
)
2298 class LDSTFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2299 """ld/st immediate&indexed: Rc=1: ffirst CR sel"""
2302 CR
: BaseRM
.mode
[3, 4]
2304 def specifiers(self
, record
):
2305 yield from super().specifiers(record
=record
, mode
="ff")
2308 class LDSTFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2309 """ld/st immediate&indexed: Rc=0: ffirst z/nonz"""
2314 def specifiers(self
, record
):
2315 yield from super().specifiers(record
=record
, mode
="ff")
2318 class LDSTImmRM(LDSTImmBaseRM
):
2319 simple
: LDSTImmSimpleRM
2324 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2327 https://libre-soc.org/openpower/sv/ldst/
2332 class LDSTIdxSimpleRM(SEABaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2333 """ld/st index: simple mode (includes element-strided and Signed-EA)"""
2334 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2341 def specifiers(self
, record
):
2347 yield from super().specifiers(record
=record
)
2350 class LDSTIdxRM(LDSTIdxBaseRM
):
2351 simple
: LDSTIdxSimpleRM
2357 class CROpBaseRM(BaseRM
):
2360 https://libre-soc.org/openpower/sv/cr_ops/
2365 class CROpSimpleRM(PredicateBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2366 """crop: simple mode"""
2371 def specifiers(self
, record
):
2373 yield "rg" # simple CR Mode reports /rg
2375 yield from super().specifiers(record
=record
)
2378 class CROpMRRM(MRBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2379 """crop: scalar reduce mode (mapreduce)"""
2385 class CROpFF5RM(FFRc0BaseRM
, PredicateBaseRM
, VLiBaseRM
, DZBaseRM
,
2386 SZBaseRM
, CROpBaseRM
):
2387 """crop: ffirst 5-bit mode"""
2394 def specifiers(self
, record
):
2395 yield from super().specifiers(record
=record
, mode
="ff")
2398 # FIXME: almost everything in this class contradicts the specs (it doesn't)
2399 # The modes however are swapped: 5-bit is 3-bit, 3-bit is 5-bit
2400 class CROpFF3RM(FFRc1BaseRM
, PredicateBaseRM
, VLiBaseRM
, ZZBaseRM
, CROpBaseRM
):
2401 """cr_op: ffirst 3-bit mode"""
2407 def specifiers(self
, record
):
2408 yield from super().specifiers(record
=record
, mode
="ff")
2411 class CROpRM(CROpBaseRM
):
2412 simple
: CROpSimpleRM
2418 # ********************
2420 # https://libre-soc.org/openpower/sv/branches/
2421 class BranchBaseRM(BaseRM
):
2431 def specifiers(self
, record
):
2443 raise ValueError(self
.sz
)
2455 # Branch modes lack source mask.
2456 # Therefore a custom code is needed.
2457 CR
= (int(self
.mmode
) == 1)
2458 mask
= int(self
.mask
)
2459 m
= PredicateBaseRM
.predicate(CR
, mask
)
2463 yield from super().specifiers(record
=record
)
2466 class BranchSimpleRM(BranchBaseRM
):
2467 """branch: simple mode"""
2471 class BranchVLSRM(BranchBaseRM
):
2472 """branch: VLSET mode"""
2476 def specifiers(self
, record
):
2482 }[int(self
.VSb
), int(self
.VLi
)]
2484 yield from super().specifiers(record
=record
)
2487 class BranchCTRRM(BranchBaseRM
):
2488 """branch: CTR-test mode"""
2491 def specifiers(self
, record
):
2497 yield from super().specifiers(record
=record
)
2500 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2501 """branch: CTR-test+VLSET mode"""
2505 class BranchRM(BranchBaseRM
):
2506 simple
: BranchSimpleRM
2509 ctrvls
: BranchCTRVLSRM
2520 @_dataclasses.dataclass(eq
=True, frozen
=True)
2525 def match(cls
, desc
, record
):
2526 raise NotImplementedError()
2528 def validate(self
, others
):
2531 def assemble(self
, insn
):
2532 raise NotImplementedError()
2535 @_dataclasses.dataclass(eq
=True, frozen
=True)
2536 class SpecifierWidth(Specifier
):
2540 def match(cls
, desc
, record
, etalon
):
2541 (mode
, _
, value
) = desc
.partition("=")
2543 value
= value
.strip()
2546 width
= _SVP64Width(value
)
2548 return cls(record
=record
, width
=width
)
2551 @_dataclasses.dataclass(eq
=True, frozen
=True)
2552 class SpecifierW(SpecifierWidth
):
2554 def match(cls
, desc
, record
):
2555 return super().match(desc
=desc
, record
=record
, etalon
="w")
2557 def assemble(self
, insn
):
2558 selector
= insn
.select(record
=self
.record
)
2559 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2560 selector
.ewsrc
= self
.width
.value
2561 selector
.elwidth
= self
.width
.value
2564 @_dataclasses.dataclass(eq
=True, frozen
=True)
2565 class SpecifierSW(SpecifierWidth
):
2567 def match(cls
, desc
, record
):
2568 if record
.svp64
.mode
is _SVMode
.CROP
:
2570 return super().match(desc
=desc
, record
=record
, etalon
="sw")
2572 def assemble(self
, insn
):
2573 selector
= insn
.select(record
=self
.record
)
2574 selector
.ewsrc
= self
.width
.value
2577 @_dataclasses.dataclass(eq
=True, frozen
=True)
2578 class SpecifierDW(SpecifierWidth
):
2580 def match(cls
, desc
, record
):
2581 return super().match(desc
=desc
, record
=record
, etalon
="dw")
2583 def assemble(self
, insn
):
2584 selector
= insn
.select(record
=self
.record
)
2585 selector
.elwidth
= self
.width
.value
2588 @_dataclasses.dataclass(eq
=True, frozen
=True)
2589 class SpecifierSubVL(Specifier
):
2593 def match(cls
, desc
, record
):
2595 value
= _SVP64SubVL(desc
)
2599 return cls(record
=record
, value
=value
)
2601 def assemble(self
, insn
):
2602 selector
= insn
.select(record
=self
.record
)
2603 selector
.subvl
= int(self
.value
.value
)
2606 @_dataclasses.dataclass(eq
=True, frozen
=True)
2607 class SpecifierPredicate(Specifier
):
2612 def match(cls
, desc
, record
, mode_match
, pred_match
):
2613 (mode
, _
, pred
) = desc
.partition("=")
2616 if not mode_match(mode
):
2619 pred
= _SVP64Pred(pred
.strip())
2620 if not pred_match(pred
):
2621 raise ValueError(pred
)
2623 return cls(record
=record
, mode
=mode
, pred
=pred
)
2626 @_dataclasses.dataclass(eq
=True, frozen
=True)
2627 class SpecifierFF(SpecifierPredicate
):
2629 def match(cls
, desc
, record
):
2630 return super().match(desc
=desc
, record
=record
,
2631 mode_match
=lambda mode_arg
: mode_arg
== "ff",
2632 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2637 def assemble(self
, insn
):
2638 selector
= insn
.select(record
=self
.record
)
2639 if selector
.mode
.sel
!= 0:
2640 raise ValueError("cannot override mode")
2641 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2642 selector
.mode
.sel
= 0b01
2643 # HACK: please finally provide correct logic for CRs.
2644 if self
.pred
in (_SVP64Pred
.RC1
, _SVP64Pred
.RC1_N
):
2645 selector
.mode
[2] = (self
.pred
is _SVP64Pred
.RC1_N
)
2647 selector
.mode
[2] = self
.pred
.inv
2648 selector
.mode
[3, 4] = self
.pred
.state
2650 selector
.mode
.sel
= 0b01 if self
.mode
== "ff" else 0b11
2651 selector
.inv
= self
.pred
.inv
2653 selector
.CR
= self
.pred
.state
2655 selector
.RC1
= self
.pred
.state
2658 @_dataclasses.dataclass(eq
=True, frozen
=True)
2659 class SpecifierMask(SpecifierPredicate
):
2661 def match(cls
, desc
, record
, mode
):
2662 return super().match(desc
=desc
, record
=record
,
2663 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2664 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2669 def assemble(self
, insn
):
2670 raise NotImplementedError()
2673 @_dataclasses.dataclass(eq
=True, frozen
=True)
2674 class SpecifierM(SpecifierMask
):
2676 def match(cls
, desc
, record
):
2677 return super().match(desc
=desc
, record
=record
, mode
="m")
2679 def validate(self
, others
):
2681 if isinstance(spec
, SpecifierSM
):
2682 raise ValueError("source-mask and predicate mask conflict")
2683 elif isinstance(spec
, SpecifierDM
):
2684 raise ValueError("dest-mask and predicate mask conflict")
2686 def assemble(self
, insn
):
2687 selector
= insn
.select(record
=self
.record
)
2688 selector
.mask
= int(self
.pred
)
2689 if ((self
.record
.ptype
is _SVPType
.P2
) and
2690 (self
.record
.svp64
.mode
is not _SVMode
.BRANCH
)):
2691 selector
.smask
= int(self
.pred
)
2692 # LDST_IDX smask moving to extra322 but not straight away (False)
2693 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2694 selector
.smask_extra332
= int(self
.pred
)
2696 selector
.smask
= int(self
.pred
)
2698 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2701 @_dataclasses.dataclass(eq
=True, frozen
=True)
2702 class SpecifierSM(SpecifierMask
):
2704 def match(cls
, desc
, record
):
2705 return super().match(desc
=desc
, record
=record
, mode
="sm")
2707 def validate(self
, others
):
2708 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2709 raise ValueError("source-mask on non-twin predicate")
2711 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2714 if isinstance(spec
, SpecifierDM
):
2718 raise ValueError("missing dest-mask in CR twin predication")
2719 if self
.pred
.mode
!= twin
.pred
.mode
:
2720 raise ValueError(f
"predicate masks mismatch: "
2721 f
"{self.pred!r} vs {twin.pred!r}")
2723 def assemble(self
, insn
):
2724 selector
= insn
.select(record
=self
.record
)
2725 # LDST_IDX smask moving to extra322 but not straight away (False)
2726 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2727 selector
.smask_extra332
= int(self
.pred
)
2729 selector
.smask
= int(self
.pred
)
2730 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2733 @_dataclasses.dataclass(eq
=True, frozen
=True)
2734 class SpecifierDM(SpecifierMask
):
2736 def match(cls
, desc
, record
):
2737 return super().match(desc
=desc
, record
=record
, mode
="dm")
2739 def validate(self
, others
):
2740 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2741 raise ValueError("dest-mask on non-twin predicate")
2743 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2746 if isinstance(spec
, SpecifierSM
):
2750 raise ValueError("missing source-mask in CR twin predication")
2751 if self
.pred
.mode
!= twin
.pred
.mode
:
2752 raise ValueError(f
"predicate masks mismatch: "
2753 f
"{self.pred!r} vs {twin.pred!r}")
2755 def assemble(self
, insn
):
2756 selector
= insn
.select(record
=self
.record
)
2757 selector
.mask
= int(self
.pred
)
2758 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2761 @_dataclasses.dataclass(eq
=True, frozen
=True)
2762 class SpecifierZZ(Specifier
):
2764 def match(cls
, desc
, record
):
2768 return cls(record
=record
)
2770 def validate(self
, others
):
2772 # Since zz takes precedence (overrides) sz and dz,
2773 # treat them as mutually exclusive.
2774 if isinstance(spec
, (SpecifierSZ
, SpecifierDZ
)):
2775 raise ValueError("mutually exclusive predicate masks")
2777 def assemble(self
, insn
):
2778 selector
= insn
.select(record
=self
.record
)
2779 if hasattr(selector
, "zz"): # this should be done in a different way
2786 @_dataclasses.dataclass(eq
=True, frozen
=True)
2787 class SpecifierXZ(Specifier
):
2789 hint
: str = _dataclasses
.field(repr=False)
2792 def match(cls
, desc
, record
, etalon
, hint
):
2796 return cls(desc
=desc
, record
=record
, hint
=hint
)
2798 def validate(self
, others
):
2799 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2800 raise ValueError(f
"{self.hint} on non-twin predicate")
2802 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2805 if isinstance(spec
, SpecifierXZ
):
2809 raise ValueError(f
"missing {self.hint} in CR twin predication")
2810 if self
.pred
!= twin
.pred
:
2811 raise ValueError(f
"predicate masks mismatch: "
2812 f
"{self.pred!r} vs {twin.pred!r}")
2814 def assemble(self
, insn
):
2815 selector
= insn
.select(record
=self
.record
)
2816 setattr(selector
, self
.desc
, 1)
2819 @_dataclasses.dataclass(eq
=True, frozen
=True)
2820 class SpecifierSZ(SpecifierXZ
):
2822 def match(cls
, desc
, record
):
2823 return super().match(desc
=desc
, record
=record
,
2824 etalon
="sz", hint
="source-mask")
2826 def validate(self
, others
):
2828 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2829 if isinstance(spec
, SpecifierFF
):
2830 raise ValueError("source-zero not allowed in ff mode")
2833 @_dataclasses.dataclass(eq
=True, frozen
=True)
2834 class SpecifierDZ(SpecifierXZ
):
2836 def match(cls
, desc
, record
):
2837 return super().match(desc
=desc
, record
=record
,
2838 etalon
="dz", hint
="dest-mask")
2840 def validate(self
, others
):
2842 if ((self
.record
.svp64
.mode
is not _SVMode
.CROP
) and
2843 isinstance(spec
, SpecifierFF
) and
2844 (spec
.pred
.mode
is _SVP64PredMode
.RC1
)):
2845 raise ValueError(f
"dest-zero not allowed in ff mode BO")
2848 @_dataclasses.dataclass(eq
=True, frozen
=True)
2849 class SpecifierEls(Specifier
):
2851 def match(cls
, desc
, record
):
2855 if record
.svp64
.mode
not in (_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
):
2856 raise ValueError("els is only valid in ld/st modes, not "
2857 "%s" % str(self
.record
.svp64
.mode
))
2859 return cls(record
=record
)
2861 def assemble(self
, insn
):
2862 if self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
: # stride mode
2863 insn
.prefix
.rm
.mode
[1] = 0
2865 selector
= insn
.select(record
=self
.record
)
2870 @_dataclasses.dataclass(eq
=True, frozen
=True)
2871 class SpecifierSEA(Specifier
):
2873 def match(cls
, desc
, record
):
2877 return cls(record
=record
)
2879 def validate(self
, others
):
2880 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
:
2881 raise ValueError("sea is only valid in ld/st modes, not "
2882 "%s" % str(self
.record
.svp64
.mode
))
2885 if isinstance(spec
, SpecifierFF
):
2886 raise ValueError(f
"sea cannot be used in ff mode")
2888 def assemble(self
, insn
):
2889 selector
= insn
.select(record
=self
.record
)
2890 if selector
.mode
.sel
not in (0b10, 0b00):
2891 raise ValueError("sea is only valid for normal and els modes, "
2892 "not %d" % int(selector
.mode
.sel
))
2896 @_dataclasses.dataclass(eq
=True, frozen
=True)
2897 class SpecifierSat(Specifier
):
2902 def match(cls
, desc
, record
, etalon
, sign
):
2906 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.LDST_IMM
,
2908 raise ValueError("only normal, ld/st imm and "
2909 "ld/st idx modes supported")
2911 return cls(record
=record
, desc
=desc
, sign
=sign
)
2913 def assemble(self
, insn
):
2914 selector
= insn
.select(record
=self
.record
)
2915 selector
.mode
[0] = 0b1
2916 selector
.mode
[1] = 0b0
2917 selector
.N
= int(self
.sign
)
2920 @_dataclasses.dataclass(eq
=True, frozen
=True)
2921 class SpecifierSatS(SpecifierSat
):
2923 def match(cls
, desc
, record
):
2924 return super().match(desc
=desc
, record
=record
,
2925 etalon
="sats", sign
=True)
2928 @_dataclasses.dataclass(eq
=True, frozen
=True)
2929 class SpecifierSatU(SpecifierSat
):
2931 def match(cls
, desc
, record
):
2932 return super().match(desc
=desc
, record
=record
,
2933 etalon
="satu", sign
=False)
2936 @_dataclasses.dataclass(eq
=True, frozen
=True)
2937 class SpecifierMapReduce(Specifier
):
2941 def match(cls
, record
, RG
):
2942 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2943 raise ValueError("only normal and crop modes supported")
2945 return cls(record
=record
, RG
=RG
)
2947 def assemble(self
, insn
):
2948 selector
= insn
.select(record
=self
.record
)
2949 if self
.record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2950 raise ValueError("only normal and crop modes supported")
2951 selector
.mode
[0] = 0
2952 selector
.mode
[1] = 0
2953 selector
.mode
[2] = 1
2954 selector
.RG
= self
.RG
2957 @_dataclasses.dataclass(eq
=True, frozen
=True)
2958 class SpecifierMR(SpecifierMapReduce
):
2960 def match(cls
, desc
, record
):
2964 return super().match(record
=record
, RG
=False)
2967 @_dataclasses.dataclass(eq
=True, frozen
=True)
2968 class SpecifierMRR(SpecifierMapReduce
):
2970 def match(cls
, desc
, record
):
2974 return super().match(record
=record
, RG
=True)
2977 @_dataclasses.dataclass(eq
=True, frozen
=True)
2978 class SpecifierBranch(Specifier
):
2980 def match(cls
, desc
, record
, etalon
):
2984 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
2985 raise ValueError("only branch modes supported")
2987 return cls(record
=record
)
2990 @_dataclasses.dataclass(eq
=True, frozen
=True)
2991 class SpecifierAll(SpecifierBranch
):
2993 def match(cls
, desc
, record
):
2994 return super().match(desc
=desc
, record
=record
, etalon
="all")
2996 def assemble(self
, insn
):
2997 selector
= insn
.select(record
=self
.record
)
3001 @_dataclasses.dataclass(eq
=True, frozen
=True)
3002 class SpecifierSNZ(Specifier
):
3004 def match(cls
, desc
, record
):
3008 if record
.svp64
.mode
not in (_SVMode
.BRANCH
, _SVMode
.CROP
):
3009 raise ValueError("only branch and crop modes supported")
3011 return cls(record
=record
)
3013 def assemble(self
, insn
):
3014 selector
= insn
.select(record
=self
.record
)
3015 if self
.record
.svp64
.mode
in (_SVMode
.CROP
, _SVMode
.BRANCH
):
3017 if self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3020 raise ValueError("only branch and crop modes supported")
3023 @_dataclasses.dataclass(eq
=True, frozen
=True)
3024 class SpecifierSL(SpecifierBranch
):
3026 def match(cls
, desc
, record
):
3027 return super().match(desc
=desc
, record
=record
, etalon
="sl")
3029 def assemble(self
, insn
):
3030 selector
= insn
.select(record
=self
.record
)
3034 @_dataclasses.dataclass(eq
=True, frozen
=True)
3035 class SpecifierSLu(SpecifierBranch
):
3037 def match(cls
, desc
, record
):
3038 return super().match(desc
=desc
, record
=record
, etalon
="slu")
3040 def assemble(self
, insn
):
3041 selector
= insn
.select(record
=self
.record
)
3045 @_dataclasses.dataclass(eq
=True, frozen
=True)
3046 class SpecifierLRu(SpecifierBranch
):
3048 def match(cls
, desc
, record
):
3049 return super().match(desc
=desc
, record
=record
, etalon
="lru")
3051 def assemble(self
, insn
):
3052 selector
= insn
.select(record
=self
.record
)
3056 @_dataclasses.dataclass(eq
=True, frozen
=True)
3057 class SpecifierVSXX(SpecifierBranch
):
3062 def match(cls
, desc
, record
, etalon
, VSb
, VLi
):
3066 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3067 raise ValueError("only branch modes supported")
3069 return cls(record
=record
, VSb
=VSb
, VLi
=VLi
)
3071 def assemble(self
, insn
):
3072 selector
= insn
.select(record
=self
.record
)
3074 selector
.VSb
= int(self
.VSb
)
3075 selector
.VLi
= int(self
.VLi
)
3078 @_dataclasses.dataclass(eq
=True, frozen
=True)
3079 class SpecifierVS(SpecifierVSXX
):
3081 def match(cls
, desc
, record
):
3082 return super().match(desc
=desc
, record
=record
,
3083 etalon
="vs", VSb
=False, VLi
=False)
3086 @_dataclasses.dataclass(eq
=True, frozen
=True)
3087 class SpecifierVSi(SpecifierVSXX
):
3089 def match(cls
, desc
, record
):
3090 return super().match(desc
=desc
, record
=record
,
3091 etalon
="vsi", VSb
=False, VLi
=True)
3094 @_dataclasses.dataclass(eq
=True, frozen
=True)
3095 class SpecifierVSb(SpecifierVSXX
):
3097 def match(cls
, desc
, record
):
3098 return super().match(desc
=desc
, record
=record
,
3099 etalon
="vsb", VSb
=True, VLi
=False)
3102 @_dataclasses.dataclass(eq
=True, frozen
=True)
3103 class SpecifierVSbi(SpecifierVSXX
):
3105 def match(cls
, desc
, record
):
3106 return super().match(desc
=desc
, record
=record
,
3107 etalon
="vsbi", VSb
=True, VLi
=True)
3110 @_dataclasses.dataclass(eq
=True, frozen
=True)
3111 class SpecifierCTX(Specifier
):
3115 def match(cls
, desc
, record
, etalon
, CTi
):
3119 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3120 raise ValueError("only branch modes supported")
3122 return cls(record
=record
, CTi
=CTi
)
3124 def assemble(self
, insn
):
3125 selector
= insn
.select(record
=self
.record
)
3127 selector
.CTi
= int(self
.CTi
)
3130 @_dataclasses.dataclass(eq
=True, frozen
=True)
3131 class SpecifierCTR(SpecifierCTX
):
3133 def match(cls
, desc
, record
):
3134 return super().match(desc
=desc
, record
=record
,
3135 etalon
="ctr", CTi
=False)
3138 @_dataclasses.dataclass(eq
=True, frozen
=True)
3139 class SpecifierCTi(SpecifierCTX
):
3141 def match(cls
, desc
, record
):
3142 return super().match(desc
=desc
, record
=record
,
3143 etalon
="cti", CTi
=True)
3146 @_dataclasses.dataclass(eq
=True, frozen
=True)
3147 class SpecifierPI(Specifier
):
3149 def match(cls
, desc
, record
):
3153 if record
.svp64
.mode
not in [_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
]:
3154 raise ValueError("only ld/st imm/idx mode supported")
3156 return cls(record
=record
)
3158 def assemble(self
, insn
):
3159 selector
= insn
.select(record
=self
.record
)
3160 selector
.mode
[2] = 0b1
3164 @_dataclasses.dataclass(eq
=True, frozen
=True)
3165 class SpecifierLF(Specifier
):
3167 def match(cls
, desc
, record
):
3171 if record
.svp64
.mode
is not _SVMode
.LDST_IMM
:
3172 raise ValueError("only ld/st imm mode supported")
3174 return cls(record
=record
)
3176 def assemble(self
, insn
):
3177 selector
= insn
.select(record
=self
.record
)
3178 selector
.mode
[1] = 0
3182 @_dataclasses.dataclass(eq
=True, frozen
=True)
3183 class SpecifierVLi(Specifier
):
3185 def match(cls
, desc
, record
):
3189 return cls(record
=record
)
3191 def validate(self
, others
):
3193 if isinstance(spec
, SpecifierFF
):
3196 raise ValueError("VLi only allowed in failfirst")
3198 def assemble(self
, insn
):
3199 selector
= insn
.select(record
=self
.record
)
3200 selector
.mode
[1] = 1
3204 class Specifiers(tuple):
3239 def __new__(cls
, items
, record
):
3240 def transform(item
):
3241 for spec_cls
in cls
.SPECS
:
3242 spec
= spec_cls
.match(item
, record
=record
)
3243 if spec
is not None:
3245 raise ValueError(item
)
3247 # TODO: remove this hack
3248 items
= dict.fromkeys(items
)
3252 items
= tuple(items
)
3254 specs
= tuple(map(transform
, items
))
3255 for (index
, spec
) in enumerate(specs
):
3256 head
= specs
[:index
]
3257 tail
= specs
[index
+ 1:]
3258 spec
.validate(others
=(head
+ tail
))
3260 return super().__new
__(cls
, specs
)
3263 class SVP64OperandMeta(type):
3264 class SVP64NonZeroOperand(NonZeroOperand
):
3265 def assemble(self
, insn
, value
):
3266 if isinstance(value
, str):
3267 value
= int(value
, 0)
3268 if not isinstance(value
, int):
3269 raise ValueError("non-integer operand")
3271 # FIXME: this is really weird
3272 if self
.record
.name
in ("svstep", "svstep."):
3273 value
+= 1 # compensation
3275 return super().assemble(value
=value
, insn
=insn
)
3277 class SVP64XOStaticOperand(SpanStaticOperand
):
3278 def __init__(self
, record
, value
, span
):
3279 return super().__init
__(record
=record
, name
="XO",
3280 value
=value
, span
=span
)
3283 NonZeroOperand
: SVP64NonZeroOperand
,
3284 XOStaticOperand
: SVP64XOStaticOperand
,
3287 def __new__(metacls
, name
, bases
, ns
):
3289 for (index
, base_cls
) in enumerate(bases
):
3290 bases
[index
] = metacls
.__TRANSFORM
.get(base_cls
, base_cls
)
3292 bases
= tuple(bases
)
3294 return super().__new
__(metacls
, name
, bases
, ns
)
3297 class SVP64Operand(Operand
, metaclass
=SVP64OperandMeta
):
3300 return tuple(map(lambda bit
: (bit
+ 32), super().span
))
3304 def __init__(self
, insn
, record
):
3306 self
.__record
= record
3307 return super().__init
__()
3310 return self
.rm
.__doc
__
3313 return repr(self
.rm
)
3321 return self
.__record
3325 rm
= getattr(self
.insn
.prefix
.rm
, self
.record
.svp64
.mode
.name
.lower())
3327 # The idea behind these tables is that they are now literally
3328 # in identical format to insndb.csv and minor_xx.csv and can
3329 # be done precisely as that. The only thing to watch out for
3330 # is the insertion of Rc=1 as a "mask/value" bit and likewise
3331 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
3334 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
3335 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3336 # mode Rc mask Rc member
3338 (0b000000, 0b111000, "simple"), # simple (no Rc)
3339 (0b001000, 0b111100, "mr"), # mapreduce (no Rc)
3340 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3341 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3342 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3343 (0b001100, 0b111100, "rsvd"), # reserved
3345 mode
= int(self
.insn
.prefix
.rm
.normal
.mode
)
3346 search
= ((mode
<< 1) | self
.record
.Rc
)
3348 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
3349 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3350 # mode Rc mask Rc member
3351 # ironically/coincidentally this table is identical to NORMAL
3352 # mode except reserved in place of mr
3354 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3355 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3356 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3358 search
= ((int(self
.insn
.prefix
.rm
.ldst_imm
.mode
) << 1) |
3361 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
3362 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3363 # mode Rc mask Rc member
3365 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3366 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3367 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3369 search
= ((int(self
.insn
.prefix
.rm
.ldst_idx
.mode
) << 1) |
3372 elif self
.record
.svp64
.mode
is _SVMode
.CROP
:
3373 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
3374 # mode 3b mask 3b member
3376 (0b000000, 0b111000, "simple"), # simple
3377 (0b001000, 0b111000, "mr"), # mapreduce
3378 (0b010001, 0b010001, "ff3"), # ffirst, 3-bit CR
3379 (0b010000, 0b010000, "ff5"), # ffirst, 5-bit CR
3381 search
= ((int(self
.insn
.prefix
.rm
.crop
.mode
) << 1) |
3382 int(self
.record
.svp64
.extra_CR_3bit
))
3384 elif self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3388 (0b00, 0b11, "simple"), # simple
3389 (0b01, 0b11, "vls"), # VLset
3390 (0b10, 0b11, "ctr"), # CTR mode
3391 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
3393 # slightly weird: doesn't have a 5-bit "mode" field like others
3394 search
= int(self
.insn
.prefix
.rm
.branch
.mode
.sel
)
3397 if table
is not None:
3398 for (value
, mask
, field
) in table
:
3399 if field
.startswith("rsvd"):
3401 if ((value
& mask
) == (search
& mask
)):
3402 return getattr(rm
, field
)
3406 def __getattr__(self
, key
):
3407 if key
.startswith(f
"_{self.__class__.__name__}__"):
3408 return super().__getattribute
__(key
)
3410 return getattr(self
.rm
, key
)
3412 def __setattr__(self
, key
, value
):
3413 if key
.startswith(f
"_{self.__class__.__name__}__"):
3414 return super().__setattr
__(key
, value
)
3417 if not hasattr(rm
, key
):
3418 raise AttributeError(key
)
3420 return setattr(rm
, key
, value
)
3423 class SVP64Instruction(PrefixedInstruction
):
3424 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
3425 class Prefix(PrefixedInstruction
.Prefix
):
3427 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
3431 def select(self
, record
):
3432 return RMSelector(insn
=self
, record
=record
)
3437 for idx
in range(64):
3438 bit
= int(self
[idx
])
3440 return "".join(map(str, bits
))
3443 def assemble(cls
, record
, arguments
=None, specifiers
=None):
3444 insn
= super().assemble(record
=record
, arguments
=arguments
)
3446 specifiers
= Specifiers(items
=specifiers
, record
=record
)
3447 for specifier
in specifiers
:
3448 specifier
.assemble(insn
=insn
)
3450 insn
.prefix
.PO
= 0x1
3451 insn
.prefix
.id = 0x3
3455 def disassemble(self
, record
,
3457 style
=Style
.NORMAL
):
3459 if style
<= Style
.SHORT
:
3462 blob
= insn
.bytes(byteorder
=byteorder
)
3463 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
3466 blob_prefix
= blob(self
.prefix
)
3467 blob_suffix
= blob(self
.suffix
)
3469 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3470 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
3473 assert record
.svp64
is not None
3475 name
= f
"sv.{record.name}"
3477 rm
= self
.select(record
=record
)
3479 # convert specifiers to /x/y/z (sorted lexicographically)
3480 specifiers
= sorted(rm
.specifiers(record
=record
))
3481 if specifiers
: # if any add one extra to get the extra "/"
3482 specifiers
= ([""] + specifiers
)
3483 specifiers
= "/".join(specifiers
)
3485 # convert operands to " ,x,y,z"
3486 operands
= tuple(map(_operator
.itemgetter(1),
3487 self
.spec_dynamic_operands(record
=record
, style
=style
)))
3488 operands
= ",".join(operands
)
3489 if len(operands
) > 0: # if any separate with a space
3490 operands
= (" " + operands
)
3492 if style
<= Style
.LEGACY
:
3493 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3494 suffix
= WordInstruction
.integer(value
=int(self
.suffix
))
3495 yield from suffix
.disassemble(record
=record
,
3496 byteorder
=byteorder
, style
=style
)
3498 yield f
"{blob_prefix}{name}{specifiers}{operands}"
3500 yield f
"{blob_suffix}"
3502 if style
>= Style
.VERBOSE
:
3504 binary
= self
.binary
3505 spec
= self
.spec(record
=record
, prefix
="sv.")
3507 yield f
"{indent}spec"
3508 yield f
"{indent}{indent}{spec}"
3509 yield f
"{indent}pcode"
3510 for stmt
in record
.mdwn
.pcode
:
3511 yield f
"{indent}{indent}{stmt}"
3512 yield f
"{indent}binary"
3513 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
3514 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
3515 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
3516 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
3517 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
3518 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
3519 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
3520 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
3521 yield f
"{indent}opcodes"
3522 for opcode
in record
.opcodes
:
3523 yield f
"{indent}{indent}{opcode!r}"
3524 for operand
in self
.operands(record
=record
):
3525 yield from operand
.disassemble(insn
=self
,
3526 style
=style
, indent
=indent
)
3528 yield f
"{indent}{indent}{str(rm)}"
3529 for line
in rm
.disassemble(style
=style
):
3530 yield f
"{indent}{indent}{line}"
3534 def operands(cls
, record
):
3535 for operand
in super().operands(record
=record
):
3536 parent
= operand
.__class
__
3537 name
= f
"SVP64{parent.__name__}"
3538 bases
= (SVP64Operand
, parent
)
3539 child
= type(name
, bases
, {})
3540 yield child(**dict(operand
))
3543 def parse(stream
, factory
):
3545 return ("TODO" not in frozenset(entry
.values()))
3547 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
3548 entries
= _csv
.DictReader(lines
)
3549 entries
= filter(match
, entries
)
3550 return tuple(map(factory
, entries
))
3553 class MarkdownDatabase
:
3556 for (name
, desc
) in _ISA():
3559 (dynamic
, *static
) = desc
.regs
3560 operands
.extend(dynamic
)
3561 operands
.extend(static
)
3562 pcode
= PCode(iterable
=filter(str.strip
, desc
.pcode
))
3563 operands
= Operands(insn
=name
, operands
=operands
)
3564 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
3566 self
.__db
= dict(sorted(db
.items()))
3568 return super().__init
__()
3571 yield from self
.__db
.items()
3573 def __contains__(self
, key
):
3574 return self
.__db
.__contains
__(key
)
3576 def __getitem__(self
, key
):
3577 return self
.__db
.__getitem
__(key
)
3580 class FieldsDatabase
:
3583 df
= _DecodeFields()
3585 for (form
, fields
) in df
.instrs
.items():
3586 if form
in {"DQE", "TX"}:
3590 db
[_Form
[form
]] = Fields(fields
)
3594 return super().__init
__()
3596 def __getitem__(self
, key
):
3597 return self
.__db
.__getitem
__(key
)
3601 def __init__(self
, root
, mdwndb
):
3602 # The code below groups the instructions by name:section.
3603 # There can be multiple names for the same instruction.
3604 # The point is to capture different opcodes for the same instruction.
3606 records
= _collections
.defaultdict(set)
3607 path
= (root
/ "insndb.csv")
3608 with
open(path
, "r", encoding
="UTF-8") as stream
:
3609 for section
in sorted(parse(stream
, Section
.CSV
)):
3610 path
= (root
/ section
.path
)
3612 section
.Mode
.INTEGER
: IntegerOpcode
,
3613 section
.Mode
.PATTERN
: PatternOpcode
,
3615 factory
= _functools
.partial(
3616 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
3617 with
open(path
, "r", encoding
="UTF-8") as stream
:
3618 for insn
in parse(stream
, factory
):
3619 for name
in insn
.names
:
3620 records
[name
].add(insn
)
3621 sections
[name
] = section
3623 items
= sorted(records
.items())
3625 for (name
, multirecord
) in items
:
3626 records
[name
] = PPCMultiRecord(sorted(multirecord
))
3628 def exact_match(name
):
3629 record
= records
.get(name
)
3635 if not name
.endswith("l"):
3637 alias
= exact_match(name
[:-1])
3640 record
= records
[alias
]
3641 if "lk" not in record
.flags
:
3642 raise ValueError(record
)
3646 if not name
.endswith("a"):
3648 alias
= LK_match(name
[:-1])
3651 record
= records
[alias
]
3652 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
3653 raise ValueError(record
)
3654 if "AA" not in mdwndb
[name
].operands
:
3655 raise ValueError(record
)
3659 if not name
.endswith("."):
3661 alias
= exact_match(name
[:-1])
3664 record
= records
[alias
]
3665 if record
.Rc
is _RCOE
.NONE
:
3666 raise ValueError(record
)
3670 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
3671 for (name
, _
) in mdwndb
:
3672 if name
.startswith("sv."):
3675 for match
in matches
:
3677 if alias
is not None:
3681 section
= sections
[alias
]
3682 record
= records
[alias
]
3683 db
[name
] = (section
, record
)
3685 self
.__db
= dict(sorted(db
.items()))
3687 return super().__init
__()
3689 @_functools.lru_cache(maxsize
=512, typed
=False)
3690 def __getitem__(self
, key
):
3691 return self
.__db
.get(key
, (None, None))
3694 class SVP64Database
:
3695 def __init__(self
, root
, ppcdb
):
3697 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
3698 for (prefix
, _
, names
) in _os
.walk(root
):
3699 prefix
= _pathlib
.Path(prefix
)
3700 for name
in filter(lambda name
: pattern
.match(name
), names
):
3701 path
= (prefix
/ _pathlib
.Path(name
))
3702 with
open(path
, "r", encoding
="UTF-8") as stream
:
3703 db
.update(parse(stream
, SVP64Record
.CSV
))
3704 db
= {record
.name
:record
for record
in db
}
3706 self
.__db
= dict(sorted(db
.items()))
3707 self
.__ppcdb
= ppcdb
3709 return super().__init
__()
3711 def __getitem__(self
, key
):
3712 (_
, record
) = self
.__ppcdb
[key
]
3716 for name
in record
.names
:
3717 record
= self
.__db
.get(name
, None)
3718 if record
is not None:
3724 class Database(Node
):
3725 def __init__(self
, root
):
3726 root
= _pathlib
.Path(root
)
3727 mdwndb
= MarkdownDatabase()
3728 fieldsdb
= FieldsDatabase()
3729 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
3730 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
3734 opcodes
= _collections
.defaultdict(
3735 lambda: _collections
.defaultdict(set))
3737 for (name
, mdwn
) in mdwndb
:
3738 if name
.startswith("sv."):
3740 (section
, ppc
) = ppcdb
[name
]
3743 svp64
= svp64db
[name
]
3744 fields
= fieldsdb
[ppc
.form
]
3745 record
= Record(name
=name
,
3746 section
=section
, ppc
=ppc
, svp64
=svp64
,
3747 mdwn
=mdwn
, fields
=fields
)
3749 names
[record
.name
] = record
3750 opcodes
[section
][record
.PO
].add(record
)
3752 self
.__db
= sorted(db
)
3753 self
.__names
= dict(sorted(names
.items()))
3754 self
.__opcodes
= dict(sorted(opcodes
.items()))
3756 return super().__init
__()
3758 def subnodes(self
, match
=None):
3760 match
= lambda subnode
: True
3762 yield from filter(match
, self
)
3765 return repr(self
.__db
)
3768 yield from self
.__db
3770 @_functools.lru_cache(maxsize
=None)
3771 def __contains__(self
, key
):
3772 return self
.__getitem
__(key
) is not None
3774 @_functools.lru_cache(maxsize
=None)
3775 def __getitem__(self
, key
):
3776 if isinstance(key
, SVP64Instruction
):
3779 if isinstance(key
, Instruction
):
3782 sections
= sorted(self
.__opcodes
)
3783 for section
in sections
:
3784 group
= self
.__opcodes
[section
]
3785 for record
in group
[PO
]:
3786 if record
.match(key
=key
):
3791 elif isinstance(key
, str):
3792 return self
.__names
.get(key
)
3794 raise ValueError("instruction or name expected")