1 import collections
as _collections
2 import contextlib
as _contextlib
4 import dataclasses
as _dataclasses
6 import functools
as _functools
7 import inspect
as _inspect
9 import operator
as _operator
10 import pathlib
as _pathlib
12 import types
as _types
13 import typing
as _typing
16 from functools
import cached_property
18 from cached_property
import cached_property
20 from openpower
.decoder
.power_enums
import (
21 Function
as _Function
,
28 CRIn2Sel
as _CRIn2Sel
,
29 CROutSel
as _CROutSel
,
31 LDSTMode
as _LDSTMode
,
36 SVMaskSrc
as _SVMaskSrc
,
43 SVP64SubVL
as _SVP64SubVL
,
44 SVP64Pred
as _SVP64Pred
,
45 SVP64PredMode
as _SVP64PredMode
,
46 SVP64Width
as _SVP64Width
,
48 from openpower
.decoder
.selectable_int
import (
49 SelectableInt
as _SelectableInt
,
50 selectconcat
as _selectconcat
,
52 from openpower
.decoder
.power_fields
import (
55 DecodeFields
as _DecodeFields
,
57 from openpower
.decoder
.pseudo
.pagereader
import ISA
as _ISA
61 def __init__(self
, walk
):
63 return super().__init
__()
65 def __get__(self
, instance
, owner
):
69 return _functools
.partial(self
.__walk
, entity
)
74 def walk(clsself
, match
=None):
78 class DataclassMeta(type):
79 def __new__(metacls
, name
, bases
, ns
):
80 cls
= super().__new
__(metacls
, name
, bases
, ns
)
81 return _dataclasses
.dataclass(cls
, eq
=True, frozen
=True)
84 class Dataclass(Node
, metaclass
=DataclassMeta
):
86 def walk(clsself
, match
=None):
88 match
= lambda subnode
: True
90 def field_type(field
):
93 def field_value(field
):
94 return getattr(clsself
, field
.name
)
96 field
= (field_type
if isinstance(clsself
, type) else field_value
)
98 yield from filter(match
, map(field
, _dataclasses
.fields(clsself
)))
101 class Tuple(Node
, tuple):
102 def __init_subclass__(cls
, datatype
):
103 cls
.__datatype
= datatype
104 return super().__init
_subclass
__()
107 def walk(clsself
, match
=None):
109 match
= lambda subnode
: True
111 if isinstance(clsself
, type):
112 yield clsself
.__datatype
120 def __init__(self
, nodecls
, method
):
121 self
.__nodecls
= nodecls
122 self
.__method
= method
123 return super().__init
__()
127 return self
.__nodecls
129 @_contextlib.contextmanager
130 def __call__(self
, node
):
131 return self
.__method
(self
=self
, node
=node
)
134 class VisitorMeta(type):
135 def __init__(cls
, name
, bases
, ns
):
137 for (key
, value
) in ns
.items():
138 if isinstance(value
, VisitorMethod
):
139 if value
.type in cls
.__registry
:
140 raise AttributeError(f
"overriding visitor method: {key!r}")
141 cls
.__registry
[value
.type] = value
142 return super().__init
__(name
, bases
, ns
)
144 def __contains__(self
, nodecls
):
145 return self
.__registry
.__contains
__(nodecls
)
147 def __getitem__(self
, nodecls
):
148 return self
.__registry
.__getitem
__(nodecls
)
150 def __setitem__(self
, nodecls
, call
):
151 return self
.__registry
.__setitem
__(nodecls
, call
)
154 yield from self
.__registry
.items()
157 class Visitor(metaclass
=VisitorMeta
):
158 @_contextlib.contextmanager
159 def __call__(self
, node
):
160 (visitorcls
, nodecls
) = map(type, (self
, node
))
161 if nodecls
in visitorcls
:
162 handler
= visitorcls
[nodecls
]
163 with
handler(node
=node
) as ctx
:
170 def __init__(self
, nodecls
):
171 if not isinstance(nodecls
, type):
172 raise ValueError(nodecls
)
173 self
.__nodecls
= nodecls
174 return super().__init
__()
176 def __call__(self
, method
):
177 if not callable(method
):
178 raise ValueError(method
)
179 return VisitorMethod(nodecls
=self
.__nodecls
, method
=method
)
182 def walk(root
, match
=None):
183 nodes
= _collections
.deque([root
])
185 node
= nodes
.popleft()
186 nodes
.extend(node
.walk(match
=match
))
190 def visit(visitor
, node
):
191 with
visitor(node
=node
):
192 if isinstance(node
, Node
):
193 for subnode
in node
.walk():
194 visit(visitor
=visitor
, node
=subnode
)
197 @_functools.total_ordering
198 class Style(_enum
.Enum
):
199 LEGACY
= _enum
.auto()
201 NORMAL
= _enum
.auto()
202 VERBOSE
= _enum
.auto()
204 def __lt__(self
, other
):
205 if not isinstance(other
, self
.__class
__):
206 return NotImplemented
207 return (self
.value
< other
.value
)
210 @_functools.total_ordering
211 class Priority(_enum
.Enum
):
217 def _missing_(cls
, value
):
218 if isinstance(value
, str):
219 value
= value
.upper()
223 return super()._missing
_(value
)
225 def __lt__(self
, other
):
226 if not isinstance(other
, self
.__class
__):
227 return NotImplemented
229 # NOTE: the order is inversed, LOW < NORMAL < HIGH
230 return (self
.value
> other
.value
)
233 def dataclass(cls
, record
, keymap
=None, typemap
=None):
237 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
239 def transform(key_value
):
240 (key
, value
) = key_value
241 key
= keymap
.get(key
, key
)
242 hook
= typemap
.get(key
, lambda value
: value
)
243 if hook
is bool and value
in ("", "0"):
249 record
= dict(map(transform
, record
.items()))
250 for key
in frozenset(record
.keys()):
251 if record
[key
] == "":
257 @_functools.total_ordering
258 class Opcode(Dataclass
):
260 def __new__(cls
, value
):
261 if isinstance(value
, str):
262 value
= int(value
, 0)
263 if not isinstance(value
, int):
264 raise ValueError(value
)
266 if value
.bit_length() > 64:
267 raise ValueError(value
)
269 return super().__new
__(cls
, value
)
272 return self
.__repr
__()
275 return f
"{self:0{self.bit_length()}b}"
277 def bit_length(self
):
278 if super().bit_length() > 32:
282 class Value(Integer
):
291 def __lt__(self
, other
):
292 if not isinstance(other
, Opcode
):
293 return NotImplemented
294 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
297 return (self
.value
& self
.mask
)
300 return int(self
).__index
__()
303 def pattern(value
, mask
, bit_length
):
304 for bit
in range(bit_length
):
305 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
307 elif (value
& (1 << (bit_length
- bit
- 1))):
312 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
314 def match(self
, key
):
315 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
318 @_functools.total_ordering
319 class IntegerOpcode(Opcode
):
320 def __init__(self
, value
):
321 if value
.startswith("0b"):
322 mask
= int(("1" * len(value
[2:])), 2)
326 value
= Opcode
.Value(value
)
327 mask
= Opcode
.Mask(mask
)
329 return super().__init
__(value
=value
, mask
=mask
)
332 @_functools.total_ordering
333 class PatternOpcode(Opcode
):
334 def __init__(self
, pattern
):
335 if not isinstance(pattern
, str):
336 raise ValueError(pattern
)
338 (value
, mask
) = (0, 0)
339 for symbol
in pattern
:
340 if symbol
not in {"0", "1", "-"}:
341 raise ValueError(pattern
)
342 value |
= (symbol
== "1")
343 mask |
= (symbol
!= "-")
349 value
= Opcode
.Value(value
)
350 mask
= Opcode
.Mask(mask
)
352 return super().__init
__(value
=value
, mask
=mask
)
355 class PPCRecord(Dataclass
):
356 class FlagsMeta(type):
371 class Flags(Tuple
, datatype
=str, metaclass
=FlagsMeta
):
372 def __new__(cls
, flags
=frozenset()):
373 flags
= frozenset(flags
)
374 diff
= (flags
- frozenset(cls
))
376 raise ValueError(flags
)
377 return super().__new
__(cls
, sorted(flags
))
381 flags
: Flags
= Flags()
383 function
: _Function
= _Function
.NONE
384 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
385 in1
: _In1Sel
= _In1Sel
.NONE
386 in2
: _In2Sel
= _In2Sel
.NONE
387 in3
: _In3Sel
= _In3Sel
.NONE
388 out
: _OutSel
= _OutSel
.NONE
389 cr_in
: _CRInSel
= _CRInSel
.NONE
390 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
391 cr_out
: _CROutSel
= _CROutSel
.NONE
392 cry_in
: _CryIn
= _CryIn
.ZERO
393 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
394 upd
: _LDSTMode
= _LDSTMode
.NONE
395 Rc
: _RCOE
= _RCOE
.NONE
396 form
: _Form
= _Form
.NONE
398 unofficial
: bool = False
402 "internal op": "intop",
406 "ldst len": "ldst_len",
408 "CONDITIONS": "conditions",
411 def __lt__(self
, other
):
412 if not isinstance(other
, self
.__class
__):
413 return NotImplemented
414 lhs
= (self
.opcode
, self
.comment
)
415 rhs
= (other
.opcode
, other
.comment
)
419 def CSV(cls
, record
, opcode_cls
):
420 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
421 typemap
["opcode"] = opcode_cls
423 if record
["CR in"] == "BA_BB":
424 record
["cr_in"] = "BA"
425 record
["cr_in2"] = "BB"
429 for flag
in frozenset(PPCRecord
.Flags
):
430 if bool(record
.pop(flag
, "")):
432 record
["flags"] = PPCRecord
.Flags(flags
)
434 return dataclass(cls
, record
,
435 keymap
=PPCRecord
.__KEYMAP
,
440 return frozenset(self
.comment
.split("=")[-1].split("/"))
443 class PPCMultiRecord(Tuple
, datatype
=PPCRecord
):
444 def __getattr__(self
, attr
):
447 raise AttributeError(attr
)
448 return getattr(self
[0], attr
)
451 class SVP64Record(Dataclass
):
452 class ExtraMap(tuple):
454 @_dataclasses.dataclass(eq
=True, frozen
=True)
456 seltype
: _SelType
= _SelType
.NONE
457 reg
: _Reg
= _Reg
.NONE
460 return f
"{self.seltype.value}:{self.reg.name}"
462 def __new__(cls
, value
="0"):
463 if isinstance(value
, str):
464 def transform(value
):
465 (seltype
, reg
) = value
.split(":")
466 seltype
= _SelType(seltype
)
468 return cls
.Entry(seltype
=seltype
, reg
=reg
)
473 value
= map(transform
, value
.split(";"))
475 return super().__new
__(cls
, value
)
478 return repr(list(self
))
480 def __new__(cls
, value
=tuple()):
484 return super().__new
__(cls
, map(cls
.Extra
, value
))
487 return repr({index
:self
[index
] for index
in range(0, 4)})
490 ptype
: _SVPType
= _SVPType
.NONE
491 etype
: _SVEType
= _SVEType
.NONE
492 msrc
: _SVMaskSrc
= _SVMaskSrc
.NO
# MASK_SRC is active
493 in1
: _In1Sel
= _In1Sel
.NONE
494 in2
: _In2Sel
= _In2Sel
.NONE
495 in3
: _In3Sel
= _In3Sel
.NONE
496 out
: _OutSel
= _OutSel
.NONE
497 out2
: _OutSel
= _OutSel
.NONE
498 cr_in
: _CRInSel
= _CRInSel
.NONE
499 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
500 cr_out
: _CROutSel
= _CROutSel
.NONE
501 extra
: ExtraMap
= ExtraMap()
503 mode
: _SVMode
= _SVMode
.NORMAL
507 "CONDITIONS": "conditions",
516 def CSV(cls
, record
):
517 record
["insn"] = record
["insn"].split("=")[-1]
519 for key
in frozenset({
520 "in1", "in2", "in3", "CR in",
521 "out", "out2", "CR out",
527 if record
["CR in"] == "BA_BB":
528 record
["cr_in"] = "BA"
529 record
["cr_in2"] = "BB"
533 for idx
in range(0, 4):
534 extra
.append(record
.pop(f
"{idx}"))
536 record
["extra"] = cls
.ExtraMap(extra
)
538 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
543 "in1", "in2", "in3", "cr_in", "cr_in2",
544 "out", "out2", "cr_out",
559 for index
in range(0, 4):
560 for entry
in self
.extra
[index
]:
561 extras
[entry
.seltype
][entry
.reg
] = idxmap
[index
]
563 for (seltype
, regs
) in extras
.items():
564 idx
= regs
.get(reg
, _SVExtra
.NONE
)
565 if idx
is not _SVExtra
.NONE
:
566 yield (reg
, seltype
, idx
)
573 # has the word "in", it is a SelType.SRC "out" -> DST
574 # in1/2/3 and CR in are SRC, and must match only against "s:NN"
575 # out/out1 and CR out are DST, and must match only against "d:NN"
576 keytype
= _SelType
.SRC
if ("in" in key
) else _SelType
.DST
577 sel
= sels
[key
] = getattr(self
, key
)
578 reg
= regs
[key
] = _Reg(sel
)
579 seltypes
[key
] = _SelType
.NONE
580 idxs
[key
] = _SVExtra
.NONE
581 for (reg
, seltype
, idx
) in extra(reg
.alias
):
582 if keytype
!= seltype
: # only check SRC-to-SRC and DST-to-DST
584 if idx
!= idxs
[key
] and idxs
[key
] is not _SVExtra
.NONE
:
585 raise ValueError(idx
)
588 seltypes
[key
] = seltype
590 if sels
["cr_in"] is _CRInSel
.BA_BB
:
591 sels
["cr_in"] = _CRIn2Sel
.BA
592 sels
["cr_in2"] = _CRIn2Sel
.BB
593 idxs
["cr_in2"] = idxs
["cr_in"]
594 for key
in ("cr_in", "cr_in2"):
595 regs
[key
] = _Reg(sels
[key
])
596 seltype
[key
] = _SelType
.SRC
603 "seltype": seltypes
[key
],
607 return _types
.MappingProxyType(records
)
609 extra_idx_in1
= property(lambda self
: self
.extras
["in1"]["idx"])
610 extra_idx_in2
= property(lambda self
: self
.extras
["in2"]["idx"])
611 extra_idx_in3
= property(lambda self
: self
.extras
["in3"]["idx"])
612 extra_idx_out
= property(lambda self
: self
.extras
["out"]["idx"])
613 extra_idx_out2
= property(lambda self
: self
.extras
["out2"]["idx"])
614 extra_idx_cr_in
= property(lambda self
: self
.extras
["cr_in"]["idx"])
615 extra_idx_cr_in2
= property(lambda self
: self
.extras
["cr_in2"]["idx"])
616 extra_idx_cr_out
= property(lambda self
: self
.extras
["cr_out"]["idx"])
621 for idx
in range(0, 4):
622 for entry
in self
.extra
[idx
]:
623 if entry
.seltype
is _SelType
.DST
:
624 if extra
is not None:
625 raise ValueError(self
.svp64
)
629 if _RegType(extra
.reg
) not in (_RegType
.CR_3BIT
, _RegType
.CR_5BIT
):
630 raise ValueError(self
.svp64
)
635 def extra_CR_3bit(self
):
636 return (_RegType(self
.extra_CR
.reg
) is _RegType
.CR_3BIT
)
640 def __init__(self
, value
=(0, 32)):
641 if isinstance(value
, str):
642 (start
, end
) = map(int, value
.split(":"))
645 if start
< 0 or end
< 0 or start
>= end
:
646 raise ValueError(value
)
651 return super().__init
__()
654 return (self
.__end
- self
.__start
+ 1)
657 return f
"[{self.__start}:{self.__end}]"
660 yield from range(self
.start
, (self
.end
+ 1))
662 def __reversed__(self
):
663 return tuple(reversed(tuple(self
)))
674 class Section(Dataclass
):
675 class Mode(_enum
.Enum
):
676 INTEGER
= _enum
.auto()
677 PATTERN
= _enum
.auto()
680 def _missing_(cls
, value
):
681 if isinstance(value
, str):
682 return cls
[value
.upper()]
683 return super()._missing
_(value
)
686 def __new__(cls
, value
=None):
687 if isinstance(value
, str):
688 if value
.upper() == "NONE":
691 value
= int(value
, 0)
695 return super().__new
__(cls
, value
)
701 return (bin(self
) if self
else "None")
707 opcode
: IntegerOpcode
= None
708 priority
: Priority
= Priority
.NORMAL
710 def __lt__(self
, other
):
711 if not isinstance(other
, self
.__class
__):
712 return NotImplemented
713 return (self
.priority
< other
.priority
)
716 def CSV(cls
, record
):
717 keymap
= {"path": "csv"}
718 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
719 if record
["opcode"] == "NONE":
720 typemap
["opcode"] = lambda _
: None
722 return dataclass(cls
, record
, typemap
=typemap
, keymap
=keymap
)
726 def __init__(self
, items
):
727 if isinstance(items
, dict):
728 items
= items
.items()
731 (name
, bitrange
) = item
732 return (name
, tuple(bitrange
.values()))
734 self
.__mapping
= dict(map(transform
, items
))
736 return super().__init
__()
739 return repr(self
.__mapping
)
742 yield from self
.__mapping
.items()
744 def __contains__(self
, key
):
745 return self
.__mapping
.__contains
__(key
)
747 def __getitem__(self
, key
):
748 return self
.__mapping
.get(key
, None)
763 def __init__(self
, insn
, operands
):
765 "b": {"target_addr": TargetAddrOperandLI
},
766 "ba": {"target_addr": TargetAddrOperandLI
},
767 "bl": {"target_addr": TargetAddrOperandLI
},
768 "bla": {"target_addr": TargetAddrOperandLI
},
769 "bc": {"target_addr": TargetAddrOperandBD
},
770 "bca": {"target_addr": TargetAddrOperandBD
},
771 "bcl": {"target_addr": TargetAddrOperandBD
},
772 "bcla": {"target_addr": TargetAddrOperandBD
},
773 "addpcis": {"D": DOperandDX
},
774 "fishmv": {"D": DOperandDX
},
775 "fmvis": {"D": DOperandDX
},
778 "SVi": NonZeroOperand
,
779 "SVd": NonZeroOperand
,
780 "SVxd": NonZeroOperand
,
781 "SVyd": NonZeroOperand
,
782 "SVzd": NonZeroOperand
,
784 "D": SignedImmediateOperand
,
788 "SIM": SignedOperand
,
789 "SVD": SignedOperand
,
790 "SVDS": SignedOperand
,
791 "RSp": GPRPairOperand
,
792 "RTp": GPRPairOperand
,
793 "FRAp": FPRPairOperand
,
794 "FRBp": FPRPairOperand
,
795 "FRSp": FPRPairOperand
,
796 "FRTp": FPRPairOperand
,
798 custom_immediates
= {
804 for operand
in operands
:
808 (name
, value
) = operand
.split("=")
809 mapping
[name
] = (StaticOperand
, {
815 if name
.endswith(")"):
816 name
= name
.replace("(", " ").replace(")", "")
817 (imm_name
, _
, name
) = name
.partition(" ")
821 if imm_name
is not None:
822 imm_cls
= custom_immediates
.get(imm_name
, ImmediateOperand
)
824 if insn
in custom_insns
and name
in custom_insns
[insn
]:
825 cls
= custom_insns
[insn
][name
]
826 elif name
in custom_fields
:
827 cls
= custom_fields
[name
]
828 elif name
in _Reg
.__members
__:
830 if reg
in self
.__class
__.__GPR
_PAIRS
:
832 elif reg
in self
.__class
__.__FPR
_PAIRS
:
835 regtype
= _RegType
[name
]
836 if regtype
is _RegType
.GPR
:
838 elif regtype
is _RegType
.FPR
:
840 elif regtype
is _RegType
.CR_3BIT
:
842 elif regtype
is _RegType
.CR_5BIT
:
845 if imm_name
is not None:
846 mapping
[imm_name
] = (imm_cls
, {"name": imm_name
})
847 mapping
[name
] = (cls
, {"name": name
})
851 for (name
, (cls
, kwargs
)) in mapping
.items():
852 kwargs
= dict(kwargs
)
853 kwargs
["name"] = name
854 if issubclass(cls
, StaticOperand
):
855 static
.append((cls
, kwargs
))
856 elif issubclass(cls
, DynamicOperand
):
857 dynamic
.append((cls
, kwargs
))
859 raise ValueError(name
)
861 self
.__mapping
= mapping
862 self
.__static
= tuple(static
)
863 self
.__dynamic
= tuple(dynamic
)
865 return super().__init
__()
868 for (_
, items
) in self
.__mapping
.items():
869 (cls
, kwargs
) = items
873 return self
.__mapping
.__repr
__()
875 def __contains__(self
, key
):
876 return self
.__mapping
.__contains
__(key
)
878 def __getitem__(self
, key
):
879 return self
.__mapping
.__getitem
__(key
)
887 return self
.__dynamic
890 class Arguments(tuple):
891 def __new__(cls
, record
, arguments
, operands
):
892 operands
= iter(tuple(operands
))
893 arguments
= iter(tuple(arguments
))
898 operand
= next(operands
)
899 except StopIteration:
903 argument
= next(arguments
)
904 except StopIteration:
905 raise ValueError("operands count mismatch")
907 if isinstance(operand
, ImmediateOperand
):
908 argument
= argument
.replace("(", " ").replace(")", "")
909 (imm_argument
, _
, argument
) = argument
.partition(" ")
911 (imm_operand
, operand
) = (operand
, next(operands
))
912 except StopIteration:
913 raise ValueError("operands count mismatch")
914 items
.append((imm_argument
, imm_operand
))
915 items
.append((argument
, operand
))
919 except StopIteration:
922 raise ValueError("operands count mismatch")
924 return super().__new
__(cls
, items
)
927 class PCode(Tuple
, datatype
=str):
931 class MarkdownRecord(Dataclass
):
936 @_functools.total_ordering
937 class Record(Dataclass
):
943 svp64
: SVP64Record
= None
947 if self
.svp64
is not None:
948 return self
.svp64
.extras
950 return _types
.MappingProxyType({})
954 return self
.mdwn
.pcode
956 def __lt__(self
, other
):
957 if not isinstance(other
, Record
):
958 return NotImplemented
959 lhs
= (min(self
.opcodes
), self
.name
)
960 rhs
= (min(other
.opcodes
), other
.name
)
965 return (self
.static_operands
+ self
.dynamic_operands
)
968 def static_operands(self
):
970 operands
.append(POStaticOperand(record
=self
, value
=self
.PO
))
972 operands
.append(XOStaticOperand(
974 value
=ppc
.opcode
.value
,
975 span
=self
.section
.bitsel
,
977 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
978 operands
.append(cls(record
=self
, **kwargs
))
979 return tuple(operands
)
982 def dynamic_operands(self
):
984 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
985 operands
.append(cls(record
=self
, **kwargs
))
986 return tuple(operands
)
991 return int("".join(str(int(mapping
[bit
])) \
992 for bit
in sorted(mapping
)), 2)
994 def PO_XO(value
, mask
, opcode
, bits
):
997 for (src
, dst
) in enumerate(reversed(bits
)):
998 value
[dst
] = ((opcode
.value
& (1 << src
)) != 0)
999 mask
[dst
] = ((opcode
.mask
& (1 << src
)) != 0)
1000 return (value
, mask
)
1002 def PO(value
, mask
, opcode
, bits
):
1003 return PO_XO(value
=value
, mask
=mask
, opcode
=opcode
, bits
=bits
)
1005 def XO(value
, mask
, opcode
, bits
):
1006 (value
, mask
) = PO_XO(value
=value
, mask
=mask
,
1007 opcode
=opcode
, bits
=bits
)
1008 for (op_cls
, op_kwargs
) in self
.mdwn
.operands
.static
:
1009 operand
= op_cls(record
=self
, **op_kwargs
)
1010 for (src
, dst
) in enumerate(reversed(operand
.span
)):
1011 value
[dst
] = ((operand
.value
& (1 << src
)) != 0)
1013 return (value
, mask
)
1016 value
= {bit
:False for bit
in range(32)}
1017 mask
= {bit
:False for bit
in range(32)}
1018 if self
.section
.opcode
is not None:
1019 (value
, mask
) = PO(value
=value
, mask
=mask
,
1020 opcode
=self
.section
.opcode
, bits
=range(0, 6))
1021 for ppc
in self
.ppc
:
1022 pairs
.append(XO(value
=value
, mask
=mask
,
1023 opcode
=ppc
.opcode
, bits
=self
.section
.bitsel
))
1026 for (value
, mask
) in pairs
:
1027 value
= Opcode
.Value(binary(value
))
1028 mask
= Opcode
.Mask(binary(mask
))
1029 result
.append(Opcode(value
=value
, mask
=mask
))
1031 return tuple(result
)
1035 opcode
= self
.section
.opcode
1037 opcode
= self
.ppc
[0].opcode
1038 if isinstance(opcode
, PatternOpcode
):
1039 value
= int(opcode
.value
)
1040 bits
= opcode
.value
.bit_length()
1041 return int(_SelectableInt(value
=value
, bits
=bits
)[0:6])
1043 return int(opcode
.value
)
1047 return tuple(ppc
.opcode
for ppc
in self
.ppc
)
1049 def match(self
, key
):
1050 for opcode
in self
.opcodes
:
1051 if opcode
.match(key
):
1058 return self
.svp64
.mode
1078 if self
.svp64
is None:
1084 return self
.ppc
.cr_in
1088 return self
.ppc
.cr_in2
1092 return self
.ppc
.cr_out
1094 ptype
= property(lambda self
: self
.svp64
.ptype
)
1095 etype
= property(lambda self
: self
.svp64
.etype
)
1097 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
1098 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
1099 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
1100 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
1101 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
1102 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
1103 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
1104 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
1106 def __contains__(self
, key
):
1107 return self
.mdwn
.operands
.__contains
__(key
)
1109 def __getitem__(self
, key
):
1110 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
1111 return cls(record
=self
, **kwargs
)
1115 if "Rc" not in self
:
1117 return self
["Rc"].value
1121 def __init__(self
, record
, name
):
1122 self
.__record
= record
1126 yield ("record", self
.record
)
1127 yield ("name", self
.__name
)
1130 return f
"{self.__class__.__name__}({self.name})"
1138 return self
.__record
1142 return self
.record
.fields
[self
.name
]
1144 def assemble(self
, insn
):
1145 raise NotImplementedError()
1147 def disassemble(self
, insn
,
1148 style
=Style
.NORMAL
, indent
=""):
1149 raise NotImplementedError()
1152 class DynamicOperand(Operand
):
1153 def assemble(self
, insn
, value
):
1155 if isinstance(value
, str):
1156 value
= int(value
, 0)
1158 raise ValueError("signed operands not allowed")
1161 def disassemble(self
, insn
,
1162 style
=Style
.NORMAL
, indent
=""):
1166 if style
>= Style
.VERBOSE
:
1167 span
= map(str, span
)
1168 yield f
"{indent}{self.name}"
1169 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1170 yield f
"{indent}{indent}{', '.join(span)}"
1172 yield str(int(value
))
1175 class SignedOperand(DynamicOperand
):
1176 def assemble(self
, insn
, value
):
1177 if isinstance(value
, str):
1178 value
= int(value
, 0)
1179 return super().assemble(value
=value
, insn
=insn
)
1181 def assemble(self
, insn
, value
):
1183 if isinstance(value
, str):
1184 value
= int(value
, 0)
1187 def disassemble(self
, insn
,
1188 style
=Style
.NORMAL
, indent
=""):
1190 value
= insn
[span
].to_signed_int()
1191 sign
= "-" if (value
< 0) else ""
1194 if style
>= Style
.VERBOSE
:
1195 span
= map(str, span
)
1196 yield f
"{indent}{self.name}"
1197 yield f
"{indent}{indent}{sign}{value}"
1198 yield f
"{indent}{indent}{', '.join(span)}"
1200 yield f
"{sign}{value}"
1203 class StaticOperand(Operand
):
1204 def __init__(self
, record
, name
, value
):
1205 self
.__value
= value
1206 return super().__init
__(record
=record
, name
=name
)
1209 yield ("value", self
.__value
)
1210 yield from super().__iter
__()
1213 return f
"{self.__class__.__name__}({self.name}, value={self.value})"
1219 def assemble(self
, insn
):
1220 insn
[self
.span
] = self
.value
1222 def disassemble(self
, insn
,
1223 style
=Style
.NORMAL
, indent
=""):
1227 if style
>= Style
.VERBOSE
:
1228 span
= map(str, span
)
1229 yield f
"{indent}{self.name}"
1230 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1231 yield f
"{indent}{indent}{', '.join(span)}"
1233 yield str(int(value
))
1236 class SpanStaticOperand(StaticOperand
):
1237 def __init__(self
, record
, name
, value
, span
):
1238 self
.__span
= tuple(span
)
1239 return super().__init
__(record
=record
, name
=name
, value
=value
)
1242 yield ("span", self
.__span
)
1243 yield from super().__iter
__()
1250 class POStaticOperand(SpanStaticOperand
):
1251 def __init__(self
, record
, value
):
1252 return super().__init
__(record
=record
, name
="PO",
1253 value
=value
, span
=range(0, 6))
1256 for (key
, value
) in super().__iter
__():
1257 if key
not in {"name", "span"}:
1261 class XOStaticOperand(SpanStaticOperand
):
1262 def __init__(self
, record
, value
, span
):
1263 bits
= record
.section
.bitsel
1264 value
= _SelectableInt(value
=value
, bits
=len(bits
))
1265 span
= dict(zip(bits
, range(len(bits
))))
1266 span_rev
= {value
:key
for (key
, value
) in span
.items()}
1268 # This part is tricky: we cannot use record.operands,
1269 # as this code is called by record.static_operands method.
1270 for (cls
, kwargs
) in record
.mdwn
.operands
:
1271 operand
= cls(record
=record
, **kwargs
)
1272 for idx
in operand
.span
:
1273 rev
= span
.pop(idx
, None)
1275 span_rev
.pop(rev
, None)
1277 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1278 span
= tuple(span
.keys())
1280 return super().__init
__(record
=record
, name
="XO",
1281 value
=value
, span
=span
)
1284 for (key
, value
) in super().__iter
__():
1285 if key
not in {"name"}:
1289 class ImmediateOperand(DynamicOperand
):
1293 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1297 class NonZeroOperand(DynamicOperand
):
1298 def assemble(self
, insn
, value
):
1299 if isinstance(value
, str):
1300 value
= int(value
, 0)
1301 if not isinstance(value
, int):
1302 raise ValueError("non-integer operand")
1304 raise ValueError("non-zero operand")
1306 return super().assemble(value
=value
, insn
=insn
)
1308 def disassemble(self
, insn
,
1309 style
=Style
.NORMAL
, indent
=""):
1313 if style
>= Style
.VERBOSE
:
1314 span
= map(str, span
)
1315 yield f
"{indent}{self.name}"
1316 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1317 yield f
"{indent}{indent}{', '.join(span)}"
1319 yield str(int(value
) + 1)
1322 class ExtendableOperand(DynamicOperand
):
1323 def sv_spec_enter(self
, value
, span
):
1324 return (value
, span
)
1326 def sv_spec(self
, insn
):
1330 span
= tuple(map(str, span
))
1332 if isinstance(insn
, SVP64Instruction
):
1333 (origin_value
, origin_span
) = (value
, span
)
1334 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1336 for extra_idx
in self
.extra_idx
:
1337 if self
.record
.etype
is _SVEType
.EXTRA3
:
1338 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1339 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1340 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1342 raise ValueError(self
.record
.etype
)
1345 vector
= bool(spec
[0])
1346 spec_span
= spec
.__class
__
1347 if self
.record
.etype
is _SVEType
.EXTRA3
:
1348 spec_span
= tuple(map(str, spec_span
[1, 2]))
1350 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1351 spec_span
= tuple(map(str, spec_span
[1,]))
1352 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1355 spec_span
= (spec_span
+ ("{0}",))
1357 spec_span
= (("{0}",) + spec_span
)
1359 raise ValueError(self
.record
.etype
)
1361 vector_shift
= (2 + (5 - value
.bits
))
1362 scalar_shift
= value
.bits
1363 spec_shift
= (5 - value
.bits
)
1365 bits
= (len(span
) + len(spec_span
))
1366 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1367 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1369 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1370 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1372 value
= ((spec
<< scalar_shift
) | value
)
1373 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1375 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1376 origin_value
=origin_value
, origin_span
=origin_span
)
1378 return (vector
, value
, span
)
1380 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1381 return (value
, span
)
1384 def extra_idx(self
):
1385 for (key
, record
) in self
.record
.svp64
.extras
.items():
1386 if record
["reg"].alias
is self
.extra_reg
.alias
:
1390 def extra_reg(self
):
1391 return _Reg(self
.name
)
1393 def remap(self
, value
, vector
):
1394 raise NotImplementedError()
1396 def assemble(self
, value
, insn
, prefix
):
1399 if isinstance(value
, str):
1400 value
= value
.lower()
1401 if value
.startswith("%"):
1403 if value
.startswith("*"):
1404 if not isinstance(insn
, SVP64Instruction
):
1405 raise ValueError(value
)
1408 if value
.startswith(prefix
):
1409 if (self
.extra_reg
.or_zero
and (value
== f
"{prefix}0")):
1410 raise ValueError(value
)
1411 value
= value
[len(prefix
):]
1412 value
= int(value
, 0)
1414 if isinstance(insn
, SVP64Instruction
):
1415 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1417 for extra_idx
in self
.extra_idx
:
1418 if self
.record
.etype
is _SVEType
.EXTRA3
:
1419 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1420 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1421 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1423 raise ValueError(self
.record
.etype
)
1425 return super().assemble(value
=value
, insn
=insn
)
1427 def disassemble(self
, insn
,
1428 style
=Style
.NORMAL
, prefix
="", indent
=""):
1429 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1431 if (self
.extra_reg
.or_zero
and (value
== 0)):
1434 if style
>= Style
.VERBOSE
:
1435 mode
= "vector" if vector
else "scalar"
1436 yield f
"{indent}{self.name} ({mode})"
1437 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1438 yield f
"{indent}{indent}{', '.join(span)}"
1439 if isinstance(insn
, SVP64Instruction
):
1440 for extra_idx
in frozenset(self
.extra_idx
):
1441 if self
.record
.etype
is _SVEType
.NONE
:
1442 yield f
"{indent}{indent}extra[none]"
1444 etype
= repr(self
.record
.etype
).lower()
1445 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1447 vector
= "*" if vector
else ""
1448 yield f
"{vector}{prefix}{int(value)}"
1451 class SimpleRegisterOperand(ExtendableOperand
):
1452 def remap(self
, value
, vector
):
1454 extra
= (value
& 0b11)
1455 value
= (value
>> 2)
1457 extra
= (value
>> 5)
1458 value
= (value
& 0b11111)
1460 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1461 # (and shrink to a single bit if ok)
1462 if self
.record
.etype
is _SVEType
.EXTRA2
:
1464 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1465 assert (extra
& 0b01) == 0, \
1466 ("vector field %s cannot fit into EXTRA2" % value
)
1467 extra
= (0b10 |
(extra
>> 1))
1469 # range is r0-r63 in increments of 1
1470 assert (extra
>> 1) == 0, \
1471 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1473 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1475 # EXTRA3 vector bit needs marking
1478 raise ValueError(self
.record
.etype
)
1480 return (value
, extra
)
1483 class GPROperand(SimpleRegisterOperand
):
1484 def assemble(self
, insn
, value
):
1485 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1487 def disassemble(self
, insn
,
1488 style
=Style
.NORMAL
, indent
=""):
1489 prefix
= "" if (style
<= Style
.SHORT
) else "r"
1490 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1491 style
=style
, indent
=indent
)
1494 class GPRPairOperand(GPROperand
):
1498 class FPROperand(SimpleRegisterOperand
):
1499 def assemble(self
, insn
, value
):
1500 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1502 def disassemble(self
, insn
,
1503 style
=Style
.NORMAL
, indent
=""):
1504 prefix
= "" if (style
<= Style
.SHORT
) else "f"
1505 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1506 style
=style
, indent
=indent
)
1509 class FPRPairOperand(FPROperand
):
1513 class ConditionRegisterFieldOperand(ExtendableOperand
):
1514 def pattern(name_pattern
):
1515 (name
, pattern
) = name_pattern
1516 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1525 CR
= r
"(?:CR|cr)([0-9]+)"
1527 BIT
= rf
"({'|'.join(CONDS.keys())})"
1528 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1529 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1530 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1531 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1532 XCR
= fr
"{CR}\.{BIT}"
1533 PATTERNS
= tuple(map(pattern
, (
1538 ("BIT+CR", (LBIT
+ CR
)),
1539 ("CR+BIT", (CR
+ RBIT
)),
1540 ("BIT+CR*N", (LBIT
+ CRN
)),
1541 ("CR*N+BIT", (CRN
+ RBIT
)),
1542 ("BIT+N*CR", (LBIT
+ NCR
)),
1543 ("N*CR+BIT", (NCR
+ RBIT
)),
1546 def remap(self
, value
, vector
, regtype
):
1547 if regtype
is _RegType
.CR_5BIT
:
1548 subvalue
= (value
& 0b11)
1552 extra
= (value
& 0b1111)
1555 extra
= (value
>> 3)
1558 if self
.record
.etype
is _SVEType
.EXTRA2
:
1560 assert (extra
& 0b111) == 0, \
1561 "vector CR cannot fit into EXTRA2"
1562 extra
= (0b10 |
(extra
>> 3))
1564 assert (extra
>> 1) == 0, \
1565 "scalar CR cannot fit into EXTRA2"
1567 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1569 assert (extra
& 0b11) == 0, \
1570 "vector CR cannot fit into EXTRA3"
1571 extra
= (0b100 |
(extra
>> 2))
1573 assert (extra
>> 2) == 0, \
1574 "scalar CR cannot fit into EXTRA3"
1577 if regtype
is _RegType
.CR_5BIT
:
1578 value
= ((value
<< 2) | subvalue
)
1580 return (value
, extra
)
1582 def assemble(self
, insn
, value
):
1583 if isinstance(value
, str):
1586 if value
.startswith("*"):
1587 if not isinstance(insn
, SVP64Instruction
):
1588 raise ValueError(value
)
1592 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1593 match
= pattern
.match(value
)
1594 if match
is not None:
1595 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1596 values
= match
.groups()
1597 match
= dict(zip(keys
, values
))
1598 CR
= int(match
["CR"])
1602 N
= int(match
.get("N", "1"))
1603 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1604 value
= ((CR
* N
) + BIT
)
1611 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1613 def disassemble(self
, insn
,
1614 style
=Style
.NORMAL
, prefix
="", indent
=""):
1615 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1617 if style
>= Style
.VERBOSE
:
1618 mode
= "vector" if vector
else "scalar"
1619 yield f
"{indent}{self.name} ({mode})"
1620 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1621 yield f
"{indent}{indent}{', '.join(span)}"
1622 if isinstance(insn
, SVP64Instruction
):
1623 for extra_idx
in frozenset(self
.extra_idx
):
1624 if self
.record
.etype
is _SVEType
.NONE
:
1625 yield f
"{indent}{indent}extra[none]"
1627 etype
= repr(self
.record
.etype
).lower()
1628 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1630 vector
= "*" if vector
else ""
1631 CR
= int(value
>> 2)
1633 cond
= ("lt", "gt", "eq", "so")[CC
]
1634 if style
>= Style
.NORMAL
:
1636 if isinstance(insn
, SVP64Instruction
):
1637 yield f
"{vector}cr{CR}.{cond}"
1639 yield f
"4*cr{CR}+{cond}"
1643 yield f
"{vector}{prefix}{int(value)}"
1646 class CR3Operand(ConditionRegisterFieldOperand
):
1647 def remap(self
, value
, vector
):
1648 return super().remap(value
=value
, vector
=vector
,
1649 regtype
=_RegType
.CR_3BIT
)
1652 class CR5Operand(ConditionRegisterFieldOperand
):
1653 def remap(self
, value
, vector
):
1654 return super().remap(value
=value
, vector
=vector
,
1655 regtype
=_RegType
.CR_5BIT
)
1657 def sv_spec_enter(self
, value
, span
):
1658 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1659 return (value
, span
)
1661 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1662 value
= _selectconcat(value
, origin_value
[3:5])
1664 return (value
, span
)
1667 class EXTSOperand(SignedOperand
):
1668 field
: str # real name to report
1669 nz
: int = 0 # number of zeros
1670 fmt
: str = "d" # integer formatter
1672 def __init__(self
, record
, name
, field
, nz
=0, fmt
="d"):
1673 self
.__field
= field
1676 return super().__init
__(record
=record
, name
=name
)
1692 return self
.record
.fields
[self
.field
]
1694 def assemble(self
, insn
, value
):
1696 if isinstance(value
, str):
1697 value
= int(value
, 0)
1698 insn
[span
] = (value
>> self
.nz
)
1700 def disassemble(self
, insn
,
1701 style
=Style
.NORMAL
, indent
=""):
1703 value
= insn
[span
].to_signed_int()
1704 sign
= "-" if (value
< 0) else ""
1705 value
= (abs(value
) << self
.nz
)
1707 if style
>= Style
.VERBOSE
:
1708 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1709 zeros
= ("0" * self
.nz
)
1710 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1711 yield f
"{indent * 1}{hint}"
1712 yield f
"{indent * 2}{self.field}"
1713 yield f
"{indent * 3}{sign}{value:{self.fmt}}"
1714 yield f
"{indent * 3}{', '.join(span)}"
1716 yield f
"{sign}{value:{self.fmt}}"
1719 class TargetAddrOperand(EXTSOperand
):
1720 def __init__(self
, record
, name
, field
):
1721 return super().__init
__(record
=record
, name
=name
, field
=field
,
1725 class TargetAddrOperandLI(TargetAddrOperand
):
1726 def __init__(self
, record
, name
):
1727 return super().__init
__(record
=record
, name
=name
, field
="LI")
1730 class TargetAddrOperandBD(TargetAddrOperand
):
1731 def __init__(self
, record
, name
):
1732 return super().__init
__(record
=record
, name
=name
, field
="BD")
1735 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1736 def __init__(self
, record
, name
):
1737 return super().__init
__(record
=record
, name
=name
, field
="DS", nz
=2)
1740 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1741 def __init__(self
, record
, name
):
1742 return super().__init
__(record
=record
, name
=name
, field
="DQ", nz
=4)
1745 class DOperandDX(SignedOperand
):
1748 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1749 operands
= map(cls
, ("d0", "d1", "d2"))
1750 spans
= map(lambda operand
: operand
.span
, operands
)
1751 return sum(spans
, tuple())
1753 def disassemble(self
, insn
,
1754 style
=Style
.NORMAL
, indent
=""):
1756 value
= insn
[span
].to_signed_int()
1757 sign
= "-" if (value
< 0) else ""
1760 if style
>= Style
.VERBOSE
:
1767 for (subname
, subspan
) in mapping
.items():
1768 operand
= DynamicOperand(name
=subname
)
1770 span
= map(str, span
)
1771 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1772 yield f
"{indent}{indent}{indent}{sign}{value}"
1773 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1775 yield f
"{sign}{value}"
1778 class Instruction(_Mapping
):
1780 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1781 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1782 raise ValueError(bits
)
1784 if isinstance(value
, bytes
):
1785 if ((len(value
) * 8) != bits
):
1786 raise ValueError(f
"bit length mismatch")
1787 value
= int.from_bytes(value
, byteorder
=byteorder
)
1789 if isinstance(value
, int):
1790 value
= _SelectableInt(value
=value
, bits
=bits
)
1791 elif isinstance(value
, Instruction
):
1792 value
= value
.storage
1794 if not isinstance(value
, _SelectableInt
):
1795 raise ValueError(value
)
1798 if len(value
) != bits
:
1799 raise ValueError(value
)
1801 value
= _SelectableInt(value
=value
, bits
=bits
)
1803 return cls(storage
=value
)
1806 return hash(int(self
))
1808 def __getitem__(self
, key
):
1809 return self
.storage
.__getitem
__(key
)
1811 def __setitem__(self
, key
, value
):
1812 return self
.storage
.__setitem
__(key
, value
)
1814 def bytes(self
, byteorder
="little"):
1815 nr_bytes
= (len(self
.__class
__) // 8)
1816 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1819 def record(cls
, db
, entry
):
1822 raise KeyError(entry
)
1826 def operands(cls
, record
):
1827 yield from record
.operands
1830 def static_operands(cls
, record
):
1831 return filter(lambda operand
: isinstance(operand
, StaticOperand
),
1832 cls
.operands(record
=record
))
1835 def dynamic_operands(cls
, record
):
1836 return filter(lambda operand
: isinstance(operand
, DynamicOperand
),
1837 cls
.operands(record
=record
))
1839 def spec(self
, record
, prefix
):
1840 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1841 self
.spec_dynamic_operands(record
=record
)))
1843 static_operands
= []
1844 for (name
, value
) in self
.spec_static_operands(record
=record
):
1845 static_operands
.append(f
"{name}={value}")
1848 if dynamic_operands
:
1850 operands
+= ",".join(dynamic_operands
)
1853 operands
+= " ".join(static_operands
)
1855 return f
"{prefix}{record.name}{operands}"
1857 def spec_static_operands(self
, record
):
1858 for operand
in self
.static_operands(record
=record
):
1859 if not isinstance(operand
, (POStaticOperand
, XOStaticOperand
)):
1860 yield (operand
.name
, operand
.value
)
1862 def spec_dynamic_operands(self
, record
, style
=Style
.NORMAL
):
1866 for operand
in self
.dynamic_operands(record
=record
):
1868 value
= " ".join(operand
.disassemble(insn
=self
,
1869 style
=min(style
, Style
.NORMAL
)))
1871 name
= f
"{imm_name}({name})"
1872 value
= f
"{imm_value}({value})"
1874 if isinstance(operand
, ImmediateOperand
):
1882 def assemble(cls
, record
, arguments
=None):
1883 if arguments
is None:
1886 insn
= cls
.integer(value
=0)
1888 for operand
in cls
.static_operands(record
=record
):
1889 operand
.assemble(insn
=insn
)
1891 arguments
= Arguments(record
=record
,
1892 arguments
=arguments
, operands
=cls
.dynamic_operands(record
=record
))
1893 for (value
, operand
) in arguments
:
1894 operand
.assemble(insn
=insn
, value
=value
)
1898 def disassemble(self
, record
,
1900 style
=Style
.NORMAL
):
1901 raise NotImplementedError()
1904 class WordInstruction(Instruction
):
1905 _
: _Field
= range(0, 32)
1906 PO
: _Field
= range(0, 6)
1909 def integer(cls
, value
, byteorder
="little"):
1910 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1915 for idx
in range(32):
1916 bit
= int(self
[idx
])
1918 return "".join(map(str, bits
))
1920 def disassemble(self
, record
,
1922 style
=Style
.NORMAL
):
1923 if style
<= Style
.SHORT
:
1926 blob
= self
.bytes(byteorder
=byteorder
)
1927 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1931 yield f
"{blob}.long 0x{int(self):08x}"
1934 # awful temporary hack: workaround for ld-update
1935 # https://bugs.libre-soc.org/show_bug.cgi?id=1056#c2
1936 # XXX TODO must check that *EXTENDED* RA != extended-RT
1937 if (record
.svp64
is not None and
1938 record
.mode
== _SVMode
.LDST_IMM
and
1939 'u' in record
.name
):
1940 yield f
"{blob}.long 0x{int(self):08x}"
1944 if style
is Style
.LEGACY
:
1946 for operand
in self
.dynamic_operands(record
=record
):
1947 if isinstance(operand
, (GPRPairOperand
, FPRPairOperand
)):
1950 if style
is Style
.LEGACY
and (paired
or record
.ppc
.unofficial
):
1951 yield f
"{blob}.long 0x{int(self):08x}"
1953 operands
= tuple(map(_operator
.itemgetter(1),
1954 self
.spec_dynamic_operands(record
=record
, style
=style
)))
1956 operands
= ",".join(operands
)
1957 yield f
"{blob}{record.name} {operands}"
1959 yield f
"{blob}{record.name}"
1961 if style
>= Style
.VERBOSE
:
1963 binary
= self
.binary
1964 spec
= self
.spec(record
=record
, prefix
="")
1965 yield f
"{indent}spec"
1966 yield f
"{indent}{indent}{spec}"
1967 yield f
"{indent}pcode"
1968 for stmt
in record
.mdwn
.pcode
:
1969 yield f
"{indent}{indent}{stmt}"
1970 yield f
"{indent}binary"
1971 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1972 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1973 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1974 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1975 yield f
"{indent}opcodes"
1976 for opcode
in record
.opcodes
:
1977 yield f
"{indent}{indent}{opcode!r}"
1978 for operand
in self
.operands(record
=record
):
1979 yield from operand
.disassemble(insn
=self
,
1980 style
=style
, indent
=indent
)
1984 class PrefixedInstruction(Instruction
):
1985 class Prefix(WordInstruction
.remap(range(0, 32))):
1988 class Suffix(WordInstruction
.remap(range(32, 64))):
1991 _
: _Field
= range(64)
1997 def integer(cls
, value
, byteorder
="little"):
1998 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
2001 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
2002 def transform(value
):
2003 return WordInstruction
.integer(value
=value
,
2004 byteorder
=byteorder
)[0:32]
2006 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
2007 value
= _selectconcat(prefix
, suffix
)
2009 return super().integer(bits
=64, value
=value
)
2012 class Mode(_Mapping
):
2013 _
: _Field
= range(0, 5)
2014 sel
: _Field
= (0, 1)
2017 class ExtraRM(_Mapping
):
2018 _
: _Field
= range(0, 9)
2021 class Extra2RM(ExtraRM
):
2022 idx0
: _Field
= range(0, 2)
2023 idx1
: _Field
= range(2, 4)
2024 idx2
: _Field
= range(4, 6)
2025 idx3
: _Field
= range(6, 8)
2027 def __getitem__(self
, key
):
2033 _SVExtra
.Idx0
: self
.idx0
,
2034 _SVExtra
.Idx1
: self
.idx1
,
2035 _SVExtra
.Idx2
: self
.idx2
,
2036 _SVExtra
.Idx3
: self
.idx3
,
2039 def __setitem__(self
, key
, value
):
2040 self
[key
].assign(value
)
2043 class Extra3RM(ExtraRM
):
2044 idx0
: _Field
= range(0, 3)
2045 idx1
: _Field
= range(3, 6)
2046 idx2
: _Field
= range(6, 9)
2048 def __getitem__(self
, key
):
2053 _SVExtra
.Idx0
: self
.idx0
,
2054 _SVExtra
.Idx1
: self
.idx1
,
2055 _SVExtra
.Idx2
: self
.idx2
,
2058 def __setitem__(self
, key
, value
):
2059 self
[key
].assign(value
)
2062 class BaseRM(_Mapping
):
2063 _
: _Field
= range(24)
2064 mmode
: _Field
= (0,)
2065 mask
: _Field
= range(1, 4)
2066 elwidth
: _Field
= range(4, 6)
2067 ewsrc
: _Field
= range(6, 8)
2068 subvl
: _Field
= range(8, 10)
2069 mode
: Mode
.remap(range(19, 24))
2070 smask_extra322
: _Field
= (6,7,18,) # LDST_IDX is EXTRA332
2071 smask
: _Field
= range(16, 19) # everything else use this
2072 extra
: ExtraRM
.remap(range(10, 19))
2073 extra2
: Extra2RM
.remap(range(10, 19))
2074 extra3
: Extra3RM
.remap(range(10, 19))
2075 # XXX extra332 = (extra3[0], extra3[1], extra2[3])
2077 def specifiers(self
, record
):
2078 subvl
= int(self
.subvl
)
2086 def disassemble(self
, style
=Style
.NORMAL
):
2087 if style
>= Style
.VERBOSE
:
2089 for (name
, span
) in self
.traverse(path
="RM"):
2090 value
= self
.storage
[span
]
2092 yield f
"{indent}{int(value):0{value.bits}b}"
2093 yield f
"{indent}{', '.join(map(str, span))}"
2096 class FFRc1BaseRM(BaseRM
):
2097 def specifiers(self
, record
, mode
):
2098 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
2099 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
2100 mask
= int(_selectconcat(CR
, inv
))
2101 predicate
= PredicateBaseRM
.predicate(True, mask
)
2102 yield f
"{mode}={predicate}"
2104 yield from super().specifiers(record
=record
)
2107 class FFRc0BaseRM(BaseRM
):
2108 def specifiers(self
, record
, mode
):
2110 inv
= "~" if self
.inv
else ""
2111 yield f
"{mode}={inv}RC1"
2113 yield from super().specifiers(record
=record
)
2116 class SatBaseRM(BaseRM
):
2117 def specifiers(self
, record
):
2123 yield from super().specifiers(record
=record
)
2126 class ZZBaseRM(BaseRM
):
2127 def specifiers(self
, record
):
2131 yield from super().specifiers(record
=record
)
2134 class ZZCombinedBaseRM(BaseRM
):
2135 def specifiers(self
, record
):
2136 if self
.sz
and self
.dz
:
2143 yield from super().specifiers(record
=record
)
2146 class DZBaseRM(BaseRM
):
2147 def specifiers(self
, record
):
2151 yield from super().specifiers(record
=record
)
2154 class SZBaseRM(BaseRM
):
2155 def specifiers(self
, record
):
2159 yield from super().specifiers(record
=record
)
2162 class MRBaseRM(BaseRM
):
2163 def specifiers(self
, record
):
2169 yield from super().specifiers(record
=record
)
2172 class ElsBaseRM(BaseRM
):
2173 def specifiers(self
, record
):
2177 yield from super().specifiers(record
=record
)
2180 class WidthBaseRM(BaseRM
):
2182 def width(FP
, width
):
2191 width
= ("fp" + width
)
2194 def specifiers(self
, record
):
2195 # elwidths: use "w=" if same otherwise dw/sw
2196 # FIXME this should consider FP instructions
2198 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
2199 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2200 if record
.svp64
.mode
is _SVMode
.CROP
:
2204 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2213 yield from super().specifiers(record
=record
)
2216 class PredicateBaseRM(BaseRM
):
2218 def predicate(CR
, mask
):
2221 (False, 0b001): "1<<r3",
2222 (False, 0b010): "r3",
2223 (False, 0b011): "~r3",
2224 (False, 0b100): "r10",
2225 (False, 0b101): "~r10",
2226 (False, 0b110): "r30",
2227 (False, 0b111): "~r30",
2229 (True, 0b000): "lt",
2230 (True, 0b001): "ge",
2231 (True, 0b010): "gt",
2232 (True, 0b011): "le",
2233 (True, 0b100): "eq",
2234 (True, 0b101): "ne",
2235 (True, 0b110): "so",
2236 (True, 0b111): "ns",
2239 def specifiers(self
, record
):
2240 # predication - single and twin
2241 # use "m=" if same otherwise sm/dm
2242 CR
= (int(self
.mmode
) == 1)
2243 mask
= int(self
.mask
)
2244 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
2245 if record
.svp64
.ptype
is _SVPType
.P2
:
2246 # LDST_IDX smask moving to extra322 but not straight away (False)
2247 if False and record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2248 smask
= int(self
.smask_extra332
)
2250 smask
= int(self
.smask
)
2251 sm
= PredicateBaseRM
.predicate(CR
, smask
)
2260 yield from super().specifiers(record
=record
)
2263 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
2267 class SEABaseRM(BaseRM
):
2268 def specifiers(self
, record
):
2272 yield from super().specifiers(record
=record
)
2275 class VLiBaseRM(BaseRM
):
2276 def specifiers(self
, record
):
2280 yield from super().specifiers(record
=record
)
2283 class NormalBaseRM(PredicateWidthBaseRM
):
2286 https://libre-soc.org/openpower/sv/normal/
2291 class NormalSimpleRM(ZZCombinedBaseRM
, NormalBaseRM
):
2292 """normal: simple mode"""
2296 def specifiers(self
, record
):
2297 yield from super().specifiers(record
=record
)
2300 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
2301 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
2305 class NormalFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, NormalBaseRM
):
2306 """normal: Rc=1: ffirst CR sel"""
2309 CR
: BaseRM
.mode
[3, 4]
2311 def specifiers(self
, record
):
2312 yield from super().specifiers(record
=record
, mode
="ff")
2315 class NormalFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
2316 """normal: Rc=0: ffirst z/nonz"""
2321 def specifiers(self
, record
):
2322 yield from super().specifiers(record
=record
, mode
="ff")
2325 class NormalSatRM(SatBaseRM
, ZZCombinedBaseRM
, NormalBaseRM
):
2326 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2332 class NormalRM(NormalBaseRM
):
2333 simple
: NormalSimpleRM
2335 ffrc1
: NormalFFRc1RM
2336 ffrc0
: NormalFFRc0RM
2340 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2342 LD/ST Immediate mode
2343 https://libre-soc.org/openpower/sv/ldst/
2348 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2349 """ld/st immediate: simple mode"""
2350 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2351 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2357 def specifiers(self
, record
):
2363 yield from super().specifiers(record
=record
)
2366 class LDSTFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2367 """ld/st immediate&indexed: Rc=1: ffirst CR sel"""
2370 CR
: BaseRM
.mode
[3, 4]
2372 def specifiers(self
, record
):
2373 yield from super().specifiers(record
=record
, mode
="ff")
2376 class LDSTFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2377 """ld/st immediate&indexed: Rc=0: ffirst z/nonz"""
2382 def specifiers(self
, record
):
2383 yield from super().specifiers(record
=record
, mode
="ff")
2386 class LDSTImmRM(LDSTImmBaseRM
):
2387 simple
: LDSTImmSimpleRM
2392 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2395 https://libre-soc.org/openpower/sv/ldst/
2400 class LDSTIdxSimpleRM(SEABaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2401 """ld/st index: simple mode (includes element-strided and Signed-EA)"""
2402 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2409 def specifiers(self
, record
):
2415 yield from super().specifiers(record
=record
)
2418 class LDSTIdxRM(LDSTIdxBaseRM
):
2419 simple
: LDSTIdxSimpleRM
2425 class CROpBaseRM(BaseRM
):
2428 https://libre-soc.org/openpower/sv/cr_ops/
2433 class CROpSimpleRM(PredicateBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2434 """crop: simple mode"""
2439 def specifiers(self
, record
):
2441 yield "rg" # simple CR Mode reports /rg
2443 yield from super().specifiers(record
=record
)
2446 class CROpMRRM(MRBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2447 """crop: scalar reduce mode (mapreduce)"""
2453 class CROpFF5RM(FFRc0BaseRM
, PredicateBaseRM
, VLiBaseRM
, DZBaseRM
,
2454 SZBaseRM
, CROpBaseRM
):
2455 """crop: ffirst 5-bit mode"""
2462 def specifiers(self
, record
):
2463 yield from super().specifiers(record
=record
, mode
="ff")
2466 # FIXME: almost everything in this class contradicts the specs (it doesn't)
2467 # The modes however are swapped: 5-bit is 3-bit, 3-bit is 5-bit
2468 class CROpFF3RM(FFRc1BaseRM
, PredicateBaseRM
, VLiBaseRM
, ZZBaseRM
, CROpBaseRM
):
2469 """cr_op: ffirst 3-bit mode"""
2475 def specifiers(self
, record
):
2476 yield from super().specifiers(record
=record
, mode
="ff")
2479 class CROpRM(CROpBaseRM
):
2480 simple
: CROpSimpleRM
2486 # ********************
2488 # https://libre-soc.org/openpower/sv/branches/
2489 class BranchBaseRM(BaseRM
):
2499 def specifiers(self
, record
):
2511 raise ValueError(self
.sz
)
2523 # Branch modes lack source mask.
2524 # Therefore a custom code is needed.
2525 CR
= (int(self
.mmode
) == 1)
2526 mask
= int(self
.mask
)
2527 m
= PredicateBaseRM
.predicate(CR
, mask
)
2531 yield from super().specifiers(record
=record
)
2534 class BranchSimpleRM(BranchBaseRM
):
2535 """branch: simple mode"""
2539 class BranchVLSRM(BranchBaseRM
):
2540 """branch: VLSET mode"""
2544 def specifiers(self
, record
):
2550 }[int(self
.VSb
), int(self
.VLi
)]
2552 yield from super().specifiers(record
=record
)
2555 class BranchCTRRM(BranchBaseRM
):
2556 """branch: CTR-test mode"""
2559 def specifiers(self
, record
):
2565 yield from super().specifiers(record
=record
)
2568 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2569 """branch: CTR-test+VLSET mode"""
2573 class BranchRM(BranchBaseRM
):
2574 simple
: BranchSimpleRM
2577 ctrvls
: BranchCTRVLSRM
2588 @_dataclasses.dataclass(eq
=True, frozen
=True)
2593 def match(cls
, desc
, record
):
2594 raise NotImplementedError()
2596 def validate(self
, others
):
2599 def assemble(self
, insn
):
2600 raise NotImplementedError()
2603 @_dataclasses.dataclass(eq
=True, frozen
=True)
2604 class SpecifierWidth(Specifier
):
2608 def match(cls
, desc
, record
, etalon
):
2609 (mode
, _
, value
) = desc
.partition("=")
2611 value
= value
.strip()
2614 width
= _SVP64Width(value
)
2616 return cls(record
=record
, width
=width
)
2619 @_dataclasses.dataclass(eq
=True, frozen
=True)
2620 class SpecifierW(SpecifierWidth
):
2622 def match(cls
, desc
, record
):
2623 return super().match(desc
=desc
, record
=record
, etalon
="w")
2625 def assemble(self
, insn
):
2626 selector
= insn
.select(record
=self
.record
)
2627 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2628 selector
.ewsrc
= self
.width
.value
2629 selector
.elwidth
= self
.width
.value
2632 @_dataclasses.dataclass(eq
=True, frozen
=True)
2633 class SpecifierSW(SpecifierWidth
):
2635 def match(cls
, desc
, record
):
2636 if record
.svp64
.mode
is _SVMode
.CROP
:
2638 return super().match(desc
=desc
, record
=record
, etalon
="sw")
2640 def assemble(self
, insn
):
2641 selector
= insn
.select(record
=self
.record
)
2642 selector
.ewsrc
= self
.width
.value
2645 @_dataclasses.dataclass(eq
=True, frozen
=True)
2646 class SpecifierDW(SpecifierWidth
):
2648 def match(cls
, desc
, record
):
2649 return super().match(desc
=desc
, record
=record
, etalon
="dw")
2651 def assemble(self
, insn
):
2652 selector
= insn
.select(record
=self
.record
)
2653 selector
.elwidth
= self
.width
.value
2656 @_dataclasses.dataclass(eq
=True, frozen
=True)
2657 class SpecifierSubVL(Specifier
):
2661 def match(cls
, desc
, record
):
2663 value
= _SVP64SubVL(desc
)
2667 return cls(record
=record
, value
=value
)
2669 def assemble(self
, insn
):
2670 selector
= insn
.select(record
=self
.record
)
2671 selector
.subvl
= int(self
.value
.value
)
2674 @_dataclasses.dataclass(eq
=True, frozen
=True)
2675 class SpecifierPredicate(Specifier
):
2680 def match(cls
, desc
, record
, mode_match
, pred_match
):
2681 (mode
, _
, pred
) = desc
.partition("=")
2684 if not mode_match(mode
):
2687 pred
= _SVP64Pred(pred
.strip())
2688 if not pred_match(pred
):
2689 raise ValueError(pred
)
2691 return cls(record
=record
, mode
=mode
, pred
=pred
)
2694 @_dataclasses.dataclass(eq
=True, frozen
=True)
2695 class SpecifierFF(SpecifierPredicate
):
2697 def match(cls
, desc
, record
):
2698 return super().match(desc
=desc
, record
=record
,
2699 mode_match
=lambda mode_arg
: mode_arg
== "ff",
2700 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2705 def assemble(self
, insn
):
2706 selector
= insn
.select(record
=self
.record
)
2707 if selector
.mode
.sel
!= 0:
2708 raise ValueError("cannot override mode")
2709 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2710 selector
.mode
.sel
= 0b01
2711 # HACK: please finally provide correct logic for CRs.
2712 if self
.pred
in (_SVP64Pred
.RC1
, _SVP64Pred
.RC1_N
):
2713 selector
.mode
[2] = (self
.pred
is _SVP64Pred
.RC1_N
)
2715 selector
.mode
[2] = self
.pred
.inv
2716 selector
.mode
[3, 4] = self
.pred
.state
2718 selector
.mode
.sel
= 0b01 if self
.mode
== "ff" else 0b11
2719 selector
.inv
= self
.pred
.inv
2721 selector
.CR
= self
.pred
.state
2723 selector
.RC1
= self
.pred
.state
2726 @_dataclasses.dataclass(eq
=True, frozen
=True)
2727 class SpecifierMask(SpecifierPredicate
):
2729 def match(cls
, desc
, record
, mode
):
2730 return super().match(desc
=desc
, record
=record
,
2731 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2732 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2737 def assemble(self
, insn
):
2738 raise NotImplementedError()
2741 @_dataclasses.dataclass(eq
=True, frozen
=True)
2742 class SpecifierM(SpecifierMask
):
2744 def match(cls
, desc
, record
):
2745 return super().match(desc
=desc
, record
=record
, mode
="m")
2747 def validate(self
, others
):
2749 if isinstance(spec
, SpecifierSM
):
2750 raise ValueError("source-mask and predicate mask conflict")
2751 elif isinstance(spec
, SpecifierDM
):
2752 raise ValueError("dest-mask and predicate mask conflict")
2754 def assemble(self
, insn
):
2755 selector
= insn
.select(record
=self
.record
)
2756 selector
.mask
= int(self
.pred
)
2757 if ((self
.record
.ptype
is _SVPType
.P2
) and
2758 (self
.record
.svp64
.mode
is not _SVMode
.BRANCH
)):
2759 selector
.smask
= int(self
.pred
)
2760 # LDST_IDX smask moving to extra322 but not straight away (False)
2761 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2762 selector
.smask_extra332
= int(self
.pred
)
2764 selector
.smask
= int(self
.pred
)
2766 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2769 @_dataclasses.dataclass(eq
=True, frozen
=True)
2770 class SpecifierSM(SpecifierMask
):
2772 def match(cls
, desc
, record
):
2773 return super().match(desc
=desc
, record
=record
, mode
="sm")
2775 def validate(self
, others
):
2776 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2777 raise ValueError("source-mask on non-twin predicate")
2779 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2782 if isinstance(spec
, SpecifierDM
):
2786 raise ValueError("missing dest-mask in CR twin predication")
2787 if self
.pred
.mode
!= twin
.pred
.mode
:
2788 raise ValueError(f
"predicate masks mismatch: "
2789 f
"{self.pred!r} vs {twin.pred!r}")
2791 def assemble(self
, insn
):
2792 selector
= insn
.select(record
=self
.record
)
2793 # LDST_IDX smask moving to extra322 but not straight away (False)
2794 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2795 selector
.smask_extra332
= int(self
.pred
)
2797 selector
.smask
= int(self
.pred
)
2798 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2801 @_dataclasses.dataclass(eq
=True, frozen
=True)
2802 class SpecifierDM(SpecifierMask
):
2804 def match(cls
, desc
, record
):
2805 return super().match(desc
=desc
, record
=record
, mode
="dm")
2807 def validate(self
, others
):
2808 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2809 raise ValueError("dest-mask on non-twin predicate")
2811 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2814 if isinstance(spec
, SpecifierSM
):
2818 raise ValueError("missing source-mask in CR twin predication")
2819 if self
.pred
.mode
!= twin
.pred
.mode
:
2820 raise ValueError(f
"predicate masks mismatch: "
2821 f
"{self.pred!r} vs {twin.pred!r}")
2823 def assemble(self
, insn
):
2824 selector
= insn
.select(record
=self
.record
)
2825 selector
.mask
= int(self
.pred
)
2826 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2829 @_dataclasses.dataclass(eq
=True, frozen
=True)
2830 class SpecifierZZ(Specifier
):
2832 def match(cls
, desc
, record
):
2836 return cls(record
=record
)
2838 def validate(self
, others
):
2840 # Since zz takes precedence (overrides) sz and dz,
2841 # treat them as mutually exclusive.
2842 if isinstance(spec
, (SpecifierSZ
, SpecifierDZ
)):
2843 raise ValueError("mutually exclusive predicate masks")
2845 def assemble(self
, insn
):
2846 selector
= insn
.select(record
=self
.record
)
2847 if hasattr(selector
, "zz"): # this should be done in a different way
2854 @_dataclasses.dataclass(eq
=True, frozen
=True)
2855 class SpecifierXZ(Specifier
):
2857 hint
: str = _dataclasses
.field(repr=False)
2860 def match(cls
, desc
, record
, etalon
, hint
):
2864 return cls(desc
=desc
, record
=record
, hint
=hint
)
2866 def validate(self
, others
):
2867 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2868 raise ValueError(f
"{self.hint} on non-twin predicate")
2870 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2873 if isinstance(spec
, SpecifierXZ
):
2877 raise ValueError(f
"missing {self.hint} in CR twin predication")
2878 if self
.pred
!= twin
.pred
:
2879 raise ValueError(f
"predicate masks mismatch: "
2880 f
"{self.pred!r} vs {twin.pred!r}")
2882 def assemble(self
, insn
):
2883 selector
= insn
.select(record
=self
.record
)
2884 setattr(selector
, self
.desc
, 1)
2887 @_dataclasses.dataclass(eq
=True, frozen
=True)
2888 class SpecifierSZ(SpecifierXZ
):
2890 def match(cls
, desc
, record
):
2891 return super().match(desc
=desc
, record
=record
,
2892 etalon
="sz", hint
="source-mask")
2894 def validate(self
, others
):
2896 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2897 if isinstance(spec
, SpecifierFF
):
2898 raise ValueError("source-zero not allowed in ff mode")
2901 @_dataclasses.dataclass(eq
=True, frozen
=True)
2902 class SpecifierDZ(SpecifierXZ
):
2904 def match(cls
, desc
, record
):
2905 return super().match(desc
=desc
, record
=record
,
2906 etalon
="dz", hint
="dest-mask")
2908 def validate(self
, others
):
2910 if ((self
.record
.svp64
.mode
is not _SVMode
.CROP
) and
2911 isinstance(spec
, SpecifierFF
) and
2912 (spec
.pred
.mode
is _SVP64PredMode
.RC1
)):
2913 raise ValueError(f
"dest-zero not allowed in ff mode BO")
2916 @_dataclasses.dataclass(eq
=True, frozen
=True)
2917 class SpecifierEls(Specifier
):
2919 def match(cls
, desc
, record
):
2923 if record
.svp64
.mode
not in (_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
):
2924 raise ValueError("els is only valid in ld/st modes, not "
2925 "%s" % str(self
.record
.svp64
.mode
))
2927 return cls(record
=record
)
2929 def assemble(self
, insn
):
2930 if self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
: # stride mode
2931 insn
.prefix
.rm
.mode
[1] = 0
2933 selector
= insn
.select(record
=self
.record
)
2938 @_dataclasses.dataclass(eq
=True, frozen
=True)
2939 class SpecifierSEA(Specifier
):
2941 def match(cls
, desc
, record
):
2945 return cls(record
=record
)
2947 def validate(self
, others
):
2948 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
:
2949 raise ValueError("sea is only valid in ld/st modes, not "
2950 "%s" % str(self
.record
.svp64
.mode
))
2953 if isinstance(spec
, SpecifierFF
):
2954 raise ValueError(f
"sea cannot be used in ff mode")
2956 def assemble(self
, insn
):
2957 selector
= insn
.select(record
=self
.record
)
2958 if selector
.mode
.sel
not in (0b10, 0b00):
2959 raise ValueError("sea is only valid for normal and els modes, "
2960 "not %d" % int(selector
.mode
.sel
))
2964 @_dataclasses.dataclass(eq
=True, frozen
=True)
2965 class SpecifierSat(Specifier
):
2970 def match(cls
, desc
, record
, etalon
, sign
):
2974 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.LDST_IMM
,
2976 raise ValueError("only normal, ld/st imm and "
2977 "ld/st idx modes supported")
2979 return cls(record
=record
, desc
=desc
, sign
=sign
)
2981 def assemble(self
, insn
):
2982 selector
= insn
.select(record
=self
.record
)
2983 selector
.mode
[0] = 0b1
2984 selector
.mode
[1] = 0b0
2985 selector
.N
= int(self
.sign
)
2988 @_dataclasses.dataclass(eq
=True, frozen
=True)
2989 class SpecifierSatS(SpecifierSat
):
2991 def match(cls
, desc
, record
):
2992 return super().match(desc
=desc
, record
=record
,
2993 etalon
="sats", sign
=True)
2996 @_dataclasses.dataclass(eq
=True, frozen
=True)
2997 class SpecifierSatU(SpecifierSat
):
2999 def match(cls
, desc
, record
):
3000 return super().match(desc
=desc
, record
=record
,
3001 etalon
="satu", sign
=False)
3004 @_dataclasses.dataclass(eq
=True, frozen
=True)
3005 class SpecifierMapReduce(Specifier
):
3009 def match(cls
, record
, RG
):
3010 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
3011 raise ValueError("only normal and crop modes supported")
3013 return cls(record
=record
, RG
=RG
)
3015 def assemble(self
, insn
):
3016 selector
= insn
.select(record
=self
.record
)
3017 if self
.record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
3018 raise ValueError("only normal and crop modes supported")
3019 selector
.mode
[0] = 0
3020 selector
.mode
[1] = 0
3021 selector
.mode
[2] = 1
3022 selector
.RG
= self
.RG
3025 @_dataclasses.dataclass(eq
=True, frozen
=True)
3026 class SpecifierMR(SpecifierMapReduce
):
3028 def match(cls
, desc
, record
):
3032 return super().match(record
=record
, RG
=False)
3035 @_dataclasses.dataclass(eq
=True, frozen
=True)
3036 class SpecifierMRR(SpecifierMapReduce
):
3038 def match(cls
, desc
, record
):
3042 return super().match(record
=record
, RG
=True)
3045 @_dataclasses.dataclass(eq
=True, frozen
=True)
3046 class SpecifierBranch(Specifier
):
3048 def match(cls
, desc
, record
, etalon
):
3052 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3053 raise ValueError("only branch modes supported")
3055 return cls(record
=record
)
3058 @_dataclasses.dataclass(eq
=True, frozen
=True)
3059 class SpecifierAll(SpecifierBranch
):
3061 def match(cls
, desc
, record
):
3062 return super().match(desc
=desc
, record
=record
, etalon
="all")
3064 def assemble(self
, insn
):
3065 selector
= insn
.select(record
=self
.record
)
3069 @_dataclasses.dataclass(eq
=True, frozen
=True)
3070 class SpecifierSNZ(Specifier
):
3072 def match(cls
, desc
, record
):
3076 if record
.svp64
.mode
not in (_SVMode
.BRANCH
, _SVMode
.CROP
):
3077 raise ValueError("only branch and crop modes supported")
3079 return cls(record
=record
)
3081 def assemble(self
, insn
):
3082 selector
= insn
.select(record
=self
.record
)
3083 if self
.record
.svp64
.mode
in (_SVMode
.CROP
, _SVMode
.BRANCH
):
3085 if self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3088 raise ValueError("only branch and crop modes supported")
3091 @_dataclasses.dataclass(eq
=True, frozen
=True)
3092 class SpecifierSL(SpecifierBranch
):
3094 def match(cls
, desc
, record
):
3095 return super().match(desc
=desc
, record
=record
, etalon
="sl")
3097 def assemble(self
, insn
):
3098 selector
= insn
.select(record
=self
.record
)
3102 @_dataclasses.dataclass(eq
=True, frozen
=True)
3103 class SpecifierSLu(SpecifierBranch
):
3105 def match(cls
, desc
, record
):
3106 return super().match(desc
=desc
, record
=record
, etalon
="slu")
3108 def assemble(self
, insn
):
3109 selector
= insn
.select(record
=self
.record
)
3113 @_dataclasses.dataclass(eq
=True, frozen
=True)
3114 class SpecifierLRu(SpecifierBranch
):
3116 def match(cls
, desc
, record
):
3117 return super().match(desc
=desc
, record
=record
, etalon
="lru")
3119 def assemble(self
, insn
):
3120 selector
= insn
.select(record
=self
.record
)
3124 @_dataclasses.dataclass(eq
=True, frozen
=True)
3125 class SpecifierVSXX(SpecifierBranch
):
3130 def match(cls
, desc
, record
, etalon
, VSb
, VLi
):
3134 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3135 raise ValueError("only branch modes supported")
3137 return cls(record
=record
, VSb
=VSb
, VLi
=VLi
)
3139 def assemble(self
, insn
):
3140 selector
= insn
.select(record
=self
.record
)
3142 selector
.VSb
= int(self
.VSb
)
3143 selector
.VLi
= int(self
.VLi
)
3146 @_dataclasses.dataclass(eq
=True, frozen
=True)
3147 class SpecifierVS(SpecifierVSXX
):
3149 def match(cls
, desc
, record
):
3150 return super().match(desc
=desc
, record
=record
,
3151 etalon
="vs", VSb
=False, VLi
=False)
3154 @_dataclasses.dataclass(eq
=True, frozen
=True)
3155 class SpecifierVSi(SpecifierVSXX
):
3157 def match(cls
, desc
, record
):
3158 return super().match(desc
=desc
, record
=record
,
3159 etalon
="vsi", VSb
=False, VLi
=True)
3162 @_dataclasses.dataclass(eq
=True, frozen
=True)
3163 class SpecifierVSb(SpecifierVSXX
):
3165 def match(cls
, desc
, record
):
3166 return super().match(desc
=desc
, record
=record
,
3167 etalon
="vsb", VSb
=True, VLi
=False)
3170 @_dataclasses.dataclass(eq
=True, frozen
=True)
3171 class SpecifierVSbi(SpecifierVSXX
):
3173 def match(cls
, desc
, record
):
3174 return super().match(desc
=desc
, record
=record
,
3175 etalon
="vsbi", VSb
=True, VLi
=True)
3178 @_dataclasses.dataclass(eq
=True, frozen
=True)
3179 class SpecifierCTX(Specifier
):
3183 def match(cls
, desc
, record
, etalon
, CTi
):
3187 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3188 raise ValueError("only branch modes supported")
3190 return cls(record
=record
, CTi
=CTi
)
3192 def assemble(self
, insn
):
3193 selector
= insn
.select(record
=self
.record
)
3195 selector
.CTi
= int(self
.CTi
)
3198 @_dataclasses.dataclass(eq
=True, frozen
=True)
3199 class SpecifierCTR(SpecifierCTX
):
3201 def match(cls
, desc
, record
):
3202 return super().match(desc
=desc
, record
=record
,
3203 etalon
="ctr", CTi
=False)
3206 @_dataclasses.dataclass(eq
=True, frozen
=True)
3207 class SpecifierCTi(SpecifierCTX
):
3209 def match(cls
, desc
, record
):
3210 return super().match(desc
=desc
, record
=record
,
3211 etalon
="cti", CTi
=True)
3214 @_dataclasses.dataclass(eq
=True, frozen
=True)
3215 class SpecifierPI(Specifier
):
3217 def match(cls
, desc
, record
):
3221 if record
.svp64
.mode
not in [_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
]:
3222 raise ValueError("only ld/st imm/idx mode supported")
3224 return cls(record
=record
)
3226 def assemble(self
, insn
):
3227 selector
= insn
.select(record
=self
.record
)
3228 selector
.mode
[2] = 0b1
3232 @_dataclasses.dataclass(eq
=True, frozen
=True)
3233 class SpecifierLF(Specifier
):
3235 def match(cls
, desc
, record
):
3239 if record
.svp64
.mode
is not _SVMode
.LDST_IMM
:
3240 raise ValueError("only ld/st imm mode supported")
3242 return cls(record
=record
)
3244 def assemble(self
, insn
):
3245 selector
= insn
.select(record
=self
.record
)
3246 selector
.mode
[1] = 0
3250 @_dataclasses.dataclass(eq
=True, frozen
=True)
3251 class SpecifierVLi(Specifier
):
3253 def match(cls
, desc
, record
):
3257 return cls(record
=record
)
3259 def validate(self
, others
):
3261 if isinstance(spec
, SpecifierFF
):
3264 raise ValueError("VLi only allowed in failfirst")
3266 def assemble(self
, insn
):
3267 selector
= insn
.select(record
=self
.record
)
3268 selector
.mode
[1] = 1
3272 class Specifiers(tuple):
3307 def __new__(cls
, items
, record
):
3308 def transform(item
):
3309 for spec_cls
in cls
.SPECS
:
3310 spec
= spec_cls
.match(item
, record
=record
)
3311 if spec
is not None:
3313 raise ValueError(item
)
3315 # TODO: remove this hack
3316 items
= dict.fromkeys(items
)
3320 items
= tuple(items
)
3322 specs
= tuple(map(transform
, items
))
3323 for (index
, spec
) in enumerate(specs
):
3324 head
= specs
[:index
]
3325 tail
= specs
[index
+ 1:]
3326 spec
.validate(others
=(head
+ tail
))
3328 return super().__new
__(cls
, specs
)
3331 class SVP64OperandMeta(type):
3332 class SVP64NonZeroOperand(NonZeroOperand
):
3333 def assemble(self
, insn
, value
):
3334 if isinstance(value
, str):
3335 value
= int(value
, 0)
3336 if not isinstance(value
, int):
3337 raise ValueError("non-integer operand")
3339 # FIXME: this is really weird
3340 if self
.record
.name
in ("svstep", "svstep."):
3341 value
+= 1 # compensation
3343 return super().assemble(value
=value
, insn
=insn
)
3345 class SVP64XOStaticOperand(SpanStaticOperand
):
3346 def __init__(self
, record
, value
, span
):
3347 return super().__init
__(record
=record
, name
="XO",
3348 value
=value
, span
=span
)
3351 NonZeroOperand
: SVP64NonZeroOperand
,
3352 XOStaticOperand
: SVP64XOStaticOperand
,
3355 def __new__(metacls
, name
, bases
, ns
):
3357 for (index
, base_cls
) in enumerate(bases
):
3358 bases
[index
] = metacls
.__TRANSFORM
.get(base_cls
, base_cls
)
3360 bases
= tuple(bases
)
3362 return super().__new
__(metacls
, name
, bases
, ns
)
3365 class SVP64Operand(Operand
, metaclass
=SVP64OperandMeta
):
3368 return tuple(map(lambda bit
: (bit
+ 32), super().span
))
3372 def __init__(self
, insn
, record
):
3374 self
.__record
= record
3375 return super().__init
__()
3378 return self
.rm
.__doc
__
3381 return repr(self
.rm
)
3389 return self
.__record
3393 rm
= getattr(self
.insn
.prefix
.rm
, self
.record
.svp64
.mode
.name
.lower())
3395 # The idea behind these tables is that they are now literally
3396 # in identical format to insndb.csv and minor_xx.csv and can
3397 # be done precisely as that. The only thing to watch out for
3398 # is the insertion of Rc=1 as a "mask/value" bit and likewise
3399 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
3402 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
3403 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3404 # mode Rc mask Rc member
3406 (0b000000, 0b111000, "simple"), # simple (no Rc)
3407 (0b001000, 0b111100, "mr"), # mapreduce (no Rc)
3408 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3409 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3410 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3411 (0b001100, 0b111100, "rsvd"), # reserved
3413 mode
= int(self
.insn
.prefix
.rm
.normal
.mode
)
3414 search
= ((mode
<< 1) | self
.record
.Rc
)
3416 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
3417 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3418 # mode Rc mask Rc member
3419 # ironically/coincidentally this table is identical to NORMAL
3420 # mode except reserved in place of mr
3422 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3423 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3424 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3426 search
= ((int(self
.insn
.prefix
.rm
.ldst_imm
.mode
) << 1) |
3429 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
3430 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3431 # mode Rc mask Rc member
3433 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3434 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3435 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3437 search
= ((int(self
.insn
.prefix
.rm
.ldst_idx
.mode
) << 1) |
3440 elif self
.record
.svp64
.mode
is _SVMode
.CROP
:
3441 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
3442 # mode 3b mask 3b member
3444 (0b000000, 0b111000, "simple"), # simple
3445 (0b001000, 0b111000, "mr"), # mapreduce
3446 (0b010001, 0b010001, "ff3"), # ffirst, 3-bit CR
3447 (0b010000, 0b010000, "ff5"), # ffirst, 5-bit CR
3449 search
= ((int(self
.insn
.prefix
.rm
.crop
.mode
) << 1) |
3450 int(self
.record
.svp64
.extra_CR_3bit
))
3452 elif self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3456 (0b00, 0b11, "simple"), # simple
3457 (0b01, 0b11, "vls"), # VLset
3458 (0b10, 0b11, "ctr"), # CTR mode
3459 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
3461 # slightly weird: doesn't have a 5-bit "mode" field like others
3462 search
= int(self
.insn
.prefix
.rm
.branch
.mode
.sel
)
3465 if table
is not None:
3466 for (value
, mask
, field
) in table
:
3467 if field
.startswith("rsvd"):
3469 if ((value
& mask
) == (search
& mask
)):
3470 return getattr(rm
, field
)
3474 def __getattr__(self
, key
):
3475 if key
.startswith(f
"_{self.__class__.__name__}__"):
3476 return super().__getattribute
__(key
)
3478 return getattr(self
.rm
, key
)
3480 def __setattr__(self
, key
, value
):
3481 if key
.startswith(f
"_{self.__class__.__name__}__"):
3482 return super().__setattr
__(key
, value
)
3485 if not hasattr(rm
, key
):
3486 raise AttributeError(key
)
3488 return setattr(rm
, key
, value
)
3491 class SVP64Instruction(PrefixedInstruction
):
3492 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
3493 class Prefix(PrefixedInstruction
.Prefix
):
3495 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
3499 def select(self
, record
):
3500 return RMSelector(insn
=self
, record
=record
)
3505 for idx
in range(64):
3506 bit
= int(self
[idx
])
3508 return "".join(map(str, bits
))
3511 def assemble(cls
, record
, arguments
=None, specifiers
=None):
3512 insn
= super().assemble(record
=record
, arguments
=arguments
)
3514 specifiers
= Specifiers(items
=specifiers
, record
=record
)
3515 for specifier
in specifiers
:
3516 specifier
.assemble(insn
=insn
)
3518 insn
.prefix
.PO
= 0x1
3519 insn
.prefix
.id = 0x3
3523 def disassemble(self
, record
,
3525 style
=Style
.NORMAL
):
3527 if style
<= Style
.SHORT
:
3530 blob
= insn
.bytes(byteorder
=byteorder
)
3531 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
3534 blob_prefix
= blob(self
.prefix
)
3535 blob_suffix
= blob(self
.suffix
)
3537 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3538 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
3541 assert record
.svp64
is not None
3543 name
= f
"sv.{record.name}"
3545 rm
= self
.select(record
=record
)
3547 # convert specifiers to /x/y/z (sorted lexicographically)
3548 specifiers
= sorted(rm
.specifiers(record
=record
))
3549 if specifiers
: # if any add one extra to get the extra "/"
3550 specifiers
= ([""] + specifiers
)
3551 specifiers
= "/".join(specifiers
)
3553 # convert operands to " ,x,y,z"
3554 operands
= tuple(map(_operator
.itemgetter(1),
3555 self
.spec_dynamic_operands(record
=record
, style
=style
)))
3556 operands
= ",".join(operands
)
3557 if len(operands
) > 0: # if any separate with a space
3558 operands
= (" " + operands
)
3560 if style
<= Style
.LEGACY
:
3561 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3562 suffix
= WordInstruction
.integer(value
=int(self
.suffix
))
3563 yield from suffix
.disassemble(record
=record
,
3564 byteorder
=byteorder
, style
=style
)
3566 yield f
"{blob_prefix}{name}{specifiers}{operands}"
3568 yield f
"{blob_suffix}"
3570 if style
>= Style
.VERBOSE
:
3572 binary
= self
.binary
3573 spec
= self
.spec(record
=record
, prefix
="sv.")
3575 yield f
"{indent}spec"
3576 yield f
"{indent}{indent}{spec}"
3577 yield f
"{indent}pcode"
3578 for stmt
in record
.mdwn
.pcode
:
3579 yield f
"{indent}{indent}{stmt}"
3580 yield f
"{indent}binary"
3581 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
3582 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
3583 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
3584 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
3585 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
3586 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
3587 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
3588 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
3589 yield f
"{indent}opcodes"
3590 for opcode
in record
.opcodes
:
3591 yield f
"{indent}{indent}{opcode!r}"
3592 for operand
in self
.operands(record
=record
):
3593 yield from operand
.disassemble(insn
=self
,
3594 style
=style
, indent
=indent
)
3596 yield f
"{indent}{indent}{str(rm)}"
3597 for line
in rm
.disassemble(style
=style
):
3598 yield f
"{indent}{indent}{line}"
3602 def operands(cls
, record
):
3603 for operand
in super().operands(record
=record
):
3604 parent
= operand
.__class
__
3605 name
= f
"SVP64{parent.__name__}"
3606 bases
= (SVP64Operand
, parent
)
3607 child
= type(name
, bases
, {})
3608 yield child(**dict(operand
))
3611 def parse(stream
, factory
):
3613 return ("TODO" not in frozenset(entry
.values()))
3615 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
3616 entries
= _csv
.DictReader(lines
)
3617 entries
= filter(match
, entries
)
3618 return tuple(map(factory
, entries
))
3621 class MarkdownDatabase
:
3624 for (name
, desc
) in _ISA():
3627 (dynamic
, *static
) = desc
.regs
3628 operands
.extend(dynamic
)
3629 operands
.extend(static
)
3630 pcode
= PCode(iterable
=filter(str.strip
, desc
.pcode
))
3631 operands
= Operands(insn
=name
, operands
=operands
)
3632 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
3634 self
.__db
= dict(sorted(db
.items()))
3636 return super().__init
__()
3639 yield from self
.__db
.items()
3641 def __contains__(self
, key
):
3642 return self
.__db
.__contains
__(key
)
3644 def __getitem__(self
, key
):
3645 return self
.__db
.__getitem
__(key
)
3648 class FieldsDatabase
:
3651 df
= _DecodeFields()
3653 for (form
, fields
) in df
.instrs
.items():
3654 if form
in {"DQE", "TX"}:
3658 db
[_Form
[form
]] = Fields(fields
)
3662 return super().__init
__()
3664 def __getitem__(self
, key
):
3665 return self
.__db
.__getitem
__(key
)
3669 def __init__(self
, root
, mdwndb
):
3670 # The code below groups the instructions by name:section.
3671 # There can be multiple names for the same instruction.
3672 # The point is to capture different opcodes for the same instruction.
3674 records
= _collections
.defaultdict(set)
3675 path
= (root
/ "insndb.csv")
3676 with
open(path
, "r", encoding
="UTF-8") as stream
:
3677 for section
in sorted(parse(stream
, Section
.CSV
)):
3678 path
= (root
/ section
.csv
)
3680 section
.Mode
.INTEGER
: IntegerOpcode
,
3681 section
.Mode
.PATTERN
: PatternOpcode
,
3683 factory
= _functools
.partial(
3684 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
3685 with
open(path
, "r", encoding
="UTF-8") as stream
:
3686 for insn
in parse(stream
, factory
):
3687 for name
in insn
.names
:
3688 records
[name
].add(insn
)
3689 sections
[name
] = section
3691 items
= sorted(records
.items())
3693 for (name
, multirecord
) in items
:
3694 records
[name
] = PPCMultiRecord(sorted(multirecord
))
3696 def exact_match(name
):
3697 record
= records
.get(name
)
3703 if not name
.endswith("l"):
3705 alias
= exact_match(name
[:-1])
3708 record
= records
[alias
]
3709 if "lk" not in record
.flags
:
3710 raise ValueError(record
)
3714 if not name
.endswith("a"):
3716 alias
= LK_match(name
[:-1])
3719 record
= records
[alias
]
3720 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
3721 raise ValueError(record
)
3722 if "AA" not in mdwndb
[name
].operands
:
3723 raise ValueError(record
)
3727 if not name
.endswith("."):
3729 alias
= exact_match(name
[:-1])
3732 record
= records
[alias
]
3733 if record
.Rc
is _RCOE
.NONE
:
3734 raise ValueError(record
)
3738 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
3739 for (name
, _
) in mdwndb
:
3740 if name
.startswith("sv."):
3743 for match
in matches
:
3745 if alias
is not None:
3749 section
= sections
[alias
]
3750 record
= records
[alias
]
3751 db
[name
] = (section
, record
)
3753 self
.__db
= dict(sorted(db
.items()))
3755 return super().__init
__()
3757 @_functools.lru_cache(maxsize
=512, typed
=False)
3758 def __getitem__(self
, key
):
3759 return self
.__db
.get(key
, (None, None))
3762 class SVP64Database
:
3763 def __init__(self
, root
, ppcdb
):
3765 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
3766 for (prefix
, _
, names
) in _os
.walk(root
):
3767 prefix
= _pathlib
.Path(prefix
)
3768 for name
in filter(lambda name
: pattern
.match(name
), names
):
3769 path
= (prefix
/ _pathlib
.Path(name
))
3770 with
open(path
, "r", encoding
="UTF-8") as stream
:
3771 db
.update(parse(stream
, SVP64Record
.CSV
))
3772 db
= {record
.name
:record
for record
in db
}
3774 self
.__db
= dict(sorted(db
.items()))
3775 self
.__ppcdb
= ppcdb
3777 return super().__init
__()
3779 def __getitem__(self
, key
):
3780 (_
, record
) = self
.__ppcdb
[key
]
3784 for name
in record
.names
:
3785 record
= self
.__db
.get(name
, None)
3786 if record
is not None:
3792 class Records(Tuple
, datatype
=Record
):
3793 def __new__(cls
, records
):
3794 return super().__new
__(cls
, sorted(records
))
3797 class Database(Node
):
3798 def __init__(self
, root
):
3799 root
= _pathlib
.Path(root
)
3800 mdwndb
= MarkdownDatabase()
3801 fieldsdb
= FieldsDatabase()
3802 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
3803 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
3807 opcodes
= _collections
.defaultdict(
3808 lambda: _collections
.defaultdict(set))
3810 for (name
, mdwn
) in mdwndb
:
3811 if name
.startswith("sv."):
3813 (section
, ppc
) = ppcdb
[name
]
3816 svp64
= svp64db
[name
]
3817 fields
= fieldsdb
[ppc
.form
]
3818 record
= Record(name
=name
,
3819 section
=section
, ppc
=ppc
, svp64
=svp64
,
3820 mdwn
=mdwn
, fields
=fields
)
3822 names
[record
.name
] = record
3823 opcodes
[section
][record
.PO
].add(record
)
3825 self
.__db
= Records(db
)
3826 self
.__names
= dict(sorted(names
.items()))
3827 self
.__opcodes
= dict(sorted(opcodes
.items()))
3829 return super().__init
__()
3832 def walk(clsself
, match
=None):
3834 match
= lambda subnode
: True
3836 if isinstance(clsself
, type):
3839 if match(clsself
.__db
):
3843 return repr(self
.__db
)
3846 yield from self
.__db
3848 @_functools.lru_cache(maxsize
=None)
3849 def __contains__(self
, key
):
3850 return self
.__getitem
__(key
) is not None
3852 @_functools.lru_cache(maxsize
=None)
3853 def __getitem__(self
, key
):
3854 if isinstance(key
, SVP64Instruction
):
3857 if isinstance(key
, Instruction
):
3860 sections
= sorted(self
.__opcodes
)
3861 for section
in sections
:
3862 group
= self
.__opcodes
[section
]
3863 for record
in group
[PO
]:
3864 if record
.match(key
=key
):
3869 elif isinstance(key
, str):
3870 return self
.__names
.get(key
)
3872 raise ValueError("instruction or name expected")