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
):
66 entity
= owner
if instance
is None else instance
67 return _functools
.partial(self
.__walk
, entity
)
72 def walk(clsself
, match
=lambda _
: True):
76 class DataclassMeta(type):
77 def __new__(metacls
, name
, bases
, ns
):
78 cls
= super().__new
__(metacls
, name
, bases
, ns
)
79 return _dataclasses
.dataclass(cls
, eq
=True, frozen
=True)
82 class Dataclass(Node
, metaclass
=DataclassMeta
):
84 def walk(clsself
, match
=lambda _
: True):
85 def field_type(field
):
88 def field_value(field
):
89 return getattr(clsself
, field
.name
)
91 field_node
= (field_type
if isinstance(clsself
, type) else field_value
)
93 for field
in _dataclasses
.fields(clsself
):
95 node
= field_node(field
)
99 class Tuple(Node
, tuple):
100 def __init_subclass__(cls
, datatype
):
101 cls
.__datatype
= datatype
102 return super().__init
_subclass
__()
105 def walk(clsself
, match
=lambda _
: True):
106 if isinstance(clsself
, type):
107 yield ("[]", clsself
.__datatype
)
109 for (index
, item
) in enumerate(filter(match
, clsself
)):
110 yield (str(index
), item
)
113 class Dict(Node
, dict):
114 def __init_subclass__(cls
, datatype
):
115 cls
.__datatype
= datatype
116 return super().__init
_subclass
__()
119 return hash(tuple(sorted(self
.items())))
122 raise NotImplementedError()
124 def __delitem__(self
, key
):
125 raise NotImplementedError()
127 def __setitem__(self
, key
, value
):
128 raise NotImplementedError()
130 def popitem(self
) -> tuple:
131 raise NotImplementedError()
133 def pop(self
, key
, default
=None):
134 raise NotImplementedError()
136 def update(self
, entry
, **kwargs
):
137 raise NotImplementedError()
140 def walk(clsself
, match
=lambda _
: True):
141 if isinstance(clsself
, type):
142 yield ("{}", clsself
.__datatype
)
144 yield from filter(lambda kv
: match(kv
[0]), clsself
.items())
148 def __init__(self
, nodecls
, method
):
149 self
.__nodecls
= nodecls
150 self
.__method
= method
151 return super().__init
__()
155 return self
.__nodecls
157 @_contextlib.contextmanager
158 def __call__(self
, path
, node
):
159 return self
.__method
(self
=self
, path
=path
, node
=node
)
162 class VisitorMeta(type):
163 def __init__(cls
, name
, bases
, ns
):
165 for (key
, value
) in ns
.items():
166 if isinstance(value
, VisitorMethod
):
167 if value
.type in cls
.__registry
:
168 raise AttributeError(f
"overriding visitor method: {key!r}")
169 cls
.__registry
[value
.type] = value
170 return super().__init
__(name
, bases
, ns
)
172 def __contains__(self
, nodecls
):
173 return self
.__registry
.__contains
__(nodecls
)
175 def __getitem__(self
, nodecls
):
176 return self
.__registry
.__getitem
__(nodecls
)
178 def __setitem__(self
, nodecls
, call
):
179 return self
.__registry
.__setitem
__(nodecls
, call
)
182 yield from self
.__registry
.items()
185 class Visitor(metaclass
=VisitorMeta
):
186 @_contextlib.contextmanager
187 def __call__(self
, path
, node
):
188 (visitorcls
, nodecls
) = map(type, (self
, node
))
189 if nodecls
in visitorcls
:
190 handler
= visitorcls
[nodecls
]
191 with
handler(path
=path
, node
=node
) as ctx
:
198 def __init__(self
, nodecls
):
199 if not isinstance(nodecls
, type):
200 raise ValueError(nodecls
)
201 self
.__nodecls
= nodecls
202 return super().__init
__()
204 def __call__(self
, method
):
205 if not callable(method
):
206 raise ValueError(method
)
207 return VisitorMethod(nodecls
=self
.__nodecls
, method
=method
)
210 def walk(root
, match
=lambda _
: True):
211 pairs
= _collections
.deque([root
])
213 (path
, node
) = pairs
.popleft()
214 pairs
.extend(node
.walk(match
=match
))
218 def visit(visitor
, node
, path
="/", match
=lambda _
: True):
219 with
visitor(path
=path
, node
=node
):
220 if isinstance(node
, Node
):
221 for (subpath
, subnode
) in node
.walk(match
=match
):
222 visit(visitor
=visitor
, path
=subpath
, node
=subnode
)
225 @_functools.total_ordering
226 class Style(_enum
.Enum
):
227 LEGACY
= _enum
.auto()
229 NORMAL
= _enum
.auto()
230 VERBOSE
= _enum
.auto()
232 def __lt__(self
, other
):
233 if not isinstance(other
, self
.__class
__):
234 return NotImplemented
235 return (self
.value
< other
.value
)
238 @_functools.total_ordering
239 class Priority(_enum
.Enum
):
245 def _missing_(cls
, value
):
246 if isinstance(value
, str):
247 value
= value
.upper()
251 return super()._missing
_(value
)
253 def __lt__(self
, other
):
254 if not isinstance(other
, self
.__class
__):
255 return NotImplemented
257 # NOTE: the order is inversed, LOW < NORMAL < HIGH
258 return (self
.value
> other
.value
)
261 def dataclass(cls
, record
, keymap
=None, typemap
=None):
265 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
267 def transform(key_value
):
268 (key
, value
) = key_value
269 key
= keymap
.get(key
, key
)
270 hook
= typemap
.get(key
, lambda value
: value
)
271 if hook
is bool and value
in ("", "0"):
277 record
= dict(map(transform
, record
.items()))
278 for key
in frozenset(record
.keys()):
279 if record
[key
] == "":
285 @_functools.total_ordering
286 class Opcode(Dataclass
):
288 def __new__(cls
, value
):
289 if isinstance(value
, str):
290 value
= int(value
, 0)
291 if not isinstance(value
, int):
292 raise ValueError(value
)
294 if value
.bit_length() > 64:
295 raise ValueError(value
)
297 return super().__new
__(cls
, value
)
300 return self
.__repr
__()
303 return f
"{self:0{self.bit_length()}b}"
305 def bit_length(self
):
306 if super().bit_length() > 32:
310 class Value(Integer
):
319 def __lt__(self
, other
):
320 if not isinstance(other
, Opcode
):
321 return NotImplemented
322 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
325 return (self
.value
& self
.mask
)
328 return int(self
).__index
__()
331 def pattern(value
, mask
, bit_length
):
332 for bit
in range(bit_length
):
333 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
335 elif (value
& (1 << (bit_length
- bit
- 1))):
340 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
342 def match(self
, key
):
343 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
346 @_functools.total_ordering
347 class IntegerOpcode(Opcode
):
348 def __init__(self
, value
):
349 if value
.startswith("0b"):
350 mask
= int(("1" * len(value
[2:])), 2)
354 value
= Opcode
.Value(value
)
355 mask
= Opcode
.Mask(mask
)
357 return super().__init
__(value
=value
, mask
=mask
)
360 @_functools.total_ordering
361 class PatternOpcode(Opcode
):
362 def __init__(self
, pattern
):
363 if not isinstance(pattern
, str):
364 raise ValueError(pattern
)
366 (value
, mask
) = (0, 0)
367 for symbol
in pattern
:
368 if symbol
not in {"0", "1", "-"}:
369 raise ValueError(pattern
)
370 value |
= (symbol
== "1")
371 mask |
= (symbol
!= "-")
377 value
= Opcode
.Value(value
)
378 mask
= Opcode
.Mask(mask
)
380 return super().__init
__(value
=value
, mask
=mask
)
383 class PPCRecord(Dataclass
):
384 class FlagsMeta(type):
399 class Flags(Tuple
, datatype
=str, metaclass
=FlagsMeta
):
400 def __new__(cls
, flags
=frozenset()):
401 flags
= frozenset(flags
)
402 diff
= (flags
- frozenset(cls
))
404 raise ValueError(flags
)
405 return super().__new
__(cls
, sorted(flags
))
409 flags
: Flags
= Flags()
411 function
: _Function
= _Function
.NONE
412 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
413 in1
: _In1Sel
= _In1Sel
.NONE
414 in2
: _In2Sel
= _In2Sel
.NONE
415 in3
: _In3Sel
= _In3Sel
.NONE
416 out
: _OutSel
= _OutSel
.NONE
417 cr_in
: _CRInSel
= _CRInSel
.NONE
418 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
419 cr_out
: _CROutSel
= _CROutSel
.NONE
420 cry_in
: _CryIn
= _CryIn
.ZERO
421 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
422 upd
: _LDSTMode
= _LDSTMode
.NONE
423 Rc
: _RCOE
= _RCOE
.NONE
424 form
: _Form
= _Form
.NONE
426 unofficial
: bool = False
430 "internal op": "intop",
434 "ldst len": "ldst_len",
436 "CONDITIONS": "conditions",
439 def __lt__(self
, other
):
440 if not isinstance(other
, self
.__class
__):
441 return NotImplemented
442 lhs
= (self
.opcode
, self
.comment
)
443 rhs
= (other
.opcode
, other
.comment
)
447 def CSV(cls
, record
, opcode_cls
):
448 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
449 typemap
["opcode"] = opcode_cls
451 if record
["CR in"] == "BA_BB":
452 record
["cr_in"] = "BA"
453 record
["cr_in2"] = "BB"
457 for flag
in frozenset(PPCRecord
.Flags
):
458 if bool(record
.pop(flag
, "")):
460 record
["flags"] = PPCRecord
.Flags(flags
)
462 return dataclass(cls
, record
,
463 keymap
=PPCRecord
.__KEYMAP
,
468 return frozenset(self
.comment
.split("=")[-1].split("/"))
471 class PPCMultiRecord(Tuple
, datatype
=PPCRecord
):
472 def __getattr__(self
, attr
):
475 raise AttributeError(attr
)
476 return getattr(self
[0], attr
)
479 class SVP64Record(Dataclass
):
480 class ExtraMap(tuple):
482 @_dataclasses.dataclass(eq
=True, frozen
=True)
484 seltype
: _SelType
= _SelType
.NONE
485 reg
: _Reg
= _Reg
.NONE
488 return f
"{self.seltype.value}:{self.reg.name}"
490 def __new__(cls
, value
="0"):
491 if isinstance(value
, str):
492 def transform(value
):
493 (seltype
, reg
) = value
.split(":")
494 seltype
= _SelType(seltype
)
496 return cls
.Entry(seltype
=seltype
, reg
=reg
)
501 value
= map(transform
, value
.split(";"))
503 return super().__new
__(cls
, value
)
506 return repr(list(self
))
508 def __new__(cls
, value
=tuple()):
512 return super().__new
__(cls
, map(cls
.Extra
, value
))
515 return repr({index
:self
[index
] for index
in range(0, 4)})
518 ptype
: _SVPType
= _SVPType
.NONE
519 etype
: _SVEType
= _SVEType
.NONE
520 msrc
: _SVMaskSrc
= _SVMaskSrc
.NO
# MASK_SRC is active
521 in1
: _In1Sel
= _In1Sel
.NONE
522 in2
: _In2Sel
= _In2Sel
.NONE
523 in3
: _In3Sel
= _In3Sel
.NONE
524 out
: _OutSel
= _OutSel
.NONE
525 out2
: _OutSel
= _OutSel
.NONE
526 cr_in
: _CRInSel
= _CRInSel
.NONE
527 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
528 cr_out
: _CROutSel
= _CROutSel
.NONE
529 extra
: ExtraMap
= ExtraMap()
531 mode
: _SVMode
= _SVMode
.NORMAL
535 "CONDITIONS": "conditions",
544 def CSV(cls
, record
):
545 record
["insn"] = record
["insn"].split("=")[-1]
547 for key
in frozenset({
548 "in1", "in2", "in3", "CR in",
549 "out", "out2", "CR out",
555 if record
["CR in"] == "BA_BB":
556 record
["cr_in"] = "BA"
557 record
["cr_in2"] = "BB"
561 for idx
in range(0, 4):
562 extra
.append(record
.pop(f
"{idx}"))
564 record
["extra"] = cls
.ExtraMap(extra
)
566 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
571 "in1", "in2", "in3", "cr_in", "cr_in2",
572 "out", "out2", "cr_out",
587 for index
in range(0, 4):
588 for entry
in self
.extra
[index
]:
589 extras
[entry
.seltype
][entry
.reg
] = idxmap
[index
]
591 for (seltype
, regs
) in extras
.items():
592 idx
= regs
.get(reg
, _SVExtra
.NONE
)
593 if idx
is not _SVExtra
.NONE
:
594 yield (reg
, seltype
, idx
)
601 # has the word "in", it is a SelType.SRC "out" -> DST
602 # in1/2/3 and CR in are SRC, and must match only against "s:NN"
603 # out/out1 and CR out are DST, and must match only against "d:NN"
604 keytype
= _SelType
.SRC
if ("in" in key
) else _SelType
.DST
605 sel
= sels
[key
] = getattr(self
, key
)
606 reg
= regs
[key
] = _Reg(sel
)
607 seltypes
[key
] = _SelType
.NONE
608 idxs
[key
] = _SVExtra
.NONE
609 for (reg
, seltype
, idx
) in extra(reg
.alias
):
610 if keytype
!= seltype
: # only check SRC-to-SRC and DST-to-DST
612 if idx
!= idxs
[key
] and idxs
[key
] is not _SVExtra
.NONE
:
613 raise ValueError(idx
)
616 seltypes
[key
] = seltype
618 if sels
["cr_in"] is _CRInSel
.BA_BB
:
619 sels
["cr_in"] = _CRIn2Sel
.BA
620 sels
["cr_in2"] = _CRIn2Sel
.BB
621 idxs
["cr_in2"] = idxs
["cr_in"]
622 for key
in ("cr_in", "cr_in2"):
623 regs
[key
] = _Reg(sels
[key
])
624 seltype
[key
] = _SelType
.SRC
631 "seltype": seltypes
[key
],
635 return _types
.MappingProxyType(records
)
637 extra_idx_in1
= property(lambda self
: self
.extras
["in1"]["idx"])
638 extra_idx_in2
= property(lambda self
: self
.extras
["in2"]["idx"])
639 extra_idx_in3
= property(lambda self
: self
.extras
["in3"]["idx"])
640 extra_idx_out
= property(lambda self
: self
.extras
["out"]["idx"])
641 extra_idx_out2
= property(lambda self
: self
.extras
["out2"]["idx"])
642 extra_idx_cr_in
= property(lambda self
: self
.extras
["cr_in"]["idx"])
643 extra_idx_cr_in2
= property(lambda self
: self
.extras
["cr_in2"]["idx"])
644 extra_idx_cr_out
= property(lambda self
: self
.extras
["cr_out"]["idx"])
649 for idx
in range(0, 4):
650 for entry
in self
.extra
[idx
]:
651 if entry
.seltype
is _SelType
.DST
:
652 if extra
is not None:
653 raise ValueError(self
.svp64
)
657 if _RegType(extra
.reg
) not in (_RegType
.CR_3BIT
, _RegType
.CR_5BIT
):
658 raise ValueError(self
.svp64
)
663 def extra_CR_3bit(self
):
664 return (_RegType(self
.extra_CR
.reg
) is _RegType
.CR_3BIT
)
668 def __init__(self
, value
=(0, 32)):
669 if isinstance(value
, str):
670 (start
, end
) = map(int, value
.split(":"))
673 if start
< 0 or end
< 0 or start
>= end
:
674 raise ValueError(value
)
679 return super().__init
__()
682 return (self
.__end
- self
.__start
+ 1)
685 return f
"[{self.__start}:{self.__end}]"
688 yield from range(self
.start
, (self
.end
+ 1))
690 def __reversed__(self
):
691 return tuple(reversed(tuple(self
)))
702 class Section(Dataclass
):
703 class Mode(_enum
.Enum
):
704 INTEGER
= _enum
.auto()
705 PATTERN
= _enum
.auto()
708 def _missing_(cls
, value
):
709 if isinstance(value
, str):
710 return cls
[value
.upper()]
711 return super()._missing
_(value
)
714 def __new__(cls
, value
=None):
715 if isinstance(value
, str):
716 if value
.upper() == "NONE":
719 value
= int(value
, 0)
723 return super().__new
__(cls
, value
)
729 return (bin(self
) if self
else "None")
735 opcode
: IntegerOpcode
= None
736 priority
: Priority
= Priority
.NORMAL
738 def __lt__(self
, other
):
739 if not isinstance(other
, self
.__class
__):
740 return NotImplemented
741 return (self
.priority
< other
.priority
)
744 def CSV(cls
, record
):
745 keymap
= {"path": "csv"}
746 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
747 if record
["opcode"] == "NONE":
748 typemap
["opcode"] = lambda _
: None
750 return dataclass(cls
, record
, typemap
=typemap
, keymap
=keymap
)
753 class Fields(Dict
, datatype
=type("Bits", (Tuple
,), {}, datatype
=int)):
754 def __init__(self
, items
):
755 if isinstance(items
, dict):
756 items
= items
.items()
759 (name
, bitrange
) = item
760 return (name
, tuple(bitrange
.values()))
762 mapping
= dict(map(transform
, items
))
764 return super().__init
__(mapping
)
767 yield from self
.__mapping
.items()
770 class Operands(Dict
, datatype
=object):
782 def __init__(self
, insn
, operands
):
784 "b": {"target_addr": TargetAddrOperandLI
},
785 "ba": {"target_addr": TargetAddrOperandLI
},
786 "bl": {"target_addr": TargetAddrOperandLI
},
787 "bla": {"target_addr": TargetAddrOperandLI
},
788 "bc": {"target_addr": TargetAddrOperandBD
},
789 "bca": {"target_addr": TargetAddrOperandBD
},
790 "bcl": {"target_addr": TargetAddrOperandBD
},
791 "bcla": {"target_addr": TargetAddrOperandBD
},
792 "addpcis": {"D": DOperandDX
},
793 "fishmv": {"D": DOperandDX
},
794 "fmvis": {"D": DOperandDX
},
797 "SVi": NonZeroOperand
,
798 "SVd": NonZeroOperand
,
799 "SVxd": NonZeroOperand
,
800 "SVyd": NonZeroOperand
,
801 "SVzd": NonZeroOperand
,
803 "D": SignedImmediateOperand
,
807 "SIM": SignedOperand
,
808 "SVD": SignedOperand
,
809 "SVDS": SignedOperand
,
810 "RSp": GPRPairOperand
,
811 "RTp": GPRPairOperand
,
812 "FRAp": FPRPairOperand
,
813 "FRBp": FPRPairOperand
,
814 "FRSp": FPRPairOperand
,
815 "FRTp": FPRPairOperand
,
817 custom_immediates
= {
823 for operand
in operands
:
827 (name
, value
) = operand
.split("=")
828 mapping
[name
] = (StaticOperand
, (
830 ("value", int(value
)),
834 if name
.endswith(")"):
835 name
= name
.replace("(", " ").replace(")", "")
836 (imm_name
, _
, name
) = name
.partition(" ")
840 if imm_name
is not None:
841 imm_cls
= custom_immediates
.get(imm_name
, ImmediateOperand
)
843 if insn
in custom_insns
and name
in custom_insns
[insn
]:
844 cls
= custom_insns
[insn
][name
]
845 elif name
in custom_fields
:
846 cls
= custom_fields
[name
]
847 elif name
in _Reg
.__members
__:
849 if reg
in self
.__class
__.__GPR
_PAIRS
:
851 elif reg
in self
.__class
__.__FPR
_PAIRS
:
854 regtype
= _RegType
[name
]
855 if regtype
is _RegType
.GPR
:
857 elif regtype
is _RegType
.FPR
:
859 elif regtype
is _RegType
.CR_3BIT
:
861 elif regtype
is _RegType
.CR_5BIT
:
864 if imm_name
is not None:
865 mapping
[imm_name
] = (imm_cls
, (("name", imm_name
),))
866 mapping
[name
] = (cls
, (("name", name
),))
868 return super().__init
__(mapping
)
871 def walk(clsself
, match
=lambda _
: True):
872 for (key
, (cls
, pairs
)) in clsself
.items():
873 yield ("/".join((key
, "class")), cls
.__name
__)
874 for (subkey
, value
) in pairs
:
877 path
= "/".join((key
, subkey
))
881 for (key
, items
) in self
.items():
882 (cls
, kwargs
) = items
883 yield (cls
, dict(kwargs
))
887 return lambda pair
: isinstance(pair
[0], cls
)
891 return filter(self
.__class
__.filter(StaticOperand
), self
)
895 return filter(self
.__class
__.filter(DynamicOperand
), self
)
898 class Arguments(tuple):
899 def __new__(cls
, record
, arguments
, operands
):
900 operands
= iter(tuple(operands
))
901 arguments
= iter(tuple(arguments
))
906 operand
= next(operands
)
907 except StopIteration:
911 argument
= next(arguments
)
912 except StopIteration:
913 raise ValueError("operands count mismatch")
915 if isinstance(operand
, ImmediateOperand
):
916 argument
= argument
.replace("(", " ").replace(")", "")
917 (imm_argument
, _
, argument
) = argument
.partition(" ")
919 (imm_operand
, operand
) = (operand
, next(operands
))
920 except StopIteration:
921 raise ValueError("operands count mismatch")
922 items
.append((imm_argument
, imm_operand
))
923 items
.append((argument
, operand
))
927 except StopIteration:
930 raise ValueError("operands count mismatch")
932 return super().__new
__(cls
, items
)
935 class PCode(Tuple
, datatype
=str):
939 class MarkdownRecord(Dataclass
):
944 @_functools.total_ordering
945 class Record(Dataclass
):
951 svp64
: SVP64Record
= None
955 if self
.svp64
is not None:
956 return self
.svp64
.extras
958 return _types
.MappingProxyType({})
962 return self
.mdwn
.pcode
964 def __lt__(self
, other
):
965 if not isinstance(other
, Record
):
966 return NotImplemented
967 lhs
= (min(self
.opcodes
), self
.name
)
968 rhs
= (min(other
.opcodes
), other
.name
)
973 return (self
.static_operands
+ self
.dynamic_operands
)
976 def static_operands(self
):
978 operands
.append(POStaticOperand(record
=self
, value
=self
.PO
))
980 operands
.append(XOStaticOperand(
982 value
=ppc
.opcode
.value
,
983 span
=self
.section
.bitsel
,
985 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
986 operands
.append(cls(record
=self
, **kwargs
))
987 return tuple(operands
)
990 def dynamic_operands(self
):
992 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
993 operands
.append(cls(record
=self
, **kwargs
))
994 return tuple(operands
)
999 return int("".join(str(int(mapping
[bit
])) \
1000 for bit
in sorted(mapping
)), 2)
1002 def PO_XO(value
, mask
, opcode
, bits
):
1005 for (src
, dst
) in enumerate(reversed(bits
)):
1006 value
[dst
] = ((opcode
.value
& (1 << src
)) != 0)
1007 mask
[dst
] = ((opcode
.mask
& (1 << src
)) != 0)
1008 return (value
, mask
)
1010 def PO(value
, mask
, opcode
, bits
):
1011 return PO_XO(value
=value
, mask
=mask
, opcode
=opcode
, bits
=bits
)
1013 def XO(value
, mask
, opcode
, bits
):
1014 (value
, mask
) = PO_XO(value
=value
, mask
=mask
,
1015 opcode
=opcode
, bits
=bits
)
1016 for (op_cls
, op_kwargs
) in self
.mdwn
.operands
.static
:
1017 operand
= op_cls(record
=self
, **op_kwargs
)
1018 for (src
, dst
) in enumerate(reversed(operand
.span
)):
1019 value
[dst
] = ((operand
.value
& (1 << src
)) != 0)
1021 return (value
, mask
)
1024 value
= {bit
:False for bit
in range(32)}
1025 mask
= {bit
:False for bit
in range(32)}
1026 if self
.section
.opcode
is not None:
1027 (value
, mask
) = PO(value
=value
, mask
=mask
,
1028 opcode
=self
.section
.opcode
, bits
=range(0, 6))
1029 for ppc
in self
.ppc
:
1030 pairs
.append(XO(value
=value
, mask
=mask
,
1031 opcode
=ppc
.opcode
, bits
=self
.section
.bitsel
))
1034 for (value
, mask
) in pairs
:
1035 value
= Opcode
.Value(binary(value
))
1036 mask
= Opcode
.Mask(binary(mask
))
1037 result
.append(Opcode(value
=value
, mask
=mask
))
1039 return tuple(result
)
1043 opcode
= self
.section
.opcode
1045 opcode
= self
.ppc
[0].opcode
1046 if isinstance(opcode
, PatternOpcode
):
1047 value
= int(opcode
.value
)
1048 bits
= opcode
.value
.bit_length()
1049 return int(_SelectableInt(value
=value
, bits
=bits
)[0:6])
1051 return int(opcode
.value
)
1055 return tuple(ppc
.opcode
for ppc
in self
.ppc
)
1057 def match(self
, key
):
1058 for opcode
in self
.opcodes
:
1059 if opcode
.match(key
):
1066 return self
.svp64
.mode
1086 if self
.svp64
is None:
1092 return self
.ppc
.cr_in
1096 return self
.ppc
.cr_in2
1100 return self
.ppc
.cr_out
1102 ptype
= property(lambda self
: self
.svp64
.ptype
)
1103 etype
= property(lambda self
: self
.svp64
.etype
)
1105 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
1106 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
1107 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
1108 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
1109 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
1110 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
1111 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
1112 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
1114 def __contains__(self
, key
):
1115 return self
.mdwn
.operands
.__contains
__(key
)
1117 def __getitem__(self
, key
):
1118 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
1119 return cls(record
=self
, **kwargs
)
1123 if "Rc" not in self
:
1125 return self
["Rc"].value
1129 def __init__(self
, record
, name
):
1130 self
.__record
= record
1134 yield ("record", self
.record
)
1135 yield ("name", self
.__name
)
1138 return f
"{self.__class__.__name__}({self.name})"
1146 return self
.__record
1150 return self
.record
.fields
[self
.name
]
1152 def assemble(self
, insn
):
1153 raise NotImplementedError()
1155 def disassemble(self
, insn
,
1156 style
=Style
.NORMAL
, indent
=""):
1157 raise NotImplementedError()
1160 class DynamicOperand(Operand
):
1161 def assemble(self
, insn
, value
):
1163 if isinstance(value
, str):
1164 value
= int(value
, 0)
1166 raise ValueError("signed operands not allowed")
1169 def disassemble(self
, insn
,
1170 style
=Style
.NORMAL
, indent
=""):
1174 if style
>= Style
.VERBOSE
:
1175 span
= map(str, span
)
1176 yield f
"{indent}{self.name}"
1177 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1178 yield f
"{indent}{indent}{', '.join(span)}"
1180 yield str(int(value
))
1183 class SignedOperand(DynamicOperand
):
1184 def assemble(self
, insn
, value
):
1185 if isinstance(value
, str):
1186 value
= int(value
, 0)
1187 return super().assemble(value
=value
, insn
=insn
)
1189 def assemble(self
, insn
, value
):
1191 if isinstance(value
, str):
1192 value
= int(value
, 0)
1195 def disassemble(self
, insn
,
1196 style
=Style
.NORMAL
, indent
=""):
1198 value
= insn
[span
].to_signed_int()
1199 sign
= "-" if (value
< 0) else ""
1202 if style
>= Style
.VERBOSE
:
1203 span
= map(str, span
)
1204 yield f
"{indent}{self.name}"
1205 yield f
"{indent}{indent}{sign}{value}"
1206 yield f
"{indent}{indent}{', '.join(span)}"
1208 yield f
"{sign}{value}"
1211 class StaticOperand(Operand
):
1212 def __init__(self
, record
, name
, value
):
1213 self
.__value
= value
1214 return super().__init
__(record
=record
, name
=name
)
1217 yield ("value", self
.__value
)
1218 yield from super().__iter
__()
1221 return f
"{self.__class__.__name__}({self.name}, value={self.value})"
1227 def assemble(self
, insn
):
1228 insn
[self
.span
] = self
.value
1230 def disassemble(self
, insn
,
1231 style
=Style
.NORMAL
, indent
=""):
1235 if style
>= Style
.VERBOSE
:
1236 span
= map(str, span
)
1237 yield f
"{indent}{self.name}"
1238 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1239 yield f
"{indent}{indent}{', '.join(span)}"
1241 yield str(int(value
))
1244 class SpanStaticOperand(StaticOperand
):
1245 def __init__(self
, record
, name
, value
, span
):
1246 self
.__span
= tuple(span
)
1247 return super().__init
__(record
=record
, name
=name
, value
=value
)
1250 yield ("span", self
.__span
)
1251 yield from super().__iter
__()
1258 class POStaticOperand(SpanStaticOperand
):
1259 def __init__(self
, record
, value
):
1260 return super().__init
__(record
=record
, name
="PO",
1261 value
=value
, span
=range(0, 6))
1264 for (key
, value
) in super().__iter
__():
1265 if key
not in {"name", "span"}:
1269 class XOStaticOperand(SpanStaticOperand
):
1270 def __init__(self
, record
, value
, span
):
1271 bits
= record
.section
.bitsel
1272 value
= _SelectableInt(value
=value
, bits
=len(bits
))
1273 span
= dict(zip(bits
, range(len(bits
))))
1274 span_rev
= {value
:key
for (key
, value
) in span
.items()}
1276 # This part is tricky: we cannot use record.operands,
1277 # as this code is called by record.static_operands method.
1278 for (cls
, kwargs
) in record
.mdwn
.operands
:
1279 operand
= cls(record
=record
, **kwargs
)
1280 for idx
in operand
.span
:
1281 rev
= span
.pop(idx
, None)
1283 span_rev
.pop(rev
, None)
1285 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1286 span
= tuple(span
.keys())
1288 return super().__init
__(record
=record
, name
="XO",
1289 value
=value
, span
=span
)
1292 for (key
, value
) in super().__iter
__():
1293 if key
not in {"name"}:
1297 class ImmediateOperand(DynamicOperand
):
1301 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1305 class NonZeroOperand(DynamicOperand
):
1306 def assemble(self
, insn
, value
):
1307 if isinstance(value
, str):
1308 value
= int(value
, 0)
1309 if not isinstance(value
, int):
1310 raise ValueError("non-integer operand")
1312 raise ValueError("non-zero operand")
1314 return super().assemble(value
=value
, insn
=insn
)
1316 def disassemble(self
, insn
,
1317 style
=Style
.NORMAL
, indent
=""):
1321 if style
>= Style
.VERBOSE
:
1322 span
= map(str, span
)
1323 yield f
"{indent}{self.name}"
1324 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1325 yield f
"{indent}{indent}{', '.join(span)}"
1327 yield str(int(value
) + 1)
1330 class ExtendableOperand(DynamicOperand
):
1331 def sv_spec_enter(self
, value
, span
):
1332 return (value
, span
)
1334 def sv_spec(self
, insn
):
1338 span
= tuple(map(str, span
))
1340 if isinstance(insn
, SVP64Instruction
):
1341 (origin_value
, origin_span
) = (value
, span
)
1342 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1344 for extra_idx
in self
.extra_idx
:
1345 if self
.record
.etype
is _SVEType
.EXTRA3
:
1346 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1347 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1348 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1350 raise ValueError(self
.record
.etype
)
1353 vector
= bool(spec
[0])
1354 spec_span
= spec
.__class
__
1355 if self
.record
.etype
is _SVEType
.EXTRA3
:
1356 spec_span
= tuple(map(str, spec_span
[1, 2]))
1358 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1359 spec_span
= tuple(map(str, spec_span
[1,]))
1360 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1363 spec_span
= (spec_span
+ ("{0}",))
1365 spec_span
= (("{0}",) + spec_span
)
1367 raise ValueError(self
.record
.etype
)
1369 vector_shift
= (2 + (5 - value
.bits
))
1370 scalar_shift
= value
.bits
1371 spec_shift
= (5 - value
.bits
)
1373 bits
= (len(span
) + len(spec_span
))
1374 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1375 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1377 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1378 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1380 value
= ((spec
<< scalar_shift
) | value
)
1381 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1383 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1384 origin_value
=origin_value
, origin_span
=origin_span
)
1386 return (vector
, value
, span
)
1388 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1389 return (value
, span
)
1392 def extra_idx(self
):
1393 for (key
, record
) in self
.record
.svp64
.extras
.items():
1394 if record
["reg"].alias
is self
.extra_reg
.alias
:
1398 def extra_reg(self
):
1399 return _Reg(self
.name
)
1401 def remap(self
, value
, vector
):
1402 raise NotImplementedError()
1404 def assemble(self
, value
, insn
, prefix
):
1407 if isinstance(value
, str):
1408 value
= value
.lower()
1409 if value
.startswith("%"):
1411 if value
.startswith("*"):
1412 if not isinstance(insn
, SVP64Instruction
):
1413 raise ValueError(value
)
1416 if value
.startswith(prefix
):
1417 if (self
.extra_reg
.or_zero
and (value
== f
"{prefix}0")):
1418 raise ValueError(value
)
1419 value
= value
[len(prefix
):]
1420 value
= int(value
, 0)
1422 if isinstance(insn
, SVP64Instruction
):
1423 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1425 for extra_idx
in self
.extra_idx
:
1426 if self
.record
.etype
is _SVEType
.EXTRA3
:
1427 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1428 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1429 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1431 raise ValueError(self
.record
.etype
)
1433 return super().assemble(value
=value
, insn
=insn
)
1435 def disassemble(self
, insn
,
1436 style
=Style
.NORMAL
, prefix
="", indent
=""):
1437 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1439 if (self
.extra_reg
.or_zero
and (value
== 0)):
1442 if style
>= Style
.VERBOSE
:
1443 mode
= "vector" if vector
else "scalar"
1444 yield f
"{indent}{self.name} ({mode})"
1445 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1446 yield f
"{indent}{indent}{', '.join(span)}"
1447 if isinstance(insn
, SVP64Instruction
):
1448 for extra_idx
in frozenset(self
.extra_idx
):
1449 if self
.record
.etype
is _SVEType
.NONE
:
1450 yield f
"{indent}{indent}extra[none]"
1452 etype
= repr(self
.record
.etype
).lower()
1453 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1455 vector
= "*" if vector
else ""
1456 yield f
"{vector}{prefix}{int(value)}"
1459 class SimpleRegisterOperand(ExtendableOperand
):
1460 def remap(self
, value
, vector
):
1462 extra
= (value
& 0b11)
1463 value
= (value
>> 2)
1465 extra
= (value
>> 5)
1466 value
= (value
& 0b11111)
1468 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1469 # (and shrink to a single bit if ok)
1470 if self
.record
.etype
is _SVEType
.EXTRA2
:
1472 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1473 assert (extra
& 0b01) == 0, \
1474 ("vector field %s cannot fit into EXTRA2" % value
)
1475 extra
= (0b10 |
(extra
>> 1))
1477 # range is r0-r63 in increments of 1
1478 assert (extra
>> 1) == 0, \
1479 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1481 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1483 # EXTRA3 vector bit needs marking
1486 raise ValueError(self
.record
.etype
)
1488 return (value
, extra
)
1491 class GPROperand(SimpleRegisterOperand
):
1492 def assemble(self
, insn
, value
):
1493 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1495 def disassemble(self
, insn
,
1496 style
=Style
.NORMAL
, indent
=""):
1497 prefix
= "" if (style
<= Style
.SHORT
) else "r"
1498 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1499 style
=style
, indent
=indent
)
1502 class GPRPairOperand(GPROperand
):
1506 class FPROperand(SimpleRegisterOperand
):
1507 def assemble(self
, insn
, value
):
1508 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1510 def disassemble(self
, insn
,
1511 style
=Style
.NORMAL
, indent
=""):
1512 prefix
= "" if (style
<= Style
.SHORT
) else "f"
1513 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1514 style
=style
, indent
=indent
)
1517 class FPRPairOperand(FPROperand
):
1521 class ConditionRegisterFieldOperand(ExtendableOperand
):
1522 def pattern(name_pattern
):
1523 (name
, pattern
) = name_pattern
1524 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1533 CR
= r
"(?:CR|cr)([0-9]+)"
1535 BIT
= rf
"({'|'.join(CONDS.keys())})"
1536 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1537 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1538 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1539 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1540 XCR
= fr
"{CR}\.{BIT}"
1541 PATTERNS
= tuple(map(pattern
, (
1546 ("BIT+CR", (LBIT
+ CR
)),
1547 ("CR+BIT", (CR
+ RBIT
)),
1548 ("BIT+CR*N", (LBIT
+ CRN
)),
1549 ("CR*N+BIT", (CRN
+ RBIT
)),
1550 ("BIT+N*CR", (LBIT
+ NCR
)),
1551 ("N*CR+BIT", (NCR
+ RBIT
)),
1554 def remap(self
, value
, vector
, regtype
):
1555 if regtype
is _RegType
.CR_5BIT
:
1556 subvalue
= (value
& 0b11)
1560 extra
= (value
& 0b1111)
1563 extra
= (value
>> 3)
1566 if self
.record
.etype
is _SVEType
.EXTRA2
:
1568 assert (extra
& 0b111) == 0, \
1569 "vector CR cannot fit into EXTRA2"
1570 extra
= (0b10 |
(extra
>> 3))
1572 assert (extra
>> 1) == 0, \
1573 "scalar CR cannot fit into EXTRA2"
1575 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1577 assert (extra
& 0b11) == 0, \
1578 "vector CR cannot fit into EXTRA3"
1579 extra
= (0b100 |
(extra
>> 2))
1581 assert (extra
>> 2) == 0, \
1582 "scalar CR cannot fit into EXTRA3"
1585 if regtype
is _RegType
.CR_5BIT
:
1586 value
= ((value
<< 2) | subvalue
)
1588 return (value
, extra
)
1590 def assemble(self
, insn
, value
):
1591 if isinstance(value
, str):
1594 if value
.startswith("*"):
1595 if not isinstance(insn
, SVP64Instruction
):
1596 raise ValueError(value
)
1600 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1601 match
= pattern
.match(value
)
1602 if match
is not None:
1603 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1604 values
= match
.groups()
1605 match
= dict(zip(keys
, values
))
1606 CR
= int(match
["CR"])
1610 N
= int(match
.get("N", "1"))
1611 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1612 value
= ((CR
* N
) + BIT
)
1619 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1621 def disassemble(self
, insn
,
1622 style
=Style
.NORMAL
, prefix
="", indent
=""):
1623 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1625 if style
>= Style
.VERBOSE
:
1626 mode
= "vector" if vector
else "scalar"
1627 yield f
"{indent}{self.name} ({mode})"
1628 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1629 yield f
"{indent}{indent}{', '.join(span)}"
1630 if isinstance(insn
, SVP64Instruction
):
1631 for extra_idx
in frozenset(self
.extra_idx
):
1632 if self
.record
.etype
is _SVEType
.NONE
:
1633 yield f
"{indent}{indent}extra[none]"
1635 etype
= repr(self
.record
.etype
).lower()
1636 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1638 vector
= "*" if vector
else ""
1639 CR
= int(value
>> 2)
1641 cond
= ("lt", "gt", "eq", "so")[CC
]
1642 if style
>= Style
.NORMAL
:
1644 if isinstance(insn
, SVP64Instruction
):
1645 yield f
"{vector}cr{CR}.{cond}"
1647 yield f
"4*cr{CR}+{cond}"
1651 yield f
"{vector}{prefix}{int(value)}"
1654 class CR3Operand(ConditionRegisterFieldOperand
):
1655 def remap(self
, value
, vector
):
1656 return super().remap(value
=value
, vector
=vector
,
1657 regtype
=_RegType
.CR_3BIT
)
1660 class CR5Operand(ConditionRegisterFieldOperand
):
1661 def remap(self
, value
, vector
):
1662 return super().remap(value
=value
, vector
=vector
,
1663 regtype
=_RegType
.CR_5BIT
)
1665 def sv_spec_enter(self
, value
, span
):
1666 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1667 return (value
, span
)
1669 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1670 value
= _selectconcat(value
, origin_value
[3:5])
1672 return (value
, span
)
1675 class EXTSOperand(SignedOperand
):
1676 field
: str # real name to report
1677 nz
: int = 0 # number of zeros
1678 fmt
: str = "d" # integer formatter
1680 def __init__(self
, record
, name
, field
, nz
=0, fmt
="d"):
1681 self
.__field
= field
1684 return super().__init
__(record
=record
, name
=name
)
1700 return self
.record
.fields
[self
.field
]
1702 def assemble(self
, insn
, value
):
1704 if isinstance(value
, str):
1705 value
= int(value
, 0)
1706 insn
[span
] = (value
>> self
.nz
)
1708 def disassemble(self
, insn
,
1709 style
=Style
.NORMAL
, indent
=""):
1711 value
= insn
[span
].to_signed_int()
1712 sign
= "-" if (value
< 0) else ""
1713 value
= (abs(value
) << self
.nz
)
1715 if style
>= Style
.VERBOSE
:
1716 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1717 zeros
= ("0" * self
.nz
)
1718 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1719 yield f
"{indent * 1}{hint}"
1720 yield f
"{indent * 2}{self.field}"
1721 yield f
"{indent * 3}{sign}{value:{self.fmt}}"
1722 yield f
"{indent * 3}{', '.join(span)}"
1724 yield f
"{sign}{value:{self.fmt}}"
1727 class TargetAddrOperand(EXTSOperand
):
1728 def __init__(self
, record
, name
, field
):
1729 return super().__init
__(record
=record
, name
=name
, field
=field
,
1733 class TargetAddrOperandLI(TargetAddrOperand
):
1734 def __init__(self
, record
, name
):
1735 return super().__init
__(record
=record
, name
=name
, field
="LI")
1738 class TargetAddrOperandBD(TargetAddrOperand
):
1739 def __init__(self
, record
, name
):
1740 return super().__init
__(record
=record
, name
=name
, field
="BD")
1743 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1744 def __init__(self
, record
, name
):
1745 return super().__init
__(record
=record
, name
=name
, field
="DS", nz
=2)
1748 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1749 def __init__(self
, record
, name
):
1750 return super().__init
__(record
=record
, name
=name
, field
="DQ", nz
=4)
1753 class DOperandDX(SignedOperand
):
1756 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1757 operands
= map(cls
, ("d0", "d1", "d2"))
1758 spans
= map(lambda operand
: operand
.span
, operands
)
1759 return sum(spans
, tuple())
1761 def disassemble(self
, insn
,
1762 style
=Style
.NORMAL
, indent
=""):
1764 value
= insn
[span
].to_signed_int()
1765 sign
= "-" if (value
< 0) else ""
1768 if style
>= Style
.VERBOSE
:
1775 for (subname
, subspan
) in mapping
.items():
1776 operand
= DynamicOperand(name
=subname
)
1778 span
= map(str, span
)
1779 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1780 yield f
"{indent}{indent}{indent}{sign}{value}"
1781 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1783 yield f
"{sign}{value}"
1786 class Instruction(_Mapping
):
1788 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1789 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1790 raise ValueError(bits
)
1792 if isinstance(value
, bytes
):
1793 if ((len(value
) * 8) != bits
):
1794 raise ValueError(f
"bit length mismatch")
1795 value
= int.from_bytes(value
, byteorder
=byteorder
)
1797 if isinstance(value
, int):
1798 value
= _SelectableInt(value
=value
, bits
=bits
)
1799 elif isinstance(value
, Instruction
):
1800 value
= value
.storage
1802 if not isinstance(value
, _SelectableInt
):
1803 raise ValueError(value
)
1806 if len(value
) != bits
:
1807 raise ValueError(value
)
1809 value
= _SelectableInt(value
=value
, bits
=bits
)
1811 return cls(storage
=value
)
1814 return hash(int(self
))
1816 def __getitem__(self
, key
):
1817 return self
.storage
.__getitem
__(key
)
1819 def __setitem__(self
, key
, value
):
1820 return self
.storage
.__setitem
__(key
, value
)
1822 def bytes(self
, byteorder
="little"):
1823 nr_bytes
= (len(self
.__class
__) // 8)
1824 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1827 def record(cls
, db
, entry
):
1830 raise KeyError(entry
)
1834 def operands(cls
, record
):
1835 yield from record
.operands
1838 def static_operands(cls
, record
):
1839 return filter(lambda operand
: isinstance(operand
, StaticOperand
),
1840 cls
.operands(record
=record
))
1843 def dynamic_operands(cls
, record
):
1844 return filter(lambda operand
: isinstance(operand
, DynamicOperand
),
1845 cls
.operands(record
=record
))
1847 def spec(self
, record
, prefix
):
1848 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1849 self
.spec_dynamic_operands(record
=record
)))
1851 static_operands
= []
1852 for (name
, value
) in self
.spec_static_operands(record
=record
):
1853 static_operands
.append(f
"{name}={value}")
1856 if dynamic_operands
:
1858 operands
+= ",".join(dynamic_operands
)
1861 operands
+= " ".join(static_operands
)
1863 return f
"{prefix}{record.name}{operands}"
1865 def spec_static_operands(self
, record
):
1866 for operand
in self
.static_operands(record
=record
):
1867 if not isinstance(operand
, (POStaticOperand
, XOStaticOperand
)):
1868 yield (operand
.name
, operand
.value
)
1870 def spec_dynamic_operands(self
, record
, style
=Style
.NORMAL
):
1874 for operand
in self
.dynamic_operands(record
=record
):
1876 value
= " ".join(operand
.disassemble(insn
=self
,
1877 style
=min(style
, Style
.NORMAL
)))
1879 name
= f
"{imm_name}({name})"
1880 value
= f
"{imm_value}({value})"
1882 if isinstance(operand
, ImmediateOperand
):
1890 def assemble(cls
, record
, arguments
=None):
1891 if arguments
is None:
1894 insn
= cls
.integer(value
=0)
1896 for operand
in cls
.static_operands(record
=record
):
1897 operand
.assemble(insn
=insn
)
1899 arguments
= Arguments(record
=record
,
1900 arguments
=arguments
, operands
=cls
.dynamic_operands(record
=record
))
1901 for (value
, operand
) in arguments
:
1902 operand
.assemble(insn
=insn
, value
=value
)
1906 def disassemble(self
, record
,
1908 style
=Style
.NORMAL
):
1909 raise NotImplementedError()
1912 class WordInstruction(Instruction
):
1913 _
: _Field
= range(0, 32)
1914 PO
: _Field
= range(0, 6)
1917 def integer(cls
, value
, byteorder
="little"):
1918 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1923 for idx
in range(32):
1924 bit
= int(self
[idx
])
1926 return "".join(map(str, bits
))
1928 def disassemble(self
, record
,
1930 style
=Style
.NORMAL
):
1931 if style
<= Style
.SHORT
:
1934 blob
= self
.bytes(byteorder
=byteorder
)
1935 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1939 yield f
"{blob}.long 0x{int(self):08x}"
1942 # awful temporary hack: workaround for ld-update
1943 # https://bugs.libre-soc.org/show_bug.cgi?id=1056#c2
1944 # XXX TODO must check that *EXTENDED* RA != extended-RT
1945 if (record
.svp64
is not None and
1946 record
.mode
== _SVMode
.LDST_IMM
and
1947 'u' in record
.name
):
1948 yield f
"{blob}.long 0x{int(self):08x}"
1952 if style
is Style
.LEGACY
:
1954 for operand
in self
.dynamic_operands(record
=record
):
1955 if isinstance(operand
, (GPRPairOperand
, FPRPairOperand
)):
1958 if style
is Style
.LEGACY
and (paired
or record
.ppc
.unofficial
):
1959 yield f
"{blob}.long 0x{int(self):08x}"
1961 operands
= tuple(map(_operator
.itemgetter(1),
1962 self
.spec_dynamic_operands(record
=record
, style
=style
)))
1964 operands
= ",".join(operands
)
1965 yield f
"{blob}{record.name} {operands}"
1967 yield f
"{blob}{record.name}"
1969 if style
>= Style
.VERBOSE
:
1971 binary
= self
.binary
1972 spec
= self
.spec(record
=record
, prefix
="")
1973 yield f
"{indent}spec"
1974 yield f
"{indent}{indent}{spec}"
1975 yield f
"{indent}pcode"
1976 for stmt
in record
.mdwn
.pcode
:
1977 yield f
"{indent}{indent}{stmt}"
1978 yield f
"{indent}binary"
1979 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1980 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1981 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1982 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1983 yield f
"{indent}opcodes"
1984 for opcode
in record
.opcodes
:
1985 yield f
"{indent}{indent}{opcode!r}"
1986 for operand
in self
.operands(record
=record
):
1987 yield from operand
.disassemble(insn
=self
,
1988 style
=style
, indent
=indent
)
1992 class PrefixedInstruction(Instruction
):
1993 class Prefix(WordInstruction
.remap(range(0, 32))):
1996 class Suffix(WordInstruction
.remap(range(32, 64))):
1999 _
: _Field
= range(64)
2005 def integer(cls
, value
, byteorder
="little"):
2006 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
2009 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
2010 def transform(value
):
2011 return WordInstruction
.integer(value
=value
,
2012 byteorder
=byteorder
)[0:32]
2014 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
2015 value
= _selectconcat(prefix
, suffix
)
2017 return super().integer(bits
=64, value
=value
)
2020 class Mode(_Mapping
):
2021 _
: _Field
= range(0, 5)
2022 sel
: _Field
= (0, 1)
2025 class ExtraRM(_Mapping
):
2026 _
: _Field
= range(0, 9)
2029 class Extra2RM(ExtraRM
):
2030 idx0
: _Field
= range(0, 2)
2031 idx1
: _Field
= range(2, 4)
2032 idx2
: _Field
= range(4, 6)
2033 idx3
: _Field
= range(6, 8)
2035 def __getitem__(self
, key
):
2041 _SVExtra
.Idx0
: self
.idx0
,
2042 _SVExtra
.Idx1
: self
.idx1
,
2043 _SVExtra
.Idx2
: self
.idx2
,
2044 _SVExtra
.Idx3
: self
.idx3
,
2047 def __setitem__(self
, key
, value
):
2048 self
[key
].assign(value
)
2051 class Extra3RM(ExtraRM
):
2052 idx0
: _Field
= range(0, 3)
2053 idx1
: _Field
= range(3, 6)
2054 idx2
: _Field
= range(6, 9)
2056 def __getitem__(self
, key
):
2061 _SVExtra
.Idx0
: self
.idx0
,
2062 _SVExtra
.Idx1
: self
.idx1
,
2063 _SVExtra
.Idx2
: self
.idx2
,
2066 def __setitem__(self
, key
, value
):
2067 self
[key
].assign(value
)
2070 class BaseRM(_Mapping
):
2071 _
: _Field
= range(24)
2072 mmode
: _Field
= (0,)
2073 mask
: _Field
= range(1, 4)
2074 elwidth
: _Field
= range(4, 6)
2075 ewsrc
: _Field
= range(6, 8)
2076 subvl
: _Field
= range(8, 10)
2077 mode
: Mode
.remap(range(19, 24))
2078 smask_extra322
: _Field
= (6,7,18,) # LDST_IDX is EXTRA332
2079 smask
: _Field
= range(16, 19) # everything else use this
2080 extra
: ExtraRM
.remap(range(10, 19))
2081 extra2
: Extra2RM
.remap(range(10, 19))
2082 extra3
: Extra3RM
.remap(range(10, 19))
2083 # XXX extra332 = (extra3[0], extra3[1], extra2[3])
2085 def specifiers(self
, record
):
2086 subvl
= int(self
.subvl
)
2094 def disassemble(self
, style
=Style
.NORMAL
):
2095 if style
>= Style
.VERBOSE
:
2097 for (name
, span
) in self
.traverse(path
="RM"):
2098 value
= self
.storage
[span
]
2100 yield f
"{indent}{int(value):0{value.bits}b}"
2101 yield f
"{indent}{', '.join(map(str, span))}"
2104 class FFRc1BaseRM(BaseRM
):
2105 def specifiers(self
, record
, mode
):
2106 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
2107 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
2108 mask
= int(_selectconcat(CR
, inv
))
2109 predicate
= PredicateBaseRM
.predicate(True, mask
)
2110 yield f
"{mode}={predicate}"
2112 yield from super().specifiers(record
=record
)
2115 class FFRc0BaseRM(BaseRM
):
2116 def specifiers(self
, record
, mode
):
2118 inv
= "~" if self
.inv
else ""
2119 yield f
"{mode}={inv}RC1"
2121 yield from super().specifiers(record
=record
)
2124 class SatBaseRM(BaseRM
):
2125 def specifiers(self
, record
):
2131 yield from super().specifiers(record
=record
)
2134 class ZZBaseRM(BaseRM
):
2135 def specifiers(self
, record
):
2139 yield from super().specifiers(record
=record
)
2142 class ZZCombinedBaseRM(BaseRM
):
2143 def specifiers(self
, record
):
2144 if self
.sz
and self
.dz
:
2151 yield from super().specifiers(record
=record
)
2154 class DZBaseRM(BaseRM
):
2155 def specifiers(self
, record
):
2159 yield from super().specifiers(record
=record
)
2162 class SZBaseRM(BaseRM
):
2163 def specifiers(self
, record
):
2167 yield from super().specifiers(record
=record
)
2170 class MRBaseRM(BaseRM
):
2171 def specifiers(self
, record
):
2177 yield from super().specifiers(record
=record
)
2180 class ElsBaseRM(BaseRM
):
2181 def specifiers(self
, record
):
2185 yield from super().specifiers(record
=record
)
2188 class WidthBaseRM(BaseRM
):
2190 def width(FP
, width
):
2199 width
= ("fp" + width
)
2202 def specifiers(self
, record
):
2203 # elwidths: use "w=" if same otherwise dw/sw
2204 # FIXME this should consider FP instructions
2206 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
2207 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2208 if record
.svp64
.mode
is _SVMode
.CROP
:
2212 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2221 yield from super().specifiers(record
=record
)
2224 class PredicateBaseRM(BaseRM
):
2226 def predicate(CR
, mask
):
2229 (False, 0b001): "1<<r3",
2230 (False, 0b010): "r3",
2231 (False, 0b011): "~r3",
2232 (False, 0b100): "r10",
2233 (False, 0b101): "~r10",
2234 (False, 0b110): "r30",
2235 (False, 0b111): "~r30",
2237 (True, 0b000): "lt",
2238 (True, 0b001): "ge",
2239 (True, 0b010): "gt",
2240 (True, 0b011): "le",
2241 (True, 0b100): "eq",
2242 (True, 0b101): "ne",
2243 (True, 0b110): "so",
2244 (True, 0b111): "ns",
2247 def specifiers(self
, record
):
2248 # predication - single and twin
2249 # use "m=" if same otherwise sm/dm
2250 CR
= (int(self
.mmode
) == 1)
2251 mask
= int(self
.mask
)
2252 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
2253 if record
.svp64
.ptype
is _SVPType
.P2
:
2254 # LDST_IDX smask moving to extra322 but not straight away (False)
2255 if False and record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2256 smask
= int(self
.smask_extra332
)
2258 smask
= int(self
.smask
)
2259 sm
= PredicateBaseRM
.predicate(CR
, smask
)
2268 yield from super().specifiers(record
=record
)
2271 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
2275 class SEABaseRM(BaseRM
):
2276 def specifiers(self
, record
):
2280 yield from super().specifiers(record
=record
)
2283 class VLiBaseRM(BaseRM
):
2284 def specifiers(self
, record
):
2288 yield from super().specifiers(record
=record
)
2291 class NormalBaseRM(PredicateWidthBaseRM
):
2294 https://libre-soc.org/openpower/sv/normal/
2299 class NormalSimpleRM(ZZCombinedBaseRM
, NormalBaseRM
):
2300 """normal: simple mode"""
2304 def specifiers(self
, record
):
2305 yield from super().specifiers(record
=record
)
2308 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
2309 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
2313 class NormalFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, NormalBaseRM
):
2314 """normal: Rc=1: ffirst CR sel"""
2317 CR
: BaseRM
.mode
[3, 4]
2319 def specifiers(self
, record
):
2320 yield from super().specifiers(record
=record
, mode
="ff")
2323 class NormalFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
2324 """normal: Rc=0: ffirst z/nonz"""
2329 def specifiers(self
, record
):
2330 yield from super().specifiers(record
=record
, mode
="ff")
2333 class NormalSatRM(SatBaseRM
, ZZCombinedBaseRM
, NormalBaseRM
):
2334 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2340 class NormalRM(NormalBaseRM
):
2341 simple
: NormalSimpleRM
2343 ffrc1
: NormalFFRc1RM
2344 ffrc0
: NormalFFRc0RM
2348 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2350 LD/ST Immediate mode
2351 https://libre-soc.org/openpower/sv/ldst/
2356 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2357 """ld/st immediate: simple mode"""
2358 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2359 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2365 def specifiers(self
, record
):
2371 yield from super().specifiers(record
=record
)
2374 class LDSTFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2375 """ld/st immediate&indexed: Rc=1: ffirst CR sel"""
2378 CR
: BaseRM
.mode
[3, 4]
2380 def specifiers(self
, record
):
2381 yield from super().specifiers(record
=record
, mode
="ff")
2384 class LDSTFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2385 """ld/st immediate&indexed: Rc=0: ffirst z/nonz"""
2390 def specifiers(self
, record
):
2391 yield from super().specifiers(record
=record
, mode
="ff")
2394 class LDSTImmRM(LDSTImmBaseRM
):
2395 simple
: LDSTImmSimpleRM
2400 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2403 https://libre-soc.org/openpower/sv/ldst/
2408 class LDSTIdxSimpleRM(SEABaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2409 """ld/st index: simple mode (includes element-strided and Signed-EA)"""
2410 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2417 def specifiers(self
, record
):
2423 yield from super().specifiers(record
=record
)
2426 class LDSTIdxRM(LDSTIdxBaseRM
):
2427 simple
: LDSTIdxSimpleRM
2433 class CROpBaseRM(BaseRM
):
2436 https://libre-soc.org/openpower/sv/cr_ops/
2441 class CROpSimpleRM(PredicateBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2442 """crop: simple mode"""
2447 def specifiers(self
, record
):
2449 yield "rg" # simple CR Mode reports /rg
2451 yield from super().specifiers(record
=record
)
2454 class CROpMRRM(MRBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2455 """crop: scalar reduce mode (mapreduce)"""
2461 class CROpFF5RM(FFRc0BaseRM
, PredicateBaseRM
, VLiBaseRM
, DZBaseRM
,
2462 SZBaseRM
, CROpBaseRM
):
2463 """crop: ffirst 5-bit mode"""
2470 def specifiers(self
, record
):
2471 yield from super().specifiers(record
=record
, mode
="ff")
2474 # FIXME: almost everything in this class contradicts the specs (it doesn't)
2475 # The modes however are swapped: 5-bit is 3-bit, 3-bit is 5-bit
2476 class CROpFF3RM(FFRc1BaseRM
, PredicateBaseRM
, VLiBaseRM
, ZZBaseRM
, CROpBaseRM
):
2477 """cr_op: ffirst 3-bit mode"""
2483 def specifiers(self
, record
):
2484 yield from super().specifiers(record
=record
, mode
="ff")
2487 class CROpRM(CROpBaseRM
):
2488 simple
: CROpSimpleRM
2494 # ********************
2496 # https://libre-soc.org/openpower/sv/branches/
2497 class BranchBaseRM(BaseRM
):
2507 def specifiers(self
, record
):
2519 raise ValueError(self
.sz
)
2531 # Branch modes lack source mask.
2532 # Therefore a custom code is needed.
2533 CR
= (int(self
.mmode
) == 1)
2534 mask
= int(self
.mask
)
2535 m
= PredicateBaseRM
.predicate(CR
, mask
)
2539 yield from super().specifiers(record
=record
)
2542 class BranchSimpleRM(BranchBaseRM
):
2543 """branch: simple mode"""
2547 class BranchVLSRM(BranchBaseRM
):
2548 """branch: VLSET mode"""
2552 def specifiers(self
, record
):
2558 }[int(self
.VSb
), int(self
.VLi
)]
2560 yield from super().specifiers(record
=record
)
2563 class BranchCTRRM(BranchBaseRM
):
2564 """branch: CTR-test mode"""
2567 def specifiers(self
, record
):
2573 yield from super().specifiers(record
=record
)
2576 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2577 """branch: CTR-test+VLSET mode"""
2581 class BranchRM(BranchBaseRM
):
2582 simple
: BranchSimpleRM
2585 ctrvls
: BranchCTRVLSRM
2596 @_dataclasses.dataclass(eq
=True, frozen
=True)
2601 def match(cls
, desc
, record
):
2602 raise NotImplementedError()
2604 def validate(self
, others
):
2607 def assemble(self
, insn
):
2608 raise NotImplementedError()
2611 @_dataclasses.dataclass(eq
=True, frozen
=True)
2612 class SpecifierWidth(Specifier
):
2616 def match(cls
, desc
, record
, etalon
):
2617 (mode
, _
, value
) = desc
.partition("=")
2619 value
= value
.strip()
2622 width
= _SVP64Width(value
)
2624 return cls(record
=record
, width
=width
)
2627 @_dataclasses.dataclass(eq
=True, frozen
=True)
2628 class SpecifierW(SpecifierWidth
):
2630 def match(cls
, desc
, record
):
2631 return super().match(desc
=desc
, record
=record
, etalon
="w")
2633 def assemble(self
, insn
):
2634 selector
= insn
.select(record
=self
.record
)
2635 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2636 selector
.ewsrc
= self
.width
.value
2637 selector
.elwidth
= self
.width
.value
2640 @_dataclasses.dataclass(eq
=True, frozen
=True)
2641 class SpecifierSW(SpecifierWidth
):
2643 def match(cls
, desc
, record
):
2644 if record
.svp64
.mode
is _SVMode
.CROP
:
2646 return super().match(desc
=desc
, record
=record
, etalon
="sw")
2648 def assemble(self
, insn
):
2649 selector
= insn
.select(record
=self
.record
)
2650 selector
.ewsrc
= self
.width
.value
2653 @_dataclasses.dataclass(eq
=True, frozen
=True)
2654 class SpecifierDW(SpecifierWidth
):
2656 def match(cls
, desc
, record
):
2657 return super().match(desc
=desc
, record
=record
, etalon
="dw")
2659 def assemble(self
, insn
):
2660 selector
= insn
.select(record
=self
.record
)
2661 selector
.elwidth
= self
.width
.value
2664 @_dataclasses.dataclass(eq
=True, frozen
=True)
2665 class SpecifierSubVL(Specifier
):
2669 def match(cls
, desc
, record
):
2671 value
= _SVP64SubVL(desc
)
2675 return cls(record
=record
, value
=value
)
2677 def assemble(self
, insn
):
2678 selector
= insn
.select(record
=self
.record
)
2679 selector
.subvl
= int(self
.value
.value
)
2682 @_dataclasses.dataclass(eq
=True, frozen
=True)
2683 class SpecifierPredicate(Specifier
):
2688 def match(cls
, desc
, record
, mode_match
, pred_match
):
2689 (mode
, _
, pred
) = desc
.partition("=")
2692 if not mode_match(mode
):
2695 pred
= _SVP64Pred(pred
.strip())
2696 if not pred_match(pred
):
2697 raise ValueError(pred
)
2699 return cls(record
=record
, mode
=mode
, pred
=pred
)
2702 @_dataclasses.dataclass(eq
=True, frozen
=True)
2703 class SpecifierFF(SpecifierPredicate
):
2705 def match(cls
, desc
, record
):
2706 return super().match(desc
=desc
, record
=record
,
2707 mode_match
=lambda mode_arg
: mode_arg
== "ff",
2708 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2713 def assemble(self
, insn
):
2714 selector
= insn
.select(record
=self
.record
)
2715 if selector
.mode
.sel
!= 0:
2716 raise ValueError("cannot override mode")
2717 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2718 selector
.mode
.sel
= 0b01
2719 # HACK: please finally provide correct logic for CRs.
2720 if self
.pred
in (_SVP64Pred
.RC1
, _SVP64Pred
.RC1_N
):
2721 selector
.mode
[2] = (self
.pred
is _SVP64Pred
.RC1_N
)
2723 selector
.mode
[2] = self
.pred
.inv
2724 selector
.mode
[3, 4] = self
.pred
.state
2726 selector
.mode
.sel
= 0b01 if self
.mode
== "ff" else 0b11
2727 selector
.inv
= self
.pred
.inv
2729 selector
.CR
= self
.pred
.state
2731 selector
.RC1
= self
.pred
.state
2734 @_dataclasses.dataclass(eq
=True, frozen
=True)
2735 class SpecifierMask(SpecifierPredicate
):
2737 def match(cls
, desc
, record
, mode
):
2738 return super().match(desc
=desc
, record
=record
,
2739 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2740 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2745 def assemble(self
, insn
):
2746 raise NotImplementedError()
2749 @_dataclasses.dataclass(eq
=True, frozen
=True)
2750 class SpecifierM(SpecifierMask
):
2752 def match(cls
, desc
, record
):
2753 return super().match(desc
=desc
, record
=record
, mode
="m")
2755 def validate(self
, others
):
2757 if isinstance(spec
, SpecifierSM
):
2758 raise ValueError("source-mask and predicate mask conflict")
2759 elif isinstance(spec
, SpecifierDM
):
2760 raise ValueError("dest-mask and predicate mask conflict")
2762 def assemble(self
, insn
):
2763 selector
= insn
.select(record
=self
.record
)
2764 selector
.mask
= int(self
.pred
)
2765 if ((self
.record
.ptype
is _SVPType
.P2
) and
2766 (self
.record
.svp64
.mode
is not _SVMode
.BRANCH
)):
2767 selector
.smask
= int(self
.pred
)
2768 # LDST_IDX smask moving to extra322 but not straight away (False)
2769 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2770 selector
.smask_extra332
= int(self
.pred
)
2772 selector
.smask
= int(self
.pred
)
2774 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2777 @_dataclasses.dataclass(eq
=True, frozen
=True)
2778 class SpecifierSM(SpecifierMask
):
2780 def match(cls
, desc
, record
):
2781 return super().match(desc
=desc
, record
=record
, mode
="sm")
2783 def validate(self
, others
):
2784 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2785 raise ValueError("source-mask on non-twin predicate")
2787 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2790 if isinstance(spec
, SpecifierDM
):
2794 raise ValueError("missing dest-mask in CR twin predication")
2795 if self
.pred
.mode
!= twin
.pred
.mode
:
2796 raise ValueError(f
"predicate masks mismatch: "
2797 f
"{self.pred!r} vs {twin.pred!r}")
2799 def assemble(self
, insn
):
2800 selector
= insn
.select(record
=self
.record
)
2801 # LDST_IDX smask moving to extra322 but not straight away (False)
2802 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2803 selector
.smask_extra332
= int(self
.pred
)
2805 selector
.smask
= int(self
.pred
)
2806 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2809 @_dataclasses.dataclass(eq
=True, frozen
=True)
2810 class SpecifierDM(SpecifierMask
):
2812 def match(cls
, desc
, record
):
2813 return super().match(desc
=desc
, record
=record
, mode
="dm")
2815 def validate(self
, others
):
2816 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2817 raise ValueError("dest-mask on non-twin predicate")
2819 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2822 if isinstance(spec
, SpecifierSM
):
2826 raise ValueError("missing source-mask in CR twin predication")
2827 if self
.pred
.mode
!= twin
.pred
.mode
:
2828 raise ValueError(f
"predicate masks mismatch: "
2829 f
"{self.pred!r} vs {twin.pred!r}")
2831 def assemble(self
, insn
):
2832 selector
= insn
.select(record
=self
.record
)
2833 selector
.mask
= int(self
.pred
)
2834 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2837 @_dataclasses.dataclass(eq
=True, frozen
=True)
2838 class SpecifierZZ(Specifier
):
2840 def match(cls
, desc
, record
):
2844 return cls(record
=record
)
2846 def validate(self
, others
):
2848 # Since zz takes precedence (overrides) sz and dz,
2849 # treat them as mutually exclusive.
2850 if isinstance(spec
, (SpecifierSZ
, SpecifierDZ
)):
2851 raise ValueError("mutually exclusive predicate masks")
2853 def assemble(self
, insn
):
2854 selector
= insn
.select(record
=self
.record
)
2855 if hasattr(selector
, "zz"): # this should be done in a different way
2862 @_dataclasses.dataclass(eq
=True, frozen
=True)
2863 class SpecifierXZ(Specifier
):
2865 hint
: str = _dataclasses
.field(repr=False)
2868 def match(cls
, desc
, record
, etalon
, hint
):
2872 return cls(desc
=desc
, record
=record
, hint
=hint
)
2874 def validate(self
, others
):
2875 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2876 raise ValueError(f
"{self.hint} on non-twin predicate")
2878 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2881 if isinstance(spec
, SpecifierXZ
):
2885 raise ValueError(f
"missing {self.hint} in CR twin predication")
2886 if self
.pred
!= twin
.pred
:
2887 raise ValueError(f
"predicate masks mismatch: "
2888 f
"{self.pred!r} vs {twin.pred!r}")
2890 def assemble(self
, insn
):
2891 selector
= insn
.select(record
=self
.record
)
2892 setattr(selector
, self
.desc
, 1)
2895 @_dataclasses.dataclass(eq
=True, frozen
=True)
2896 class SpecifierSZ(SpecifierXZ
):
2898 def match(cls
, desc
, record
):
2899 return super().match(desc
=desc
, record
=record
,
2900 etalon
="sz", hint
="source-mask")
2902 def validate(self
, others
):
2904 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2905 if isinstance(spec
, SpecifierFF
):
2906 raise ValueError("source-zero not allowed in ff mode")
2909 @_dataclasses.dataclass(eq
=True, frozen
=True)
2910 class SpecifierDZ(SpecifierXZ
):
2912 def match(cls
, desc
, record
):
2913 return super().match(desc
=desc
, record
=record
,
2914 etalon
="dz", hint
="dest-mask")
2916 def validate(self
, others
):
2918 if ((self
.record
.svp64
.mode
is not _SVMode
.CROP
) and
2919 isinstance(spec
, SpecifierFF
) and
2920 (spec
.pred
.mode
is _SVP64PredMode
.RC1
)):
2921 raise ValueError(f
"dest-zero not allowed in ff mode BO")
2924 @_dataclasses.dataclass(eq
=True, frozen
=True)
2925 class SpecifierEls(Specifier
):
2927 def match(cls
, desc
, record
):
2931 if record
.svp64
.mode
not in (_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
):
2932 raise ValueError("els is only valid in ld/st modes, not "
2933 "%s" % str(self
.record
.svp64
.mode
))
2935 return cls(record
=record
)
2937 def assemble(self
, insn
):
2938 if self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
: # stride mode
2939 insn
.prefix
.rm
.mode
[1] = 0
2941 selector
= insn
.select(record
=self
.record
)
2946 @_dataclasses.dataclass(eq
=True, frozen
=True)
2947 class SpecifierSEA(Specifier
):
2949 def match(cls
, desc
, record
):
2953 return cls(record
=record
)
2955 def validate(self
, others
):
2956 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
:
2957 raise ValueError("sea is only valid in ld/st modes, not "
2958 "%s" % str(self
.record
.svp64
.mode
))
2961 if isinstance(spec
, SpecifierFF
):
2962 raise ValueError(f
"sea cannot be used in ff mode")
2964 def assemble(self
, insn
):
2965 selector
= insn
.select(record
=self
.record
)
2966 if selector
.mode
.sel
not in (0b10, 0b00):
2967 raise ValueError("sea is only valid for normal and els modes, "
2968 "not %d" % int(selector
.mode
.sel
))
2972 @_dataclasses.dataclass(eq
=True, frozen
=True)
2973 class SpecifierSat(Specifier
):
2978 def match(cls
, desc
, record
, etalon
, sign
):
2982 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.LDST_IMM
,
2984 raise ValueError("only normal, ld/st imm and "
2985 "ld/st idx modes supported")
2987 return cls(record
=record
, desc
=desc
, sign
=sign
)
2989 def assemble(self
, insn
):
2990 selector
= insn
.select(record
=self
.record
)
2991 selector
.mode
[0] = 0b1
2992 selector
.mode
[1] = 0b0
2993 selector
.N
= int(self
.sign
)
2996 @_dataclasses.dataclass(eq
=True, frozen
=True)
2997 class SpecifierSatS(SpecifierSat
):
2999 def match(cls
, desc
, record
):
3000 return super().match(desc
=desc
, record
=record
,
3001 etalon
="sats", sign
=True)
3004 @_dataclasses.dataclass(eq
=True, frozen
=True)
3005 class SpecifierSatU(SpecifierSat
):
3007 def match(cls
, desc
, record
):
3008 return super().match(desc
=desc
, record
=record
,
3009 etalon
="satu", sign
=False)
3012 @_dataclasses.dataclass(eq
=True, frozen
=True)
3013 class SpecifierMapReduce(Specifier
):
3017 def match(cls
, record
, RG
):
3018 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
3019 raise ValueError("only normal and crop modes supported")
3021 return cls(record
=record
, RG
=RG
)
3023 def assemble(self
, insn
):
3024 selector
= insn
.select(record
=self
.record
)
3025 if self
.record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
3026 raise ValueError("only normal and crop modes supported")
3027 selector
.mode
[0] = 0
3028 selector
.mode
[1] = 0
3029 selector
.mode
[2] = 1
3030 selector
.RG
= self
.RG
3033 @_dataclasses.dataclass(eq
=True, frozen
=True)
3034 class SpecifierMR(SpecifierMapReduce
):
3036 def match(cls
, desc
, record
):
3040 return super().match(record
=record
, RG
=False)
3043 @_dataclasses.dataclass(eq
=True, frozen
=True)
3044 class SpecifierMRR(SpecifierMapReduce
):
3046 def match(cls
, desc
, record
):
3050 return super().match(record
=record
, RG
=True)
3053 @_dataclasses.dataclass(eq
=True, frozen
=True)
3054 class SpecifierBranch(Specifier
):
3056 def match(cls
, desc
, record
, etalon
):
3060 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3061 raise ValueError("only branch modes supported")
3063 return cls(record
=record
)
3066 @_dataclasses.dataclass(eq
=True, frozen
=True)
3067 class SpecifierAll(SpecifierBranch
):
3069 def match(cls
, desc
, record
):
3070 return super().match(desc
=desc
, record
=record
, etalon
="all")
3072 def assemble(self
, insn
):
3073 selector
= insn
.select(record
=self
.record
)
3077 @_dataclasses.dataclass(eq
=True, frozen
=True)
3078 class SpecifierSNZ(Specifier
):
3080 def match(cls
, desc
, record
):
3084 if record
.svp64
.mode
not in (_SVMode
.BRANCH
, _SVMode
.CROP
):
3085 raise ValueError("only branch and crop modes supported")
3087 return cls(record
=record
)
3089 def assemble(self
, insn
):
3090 selector
= insn
.select(record
=self
.record
)
3091 if self
.record
.svp64
.mode
in (_SVMode
.CROP
, _SVMode
.BRANCH
):
3093 if self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3096 raise ValueError("only branch and crop modes supported")
3099 @_dataclasses.dataclass(eq
=True, frozen
=True)
3100 class SpecifierSL(SpecifierBranch
):
3102 def match(cls
, desc
, record
):
3103 return super().match(desc
=desc
, record
=record
, etalon
="sl")
3105 def assemble(self
, insn
):
3106 selector
= insn
.select(record
=self
.record
)
3110 @_dataclasses.dataclass(eq
=True, frozen
=True)
3111 class SpecifierSLu(SpecifierBranch
):
3113 def match(cls
, desc
, record
):
3114 return super().match(desc
=desc
, record
=record
, etalon
="slu")
3116 def assemble(self
, insn
):
3117 selector
= insn
.select(record
=self
.record
)
3121 @_dataclasses.dataclass(eq
=True, frozen
=True)
3122 class SpecifierLRu(SpecifierBranch
):
3124 def match(cls
, desc
, record
):
3125 return super().match(desc
=desc
, record
=record
, etalon
="lru")
3127 def assemble(self
, insn
):
3128 selector
= insn
.select(record
=self
.record
)
3132 @_dataclasses.dataclass(eq
=True, frozen
=True)
3133 class SpecifierVSXX(SpecifierBranch
):
3138 def match(cls
, desc
, record
, etalon
, VSb
, VLi
):
3142 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3143 raise ValueError("only branch modes supported")
3145 return cls(record
=record
, VSb
=VSb
, VLi
=VLi
)
3147 def assemble(self
, insn
):
3148 selector
= insn
.select(record
=self
.record
)
3150 selector
.VSb
= int(self
.VSb
)
3151 selector
.VLi
= int(self
.VLi
)
3154 @_dataclasses.dataclass(eq
=True, frozen
=True)
3155 class SpecifierVS(SpecifierVSXX
):
3157 def match(cls
, desc
, record
):
3158 return super().match(desc
=desc
, record
=record
,
3159 etalon
="vs", VSb
=False, VLi
=False)
3162 @_dataclasses.dataclass(eq
=True, frozen
=True)
3163 class SpecifierVSi(SpecifierVSXX
):
3165 def match(cls
, desc
, record
):
3166 return super().match(desc
=desc
, record
=record
,
3167 etalon
="vsi", VSb
=False, VLi
=True)
3170 @_dataclasses.dataclass(eq
=True, frozen
=True)
3171 class SpecifierVSb(SpecifierVSXX
):
3173 def match(cls
, desc
, record
):
3174 return super().match(desc
=desc
, record
=record
,
3175 etalon
="vsb", VSb
=True, VLi
=False)
3178 @_dataclasses.dataclass(eq
=True, frozen
=True)
3179 class SpecifierVSbi(SpecifierVSXX
):
3181 def match(cls
, desc
, record
):
3182 return super().match(desc
=desc
, record
=record
,
3183 etalon
="vsbi", VSb
=True, VLi
=True)
3186 @_dataclasses.dataclass(eq
=True, frozen
=True)
3187 class SpecifierCTX(Specifier
):
3191 def match(cls
, desc
, record
, etalon
, CTi
):
3195 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3196 raise ValueError("only branch modes supported")
3198 return cls(record
=record
, CTi
=CTi
)
3200 def assemble(self
, insn
):
3201 selector
= insn
.select(record
=self
.record
)
3203 selector
.CTi
= int(self
.CTi
)
3206 @_dataclasses.dataclass(eq
=True, frozen
=True)
3207 class SpecifierCTR(SpecifierCTX
):
3209 def match(cls
, desc
, record
):
3210 return super().match(desc
=desc
, record
=record
,
3211 etalon
="ctr", CTi
=False)
3214 @_dataclasses.dataclass(eq
=True, frozen
=True)
3215 class SpecifierCTi(SpecifierCTX
):
3217 def match(cls
, desc
, record
):
3218 return super().match(desc
=desc
, record
=record
,
3219 etalon
="cti", CTi
=True)
3222 @_dataclasses.dataclass(eq
=True, frozen
=True)
3223 class SpecifierPI(Specifier
):
3225 def match(cls
, desc
, record
):
3229 if record
.svp64
.mode
not in [_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
]:
3230 raise ValueError("only ld/st imm/idx mode supported")
3232 return cls(record
=record
)
3234 def assemble(self
, insn
):
3235 selector
= insn
.select(record
=self
.record
)
3236 selector
.mode
[2] = 0b1
3240 @_dataclasses.dataclass(eq
=True, frozen
=True)
3241 class SpecifierLF(Specifier
):
3243 def match(cls
, desc
, record
):
3247 if record
.svp64
.mode
is not _SVMode
.LDST_IMM
:
3248 raise ValueError("only ld/st imm mode supported")
3250 return cls(record
=record
)
3252 def assemble(self
, insn
):
3253 selector
= insn
.select(record
=self
.record
)
3254 selector
.mode
[1] = 0
3258 @_dataclasses.dataclass(eq
=True, frozen
=True)
3259 class SpecifierVLi(Specifier
):
3261 def match(cls
, desc
, record
):
3265 return cls(record
=record
)
3267 def validate(self
, others
):
3269 if isinstance(spec
, SpecifierFF
):
3272 raise ValueError("VLi only allowed in failfirst")
3274 def assemble(self
, insn
):
3275 selector
= insn
.select(record
=self
.record
)
3276 selector
.mode
[1] = 1
3280 class Specifiers(tuple):
3315 def __new__(cls
, items
, record
):
3316 def transform(item
):
3317 for spec_cls
in cls
.SPECS
:
3318 spec
= spec_cls
.match(item
, record
=record
)
3319 if spec
is not None:
3321 raise ValueError(item
)
3323 # TODO: remove this hack
3324 items
= dict.fromkeys(items
)
3328 items
= tuple(items
)
3330 specs
= tuple(map(transform
, items
))
3331 for (index
, spec
) in enumerate(specs
):
3332 head
= specs
[:index
]
3333 tail
= specs
[index
+ 1:]
3334 spec
.validate(others
=(head
+ tail
))
3336 return super().__new
__(cls
, specs
)
3339 class SVP64OperandMeta(type):
3340 class SVP64NonZeroOperand(NonZeroOperand
):
3341 def assemble(self
, insn
, value
):
3342 if isinstance(value
, str):
3343 value
= int(value
, 0)
3344 if not isinstance(value
, int):
3345 raise ValueError("non-integer operand")
3347 # FIXME: this is really weird
3348 if self
.record
.name
in ("svstep", "svstep."):
3349 value
+= 1 # compensation
3351 return super().assemble(value
=value
, insn
=insn
)
3353 class SVP64XOStaticOperand(SpanStaticOperand
):
3354 def __init__(self
, record
, value
, span
):
3355 return super().__init
__(record
=record
, name
="XO",
3356 value
=value
, span
=span
)
3359 NonZeroOperand
: SVP64NonZeroOperand
,
3360 XOStaticOperand
: SVP64XOStaticOperand
,
3363 def __new__(metacls
, name
, bases
, ns
):
3365 for (index
, base_cls
) in enumerate(bases
):
3366 bases
[index
] = metacls
.__TRANSFORM
.get(base_cls
, base_cls
)
3368 bases
= tuple(bases
)
3370 return super().__new
__(metacls
, name
, bases
, ns
)
3373 class SVP64Operand(Operand
, metaclass
=SVP64OperandMeta
):
3376 return tuple(map(lambda bit
: (bit
+ 32), super().span
))
3380 def __init__(self
, insn
, record
):
3382 self
.__record
= record
3383 return super().__init
__()
3386 return self
.rm
.__doc
__
3389 return repr(self
.rm
)
3397 return self
.__record
3401 rm
= getattr(self
.insn
.prefix
.rm
, self
.record
.svp64
.mode
.name
.lower())
3403 # The idea behind these tables is that they are now literally
3404 # in identical format to insndb.csv and minor_xx.csv and can
3405 # be done precisely as that. The only thing to watch out for
3406 # is the insertion of Rc=1 as a "mask/value" bit and likewise
3407 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
3410 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
3411 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3412 # mode Rc mask Rc member
3414 (0b000000, 0b111000, "simple"), # simple (no Rc)
3415 (0b001000, 0b111100, "mr"), # mapreduce (no Rc)
3416 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3417 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3418 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3419 (0b001100, 0b111100, "rsvd"), # reserved
3421 mode
= int(self
.insn
.prefix
.rm
.normal
.mode
)
3422 search
= ((mode
<< 1) | self
.record
.Rc
)
3424 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
3425 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3426 # mode Rc mask Rc member
3427 # ironically/coincidentally this table is identical to NORMAL
3428 # mode except reserved in place of mr
3430 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3431 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3432 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3434 search
= ((int(self
.insn
.prefix
.rm
.ldst_imm
.mode
) << 1) |
3437 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
3438 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3439 # mode Rc mask Rc member
3441 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3442 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3443 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3445 search
= ((int(self
.insn
.prefix
.rm
.ldst_idx
.mode
) << 1) |
3448 elif self
.record
.svp64
.mode
is _SVMode
.CROP
:
3449 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
3450 # mode 3b mask 3b member
3452 (0b000000, 0b111000, "simple"), # simple
3453 (0b001000, 0b111000, "mr"), # mapreduce
3454 (0b010001, 0b010001, "ff3"), # ffirst, 3-bit CR
3455 (0b010000, 0b010000, "ff5"), # ffirst, 5-bit CR
3457 search
= ((int(self
.insn
.prefix
.rm
.crop
.mode
) << 1) |
3458 int(self
.record
.svp64
.extra_CR_3bit
))
3460 elif self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3464 (0b00, 0b11, "simple"), # simple
3465 (0b01, 0b11, "vls"), # VLset
3466 (0b10, 0b11, "ctr"), # CTR mode
3467 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
3469 # slightly weird: doesn't have a 5-bit "mode" field like others
3470 search
= int(self
.insn
.prefix
.rm
.branch
.mode
.sel
)
3473 if table
is not None:
3474 for (value
, mask
, field
) in table
:
3475 if field
.startswith("rsvd"):
3477 if ((value
& mask
) == (search
& mask
)):
3478 return getattr(rm
, field
)
3482 def __getattr__(self
, key
):
3483 if key
.startswith(f
"_{self.__class__.__name__}__"):
3484 return super().__getattribute
__(key
)
3486 return getattr(self
.rm
, key
)
3488 def __setattr__(self
, key
, value
):
3489 if key
.startswith(f
"_{self.__class__.__name__}__"):
3490 return super().__setattr
__(key
, value
)
3493 if not hasattr(rm
, key
):
3494 raise AttributeError(key
)
3496 return setattr(rm
, key
, value
)
3499 class SVP64Instruction(PrefixedInstruction
):
3500 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
3501 class Prefix(PrefixedInstruction
.Prefix
):
3503 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
3507 def select(self
, record
):
3508 return RMSelector(insn
=self
, record
=record
)
3513 for idx
in range(64):
3514 bit
= int(self
[idx
])
3516 return "".join(map(str, bits
))
3519 def assemble(cls
, record
, arguments
=None, specifiers
=None):
3520 insn
= super().assemble(record
=record
, arguments
=arguments
)
3522 specifiers
= Specifiers(items
=specifiers
, record
=record
)
3523 for specifier
in specifiers
:
3524 specifier
.assemble(insn
=insn
)
3526 insn
.prefix
.PO
= 0x1
3527 insn
.prefix
.id = 0x3
3531 def disassemble(self
, record
,
3533 style
=Style
.NORMAL
):
3535 if style
<= Style
.SHORT
:
3538 blob
= insn
.bytes(byteorder
=byteorder
)
3539 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
3542 blob_prefix
= blob(self
.prefix
)
3543 blob_suffix
= blob(self
.suffix
)
3545 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3546 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
3549 assert record
.svp64
is not None
3551 name
= f
"sv.{record.name}"
3553 rm
= self
.select(record
=record
)
3555 # convert specifiers to /x/y/z (sorted lexicographically)
3556 specifiers
= sorted(rm
.specifiers(record
=record
))
3557 if specifiers
: # if any add one extra to get the extra "/"
3558 specifiers
= ([""] + specifiers
)
3559 specifiers
= "/".join(specifiers
)
3561 # convert operands to " ,x,y,z"
3562 operands
= tuple(map(_operator
.itemgetter(1),
3563 self
.spec_dynamic_operands(record
=record
, style
=style
)))
3564 operands
= ",".join(operands
)
3565 if len(operands
) > 0: # if any separate with a space
3566 operands
= (" " + operands
)
3568 if style
<= Style
.LEGACY
:
3569 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3570 suffix
= WordInstruction
.integer(value
=int(self
.suffix
))
3571 yield from suffix
.disassemble(record
=record
,
3572 byteorder
=byteorder
, style
=style
)
3574 yield f
"{blob_prefix}{name}{specifiers}{operands}"
3576 yield f
"{blob_suffix}"
3578 if style
>= Style
.VERBOSE
:
3580 binary
= self
.binary
3581 spec
= self
.spec(record
=record
, prefix
="sv.")
3583 yield f
"{indent}spec"
3584 yield f
"{indent}{indent}{spec}"
3585 yield f
"{indent}pcode"
3586 for stmt
in record
.mdwn
.pcode
:
3587 yield f
"{indent}{indent}{stmt}"
3588 yield f
"{indent}binary"
3589 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
3590 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
3591 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
3592 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
3593 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
3594 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
3595 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
3596 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
3597 yield f
"{indent}opcodes"
3598 for opcode
in record
.opcodes
:
3599 yield f
"{indent}{indent}{opcode!r}"
3600 for operand
in self
.operands(record
=record
):
3601 yield from operand
.disassemble(insn
=self
,
3602 style
=style
, indent
=indent
)
3604 yield f
"{indent}{indent}{str(rm)}"
3605 for line
in rm
.disassemble(style
=style
):
3606 yield f
"{indent}{indent}{line}"
3610 def operands(cls
, record
):
3611 for operand
in super().operands(record
=record
):
3612 parent
= operand
.__class
__
3613 name
= f
"SVP64{parent.__name__}"
3614 bases
= (SVP64Operand
, parent
)
3615 child
= type(name
, bases
, {})
3616 yield child(**dict(operand
))
3619 def parse(stream
, factory
):
3621 return ("TODO" not in frozenset(entry
.values()))
3623 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
3624 entries
= _csv
.DictReader(lines
)
3625 entries
= filter(match
, entries
)
3626 return tuple(map(factory
, entries
))
3629 class MarkdownDatabase
:
3632 for (name
, desc
) in _ISA():
3635 (dynamic
, *static
) = desc
.regs
3636 operands
.extend(dynamic
)
3637 operands
.extend(static
)
3638 pcode
= PCode(iterable
=filter(str.strip
, desc
.pcode
))
3639 operands
= Operands(insn
=name
, operands
=operands
)
3640 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
3642 self
.__db
= dict(sorted(db
.items()))
3644 return super().__init
__()
3647 yield from self
.__db
.items()
3649 def __contains__(self
, key
):
3650 return self
.__db
.__contains
__(key
)
3652 def __getitem__(self
, key
):
3653 return self
.__db
.__getitem
__(key
)
3656 class FieldsDatabase
:
3659 df
= _DecodeFields()
3661 for (form
, fields
) in df
.instrs
.items():
3662 if form
in {"DQE", "TX"}:
3666 db
[_Form
[form
]] = Fields(fields
)
3670 return super().__init
__()
3672 def __getitem__(self
, key
):
3673 return self
.__db
.__getitem
__(key
)
3677 def __init__(self
, root
, mdwndb
):
3678 # The code below groups the instructions by name:section.
3679 # There can be multiple names for the same instruction.
3680 # The point is to capture different opcodes for the same instruction.
3682 records
= _collections
.defaultdict(set)
3683 path
= (root
/ "insndb.csv")
3684 with
open(path
, "r", encoding
="UTF-8") as stream
:
3685 for section
in sorted(parse(stream
, Section
.CSV
)):
3686 path
= (root
/ section
.csv
)
3688 section
.Mode
.INTEGER
: IntegerOpcode
,
3689 section
.Mode
.PATTERN
: PatternOpcode
,
3691 factory
= _functools
.partial(
3692 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
3693 with
open(path
, "r", encoding
="UTF-8") as stream
:
3694 for insn
in parse(stream
, factory
):
3695 for name
in insn
.names
:
3696 records
[name
].add(insn
)
3697 sections
[name
] = section
3699 items
= sorted(records
.items())
3701 for (name
, multirecord
) in items
:
3702 records
[name
] = PPCMultiRecord(sorted(multirecord
))
3704 def exact_match(name
):
3705 record
= records
.get(name
)
3711 if not name
.endswith("l"):
3713 alias
= exact_match(name
[:-1])
3716 record
= records
[alias
]
3717 if "lk" not in record
.flags
:
3718 raise ValueError(record
)
3722 if not name
.endswith("a"):
3724 alias
= LK_match(name
[:-1])
3727 record
= records
[alias
]
3728 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
3729 raise ValueError(record
)
3730 if "AA" not in mdwndb
[name
].operands
:
3731 raise ValueError(record
)
3735 if not name
.endswith("."):
3737 alias
= exact_match(name
[:-1])
3740 record
= records
[alias
]
3741 if record
.Rc
is _RCOE
.NONE
:
3742 raise ValueError(record
)
3746 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
3747 for (name
, _
) in mdwndb
:
3748 if name
.startswith("sv."):
3751 for match
in matches
:
3753 if alias
is not None:
3757 section
= sections
[alias
]
3758 record
= records
[alias
]
3759 db
[name
] = (section
, record
)
3761 self
.__db
= dict(sorted(db
.items()))
3763 return super().__init
__()
3765 @_functools.lru_cache(maxsize
=512, typed
=False)
3766 def __getitem__(self
, key
):
3767 return self
.__db
.get(key
, (None, None))
3770 class SVP64Database
:
3771 def __init__(self
, root
, ppcdb
):
3773 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
3774 for (prefix
, _
, names
) in _os
.walk(root
):
3775 prefix
= _pathlib
.Path(prefix
)
3776 for name
in filter(lambda name
: pattern
.match(name
), names
):
3777 path
= (prefix
/ _pathlib
.Path(name
))
3778 with
open(path
, "r", encoding
="UTF-8") as stream
:
3779 db
.update(parse(stream
, SVP64Record
.CSV
))
3780 db
= {record
.name
:record
for record
in db
}
3782 self
.__db
= dict(sorted(db
.items()))
3783 self
.__ppcdb
= ppcdb
3785 return super().__init
__()
3787 def __getitem__(self
, key
):
3788 (_
, record
) = self
.__ppcdb
[key
]
3792 for name
in record
.names
:
3793 record
= self
.__db
.get(name
, None)
3794 if record
is not None:
3800 class Records(Tuple
, datatype
=Record
):
3801 def __new__(cls
, records
):
3802 return super().__new
__(cls
, sorted(records
))
3805 class Database(Node
):
3806 def __init__(self
, root
):
3807 root
= _pathlib
.Path(root
)
3808 mdwndb
= MarkdownDatabase()
3809 fieldsdb
= FieldsDatabase()
3810 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
3811 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
3815 opcodes
= _collections
.defaultdict(
3816 lambda: _collections
.defaultdict(set))
3818 for (name
, mdwn
) in mdwndb
:
3819 if name
.startswith("sv."):
3821 (section
, ppc
) = ppcdb
[name
]
3824 svp64
= svp64db
[name
]
3825 fields
= fieldsdb
[ppc
.form
]
3826 record
= Record(name
=name
,
3827 section
=section
, ppc
=ppc
, svp64
=svp64
,
3828 mdwn
=mdwn
, fields
=fields
)
3830 names
[record
.name
] = record
3831 opcodes
[section
][record
.PO
].add(record
)
3833 self
.__db
= Records(db
)
3834 self
.__names
= dict(sorted(names
.items()))
3835 self
.__opcodes
= dict(sorted(opcodes
.items()))
3837 return super().__init
__()
3840 def walk(clsself
, match
=lambda _
: True):
3841 if isinstance(clsself
, type):
3842 yield ("records", Records
)
3844 if match(clsself
.__db
):
3845 yield ("records", clsself
.__db
)
3848 return repr(self
.__db
)
3851 yield from self
.__db
3853 @_functools.lru_cache(maxsize
=None)
3854 def __contains__(self
, key
):
3855 return self
.__getitem
__(key
) is not None
3857 @_functools.lru_cache(maxsize
=None)
3858 def __getitem__(self
, key
):
3859 if isinstance(key
, SVP64Instruction
):
3862 if isinstance(key
, Instruction
):
3865 sections
= sorted(self
.__opcodes
)
3866 for section
in sections
:
3867 group
= self
.__opcodes
[section
]
3868 for record
in group
[PO
]:
3869 if record
.match(key
=key
):
3874 elif isinstance(key
, str):
3875 return self
.__names
.get(key
)
3877 raise ValueError("instruction or name expected")