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
=lambda _
: True):
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
=lambda _
: True):
87 def field_type(field
):
90 def field_value(field
):
91 return getattr(clsself
, field
.name
)
93 field_node
= (field_type
if isinstance(clsself
, type) else field_value
)
95 for field
in _dataclasses
.fields(clsself
):
97 node
= field_node(field
)
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
=lambda _
: True):
108 if isinstance(clsself
, type):
109 yield ("[]", clsself
.__datatype
)
111 for (index
, item
) in enumerate(clsself
):
113 yield (str(index
), item
)
116 class Dict(Node
, dict):
117 def __init_subclass__(cls
, datatype
):
118 cls
.__datatype
= datatype
119 return super().__init
_subclass
__()
122 return hash(tuple(sorted(self
.items())))
125 raise NotImplementedError()
127 def __delitem__(self
, key
):
128 raise NotImplementedError()
130 def __setitem__(self
, key
, value
):
131 raise NotImplementedError()
133 def popitem(self
) -> tuple:
134 raise NotImplementedError()
136 def pop(self
, key
, default
=None):
137 raise NotImplementedError()
139 def update(self
, entry
, **kwargs
):
140 raise NotImplementedError()
143 def walk(clsself
, match
=lambda _
: True):
144 if isinstance(clsself
, type):
145 yield ("{}", clsself
.__datatype
)
147 for (key
, value
) in clsself
.items():
153 def __init__(self
, nodecls
, method
):
154 self
.__nodecls
= nodecls
155 self
.__method
= method
156 return super().__init
__()
160 return self
.__nodecls
162 @_contextlib.contextmanager
163 def __call__(self
, path
, node
):
164 return self
.__method
(self
=self
, path
=path
, node
=node
)
167 class VisitorMeta(type):
168 def __init__(cls
, name
, bases
, ns
):
170 for (key
, value
) in ns
.items():
171 if isinstance(value
, VisitorMethod
):
172 if value
.type in cls
.__registry
:
173 raise AttributeError(f
"overriding visitor method: {key!r}")
174 cls
.__registry
[value
.type] = value
175 return super().__init
__(name
, bases
, ns
)
177 def __contains__(self
, nodecls
):
178 return self
.__registry
.__contains
__(nodecls
)
180 def __getitem__(self
, nodecls
):
181 return self
.__registry
.__getitem
__(nodecls
)
183 def __setitem__(self
, nodecls
, call
):
184 return self
.__registry
.__setitem
__(nodecls
, call
)
187 yield from self
.__registry
.items()
190 class Visitor(metaclass
=VisitorMeta
):
191 @_contextlib.contextmanager
192 def __call__(self
, path
, node
):
193 (visitorcls
, nodecls
) = map(type, (self
, node
))
194 if nodecls
in visitorcls
:
195 handler
= visitorcls
[nodecls
]
196 with
handler(path
=path
, node
=node
) as ctx
:
203 def __init__(self
, nodecls
):
204 if not isinstance(nodecls
, type):
205 raise ValueError(nodecls
)
206 self
.__nodecls
= nodecls
207 return super().__init
__()
209 def __call__(self
, method
):
210 if not callable(method
):
211 raise ValueError(method
)
212 return VisitorMethod(nodecls
=self
.__nodecls
, method
=method
)
215 def walk(root
, match
=lambda _
: True):
216 pairs
= _collections
.deque([root
])
218 (path
, node
) = pairs
.popleft()
219 pairs
.extend(node
.walk(match
=match
))
223 def visit(visitor
, node
, path
="/", match
=lambda _
: True):
224 with
visitor(path
=path
, node
=node
):
225 if isinstance(node
, Node
):
226 for (subpath
, subnode
) in node
.walk(match
=match
):
227 visit(visitor
=visitor
, path
=subpath
, node
=subnode
)
230 @_functools.total_ordering
231 class Style(_enum
.Enum
):
232 LEGACY
= _enum
.auto()
234 NORMAL
= _enum
.auto()
235 VERBOSE
= _enum
.auto()
237 def __lt__(self
, other
):
238 if not isinstance(other
, self
.__class
__):
239 return NotImplemented
240 return (self
.value
< other
.value
)
243 @_functools.total_ordering
244 class Priority(_enum
.Enum
):
250 def _missing_(cls
, value
):
251 if isinstance(value
, str):
252 value
= value
.upper()
256 return super()._missing
_(value
)
258 def __lt__(self
, other
):
259 if not isinstance(other
, self
.__class
__):
260 return NotImplemented
262 # NOTE: the order is inversed, LOW < NORMAL < HIGH
263 return (self
.value
> other
.value
)
266 def dataclass(cls
, record
, keymap
=None, typemap
=None):
270 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
272 def transform(key_value
):
273 (key
, value
) = key_value
274 key
= keymap
.get(key
, key
)
275 hook
= typemap
.get(key
, lambda value
: value
)
276 if hook
is bool and value
in ("", "0"):
282 record
= dict(map(transform
, record
.items()))
283 for key
in frozenset(record
.keys()):
284 if record
[key
] == "":
290 @_functools.total_ordering
291 class Opcode(Dataclass
):
293 def __new__(cls
, value
):
294 if isinstance(value
, str):
295 value
= int(value
, 0)
296 if not isinstance(value
, int):
297 raise ValueError(value
)
299 if value
.bit_length() > 64:
300 raise ValueError(value
)
302 return super().__new
__(cls
, value
)
305 return self
.__repr
__()
308 return f
"{self:0{self.bit_length()}b}"
310 def bit_length(self
):
311 if super().bit_length() > 32:
315 class Value(Integer
):
324 def __lt__(self
, other
):
325 if not isinstance(other
, Opcode
):
326 return NotImplemented
327 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
330 return (self
.value
& self
.mask
)
333 return int(self
).__index
__()
336 def pattern(value
, mask
, bit_length
):
337 for bit
in range(bit_length
):
338 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
340 elif (value
& (1 << (bit_length
- bit
- 1))):
345 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
347 def match(self
, key
):
348 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
351 @_functools.total_ordering
352 class IntegerOpcode(Opcode
):
353 def __init__(self
, value
):
354 if value
.startswith("0b"):
355 mask
= int(("1" * len(value
[2:])), 2)
359 value
= Opcode
.Value(value
)
360 mask
= Opcode
.Mask(mask
)
362 return super().__init
__(value
=value
, mask
=mask
)
365 @_functools.total_ordering
366 class PatternOpcode(Opcode
):
367 def __init__(self
, pattern
):
368 if not isinstance(pattern
, str):
369 raise ValueError(pattern
)
371 (value
, mask
) = (0, 0)
372 for symbol
in pattern
:
373 if symbol
not in {"0", "1", "-"}:
374 raise ValueError(pattern
)
375 value |
= (symbol
== "1")
376 mask |
= (symbol
!= "-")
382 value
= Opcode
.Value(value
)
383 mask
= Opcode
.Mask(mask
)
385 return super().__init
__(value
=value
, mask
=mask
)
388 class PPCRecord(Dataclass
):
389 class FlagsMeta(type):
404 class Flags(Tuple
, datatype
=str, metaclass
=FlagsMeta
):
405 def __new__(cls
, flags
=frozenset()):
406 flags
= frozenset(flags
)
407 diff
= (flags
- frozenset(cls
))
409 raise ValueError(flags
)
410 return super().__new
__(cls
, sorted(flags
))
414 flags
: Flags
= Flags()
416 function
: _Function
= _Function
.NONE
417 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
418 in1
: _In1Sel
= _In1Sel
.NONE
419 in2
: _In2Sel
= _In2Sel
.NONE
420 in3
: _In3Sel
= _In3Sel
.NONE
421 out
: _OutSel
= _OutSel
.NONE
422 cr_in
: _CRInSel
= _CRInSel
.NONE
423 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
424 cr_out
: _CROutSel
= _CROutSel
.NONE
425 cry_in
: _CryIn
= _CryIn
.ZERO
426 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
427 upd
: _LDSTMode
= _LDSTMode
.NONE
428 Rc
: _RCOE
= _RCOE
.NONE
429 form
: _Form
= _Form
.NONE
431 unofficial
: bool = False
435 "internal op": "intop",
439 "ldst len": "ldst_len",
441 "CONDITIONS": "conditions",
444 def __lt__(self
, other
):
445 if not isinstance(other
, self
.__class
__):
446 return NotImplemented
447 lhs
= (self
.opcode
, self
.comment
)
448 rhs
= (other
.opcode
, other
.comment
)
452 def CSV(cls
, record
, opcode_cls
):
453 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
454 typemap
["opcode"] = opcode_cls
456 if record
["CR in"] == "BA_BB":
457 record
["cr_in"] = "BA"
458 record
["cr_in2"] = "BB"
462 for flag
in frozenset(PPCRecord
.Flags
):
463 if bool(record
.pop(flag
, "")):
465 record
["flags"] = PPCRecord
.Flags(flags
)
467 return dataclass(cls
, record
,
468 keymap
=PPCRecord
.__KEYMAP
,
473 return frozenset(self
.comment
.split("=")[-1].split("/"))
476 class PPCMultiRecord(Tuple
, datatype
=PPCRecord
):
477 def __getattr__(self
, attr
):
480 raise AttributeError(attr
)
481 return getattr(self
[0], attr
)
484 class SVP64Record(Dataclass
):
485 class ExtraMap(tuple):
487 @_dataclasses.dataclass(eq
=True, frozen
=True)
489 seltype
: _SelType
= _SelType
.NONE
490 reg
: _Reg
= _Reg
.NONE
493 return f
"{self.seltype.value}:{self.reg.name}"
495 def __new__(cls
, value
="0"):
496 if isinstance(value
, str):
497 def transform(value
):
498 (seltype
, reg
) = value
.split(":")
499 seltype
= _SelType(seltype
)
501 return cls
.Entry(seltype
=seltype
, reg
=reg
)
506 value
= map(transform
, value
.split(";"))
508 return super().__new
__(cls
, value
)
511 return repr(list(self
))
513 def __new__(cls
, value
=tuple()):
517 return super().__new
__(cls
, map(cls
.Extra
, value
))
520 return repr({index
:self
[index
] for index
in range(0, 4)})
523 ptype
: _SVPType
= _SVPType
.NONE
524 etype
: _SVEType
= _SVEType
.NONE
525 msrc
: _SVMaskSrc
= _SVMaskSrc
.NO
# MASK_SRC is active
526 in1
: _In1Sel
= _In1Sel
.NONE
527 in2
: _In2Sel
= _In2Sel
.NONE
528 in3
: _In3Sel
= _In3Sel
.NONE
529 out
: _OutSel
= _OutSel
.NONE
530 out2
: _OutSel
= _OutSel
.NONE
531 cr_in
: _CRInSel
= _CRInSel
.NONE
532 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
533 cr_out
: _CROutSel
= _CROutSel
.NONE
534 extra
: ExtraMap
= ExtraMap()
536 mode
: _SVMode
= _SVMode
.NORMAL
540 "CONDITIONS": "conditions",
549 def CSV(cls
, record
):
550 record
["insn"] = record
["insn"].split("=")[-1]
552 for key
in frozenset({
553 "in1", "in2", "in3", "CR in",
554 "out", "out2", "CR out",
560 if record
["CR in"] == "BA_BB":
561 record
["cr_in"] = "BA"
562 record
["cr_in2"] = "BB"
566 for idx
in range(0, 4):
567 extra
.append(record
.pop(f
"{idx}"))
569 record
["extra"] = cls
.ExtraMap(extra
)
571 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
576 "in1", "in2", "in3", "cr_in", "cr_in2",
577 "out", "out2", "cr_out",
592 for index
in range(0, 4):
593 for entry
in self
.extra
[index
]:
594 extras
[entry
.seltype
][entry
.reg
] = idxmap
[index
]
596 for (seltype
, regs
) in extras
.items():
597 idx
= regs
.get(reg
, _SVExtra
.NONE
)
598 if idx
is not _SVExtra
.NONE
:
599 yield (reg
, seltype
, idx
)
606 # has the word "in", it is a SelType.SRC "out" -> DST
607 # in1/2/3 and CR in are SRC, and must match only against "s:NN"
608 # out/out1 and CR out are DST, and must match only against "d:NN"
609 keytype
= _SelType
.SRC
if ("in" in key
) else _SelType
.DST
610 sel
= sels
[key
] = getattr(self
, key
)
611 reg
= regs
[key
] = _Reg(sel
)
612 seltypes
[key
] = _SelType
.NONE
613 idxs
[key
] = _SVExtra
.NONE
614 for (reg
, seltype
, idx
) in extra(reg
.alias
):
615 if keytype
!= seltype
: # only check SRC-to-SRC and DST-to-DST
617 if idx
!= idxs
[key
] and idxs
[key
] is not _SVExtra
.NONE
:
618 raise ValueError(idx
)
621 seltypes
[key
] = seltype
623 if sels
["cr_in"] is _CRInSel
.BA_BB
:
624 sels
["cr_in"] = _CRIn2Sel
.BA
625 sels
["cr_in2"] = _CRIn2Sel
.BB
626 idxs
["cr_in2"] = idxs
["cr_in"]
627 for key
in ("cr_in", "cr_in2"):
628 regs
[key
] = _Reg(sels
[key
])
629 seltype
[key
] = _SelType
.SRC
636 "seltype": seltypes
[key
],
640 return _types
.MappingProxyType(records
)
642 extra_idx_in1
= property(lambda self
: self
.extras
["in1"]["idx"])
643 extra_idx_in2
= property(lambda self
: self
.extras
["in2"]["idx"])
644 extra_idx_in3
= property(lambda self
: self
.extras
["in3"]["idx"])
645 extra_idx_out
= property(lambda self
: self
.extras
["out"]["idx"])
646 extra_idx_out2
= property(lambda self
: self
.extras
["out2"]["idx"])
647 extra_idx_cr_in
= property(lambda self
: self
.extras
["cr_in"]["idx"])
648 extra_idx_cr_in2
= property(lambda self
: self
.extras
["cr_in2"]["idx"])
649 extra_idx_cr_out
= property(lambda self
: self
.extras
["cr_out"]["idx"])
654 for idx
in range(0, 4):
655 for entry
in self
.extra
[idx
]:
656 if entry
.seltype
is _SelType
.DST
:
657 if extra
is not None:
658 raise ValueError(self
.svp64
)
662 if _RegType(extra
.reg
) not in (_RegType
.CR_3BIT
, _RegType
.CR_5BIT
):
663 raise ValueError(self
.svp64
)
668 def extra_CR_3bit(self
):
669 return (_RegType(self
.extra_CR
.reg
) is _RegType
.CR_3BIT
)
673 def __init__(self
, value
=(0, 32)):
674 if isinstance(value
, str):
675 (start
, end
) = map(int, value
.split(":"))
678 if start
< 0 or end
< 0 or start
>= end
:
679 raise ValueError(value
)
684 return super().__init
__()
687 return (self
.__end
- self
.__start
+ 1)
690 return f
"[{self.__start}:{self.__end}]"
693 yield from range(self
.start
, (self
.end
+ 1))
695 def __reversed__(self
):
696 return tuple(reversed(tuple(self
)))
707 class Section(Dataclass
):
708 class Mode(_enum
.Enum
):
709 INTEGER
= _enum
.auto()
710 PATTERN
= _enum
.auto()
713 def _missing_(cls
, value
):
714 if isinstance(value
, str):
715 return cls
[value
.upper()]
716 return super()._missing
_(value
)
719 def __new__(cls
, value
=None):
720 if isinstance(value
, str):
721 if value
.upper() == "NONE":
724 value
= int(value
, 0)
728 return super().__new
__(cls
, value
)
734 return (bin(self
) if self
else "None")
740 opcode
: IntegerOpcode
= None
741 priority
: Priority
= Priority
.NORMAL
743 def __lt__(self
, other
):
744 if not isinstance(other
, self
.__class
__):
745 return NotImplemented
746 return (self
.priority
< other
.priority
)
749 def CSV(cls
, record
):
750 keymap
= {"path": "csv"}
751 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
752 if record
["opcode"] == "NONE":
753 typemap
["opcode"] = lambda _
: None
755 return dataclass(cls
, record
, typemap
=typemap
, keymap
=keymap
)
758 class Fields(Dict
, datatype
=type("Bits", (Tuple
,), {}, datatype
=int)):
759 def __init__(self
, items
):
760 if isinstance(items
, dict):
761 items
= items
.items()
764 (name
, bitrange
) = item
765 return (name
, tuple(bitrange
.values()))
767 mapping
= dict(map(transform
, items
))
769 return super().__init
__(mapping
)
772 yield from self
.__mapping
.items()
775 class Operands(Dict
, datatype
=object):
787 def __init__(self
, insn
, operands
):
789 "b": {"target_addr": TargetAddrOperandLI
},
790 "ba": {"target_addr": TargetAddrOperandLI
},
791 "bl": {"target_addr": TargetAddrOperandLI
},
792 "bla": {"target_addr": TargetAddrOperandLI
},
793 "bc": {"target_addr": TargetAddrOperandBD
},
794 "bca": {"target_addr": TargetAddrOperandBD
},
795 "bcl": {"target_addr": TargetAddrOperandBD
},
796 "bcla": {"target_addr": TargetAddrOperandBD
},
797 "addpcis": {"D": DOperandDX
},
798 "fishmv": {"D": DOperandDX
},
799 "fmvis": {"D": DOperandDX
},
802 "SVi": NonZeroOperand
,
803 "SVd": NonZeroOperand
,
804 "SVxd": NonZeroOperand
,
805 "SVyd": NonZeroOperand
,
806 "SVzd": NonZeroOperand
,
808 "D": SignedImmediateOperand
,
812 "SIM": SignedOperand
,
813 "SVD": SignedOperand
,
814 "SVDS": SignedOperand
,
815 "RSp": GPRPairOperand
,
816 "RTp": GPRPairOperand
,
817 "FRAp": FPRPairOperand
,
818 "FRBp": FPRPairOperand
,
819 "FRSp": FPRPairOperand
,
820 "FRTp": FPRPairOperand
,
822 custom_immediates
= {
828 for operand
in operands
:
832 (name
, value
) = operand
.split("=")
833 mapping
[name
] = (StaticOperand
, (
835 ("value", int(value
)),
839 if name
.endswith(")"):
840 name
= name
.replace("(", " ").replace(")", "")
841 (imm_name
, _
, name
) = name
.partition(" ")
845 if imm_name
is not None:
846 imm_cls
= custom_immediates
.get(imm_name
, ImmediateOperand
)
848 if insn
in custom_insns
and name
in custom_insns
[insn
]:
849 cls
= custom_insns
[insn
][name
]
850 elif name
in custom_fields
:
851 cls
= custom_fields
[name
]
852 elif name
in _Reg
.__members
__:
854 if reg
in self
.__class
__.__GPR
_PAIRS
:
856 elif reg
in self
.__class
__.__FPR
_PAIRS
:
859 regtype
= _RegType
[name
]
860 if regtype
is _RegType
.GPR
:
862 elif regtype
is _RegType
.FPR
:
864 elif regtype
is _RegType
.CR_3BIT
:
866 elif regtype
is _RegType
.CR_5BIT
:
869 if imm_name
is not None:
870 mapping
[imm_name
] = (imm_cls
, (("name", imm_name
),))
871 mapping
[name
] = (cls
, (("name", name
),))
873 return super().__init
__(mapping
)
876 def walk(clsself
, match
=lambda _
: True):
877 for (key
, (cls
, pairs
)) in clsself
.items():
878 yield ("/".join((key
, "class")), cls
.__name
__)
879 for (subkey
, value
) in pairs
:
882 path
= "/".join((key
, subkey
))
886 for (key
, items
) in self
.items():
887 (cls
, kwargs
) = items
888 yield (cls
, dict(kwargs
))
892 return lambda pair
: isinstance(pair
[0], cls
)
896 return filter(self
.__class
__.filter(StaticOperand
), self
)
900 return filter(self
.__class
__.filter(DynamicOperand
), self
)
903 class Arguments(tuple):
904 def __new__(cls
, record
, arguments
, operands
):
905 operands
= iter(tuple(operands
))
906 arguments
= iter(tuple(arguments
))
911 operand
= next(operands
)
912 except StopIteration:
916 argument
= next(arguments
)
917 except StopIteration:
918 raise ValueError("operands count mismatch")
920 if isinstance(operand
, ImmediateOperand
):
921 argument
= argument
.replace("(", " ").replace(")", "")
922 (imm_argument
, _
, argument
) = argument
.partition(" ")
924 (imm_operand
, operand
) = (operand
, next(operands
))
925 except StopIteration:
926 raise ValueError("operands count mismatch")
927 items
.append((imm_argument
, imm_operand
))
928 items
.append((argument
, operand
))
932 except StopIteration:
935 raise ValueError("operands count mismatch")
937 return super().__new
__(cls
, items
)
940 class PCode(Tuple
, datatype
=str):
944 class MarkdownRecord(Dataclass
):
949 @_functools.total_ordering
950 class Record(Dataclass
):
956 svp64
: SVP64Record
= None
960 if self
.svp64
is not None:
961 return self
.svp64
.extras
963 return _types
.MappingProxyType({})
967 return self
.mdwn
.pcode
969 def __lt__(self
, other
):
970 if not isinstance(other
, Record
):
971 return NotImplemented
972 lhs
= (min(self
.opcodes
), self
.name
)
973 rhs
= (min(other
.opcodes
), other
.name
)
978 return (self
.static_operands
+ self
.dynamic_operands
)
981 def static_operands(self
):
983 operands
.append(POStaticOperand(record
=self
, value
=self
.PO
))
985 operands
.append(XOStaticOperand(
987 value
=ppc
.opcode
.value
,
988 span
=self
.section
.bitsel
,
990 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
991 operands
.append(cls(record
=self
, **kwargs
))
992 return tuple(operands
)
995 def dynamic_operands(self
):
997 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
998 operands
.append(cls(record
=self
, **kwargs
))
999 return tuple(operands
)
1003 def binary(mapping
):
1004 return int("".join(str(int(mapping
[bit
])) \
1005 for bit
in sorted(mapping
)), 2)
1007 def PO_XO(value
, mask
, opcode
, bits
):
1010 for (src
, dst
) in enumerate(reversed(bits
)):
1011 value
[dst
] = ((opcode
.value
& (1 << src
)) != 0)
1012 mask
[dst
] = ((opcode
.mask
& (1 << src
)) != 0)
1013 return (value
, mask
)
1015 def PO(value
, mask
, opcode
, bits
):
1016 return PO_XO(value
=value
, mask
=mask
, opcode
=opcode
, bits
=bits
)
1018 def XO(value
, mask
, opcode
, bits
):
1019 (value
, mask
) = PO_XO(value
=value
, mask
=mask
,
1020 opcode
=opcode
, bits
=bits
)
1021 for (op_cls
, op_kwargs
) in self
.mdwn
.operands
.static
:
1022 operand
= op_cls(record
=self
, **op_kwargs
)
1023 for (src
, dst
) in enumerate(reversed(operand
.span
)):
1024 value
[dst
] = ((operand
.value
& (1 << src
)) != 0)
1026 return (value
, mask
)
1029 value
= {bit
:False for bit
in range(32)}
1030 mask
= {bit
:False for bit
in range(32)}
1031 if self
.section
.opcode
is not None:
1032 (value
, mask
) = PO(value
=value
, mask
=mask
,
1033 opcode
=self
.section
.opcode
, bits
=range(0, 6))
1034 for ppc
in self
.ppc
:
1035 pairs
.append(XO(value
=value
, mask
=mask
,
1036 opcode
=ppc
.opcode
, bits
=self
.section
.bitsel
))
1039 for (value
, mask
) in pairs
:
1040 value
= Opcode
.Value(binary(value
))
1041 mask
= Opcode
.Mask(binary(mask
))
1042 result
.append(Opcode(value
=value
, mask
=mask
))
1044 return tuple(result
)
1048 opcode
= self
.section
.opcode
1050 opcode
= self
.ppc
[0].opcode
1051 if isinstance(opcode
, PatternOpcode
):
1052 value
= int(opcode
.value
)
1053 bits
= opcode
.value
.bit_length()
1054 return int(_SelectableInt(value
=value
, bits
=bits
)[0:6])
1056 return int(opcode
.value
)
1060 return tuple(ppc
.opcode
for ppc
in self
.ppc
)
1062 def match(self
, key
):
1063 for opcode
in self
.opcodes
:
1064 if opcode
.match(key
):
1071 return self
.svp64
.mode
1091 if self
.svp64
is None:
1097 return self
.ppc
.cr_in
1101 return self
.ppc
.cr_in2
1105 return self
.ppc
.cr_out
1107 ptype
= property(lambda self
: self
.svp64
.ptype
)
1108 etype
= property(lambda self
: self
.svp64
.etype
)
1110 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
1111 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
1112 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
1113 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
1114 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
1115 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
1116 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
1117 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
1119 def __contains__(self
, key
):
1120 return self
.mdwn
.operands
.__contains
__(key
)
1122 def __getitem__(self
, key
):
1123 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
1124 return cls(record
=self
, **kwargs
)
1128 if "Rc" not in self
:
1130 return self
["Rc"].value
1134 def __init__(self
, record
, name
):
1135 self
.__record
= record
1139 yield ("record", self
.record
)
1140 yield ("name", self
.__name
)
1143 return f
"{self.__class__.__name__}({self.name})"
1151 return self
.__record
1155 return self
.record
.fields
[self
.name
]
1157 def assemble(self
, insn
):
1158 raise NotImplementedError()
1160 def disassemble(self
, insn
,
1161 style
=Style
.NORMAL
, indent
=""):
1162 raise NotImplementedError()
1165 class DynamicOperand(Operand
):
1166 def assemble(self
, insn
, value
):
1168 if isinstance(value
, str):
1169 value
= int(value
, 0)
1171 raise ValueError("signed operands not allowed")
1174 def disassemble(self
, insn
,
1175 style
=Style
.NORMAL
, indent
=""):
1179 if style
>= Style
.VERBOSE
:
1180 span
= map(str, span
)
1181 yield f
"{indent}{self.name}"
1182 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1183 yield f
"{indent}{indent}{', '.join(span)}"
1185 yield str(int(value
))
1188 class SignedOperand(DynamicOperand
):
1189 def assemble(self
, insn
, value
):
1190 if isinstance(value
, str):
1191 value
= int(value
, 0)
1192 return super().assemble(value
=value
, insn
=insn
)
1194 def assemble(self
, insn
, value
):
1196 if isinstance(value
, str):
1197 value
= int(value
, 0)
1200 def disassemble(self
, insn
,
1201 style
=Style
.NORMAL
, indent
=""):
1203 value
= insn
[span
].to_signed_int()
1204 sign
= "-" if (value
< 0) else ""
1207 if style
>= Style
.VERBOSE
:
1208 span
= map(str, span
)
1209 yield f
"{indent}{self.name}"
1210 yield f
"{indent}{indent}{sign}{value}"
1211 yield f
"{indent}{indent}{', '.join(span)}"
1213 yield f
"{sign}{value}"
1216 class StaticOperand(Operand
):
1217 def __init__(self
, record
, name
, value
):
1218 self
.__value
= value
1219 return super().__init
__(record
=record
, name
=name
)
1222 yield ("value", self
.__value
)
1223 yield from super().__iter
__()
1226 return f
"{self.__class__.__name__}({self.name}, value={self.value})"
1232 def assemble(self
, insn
):
1233 insn
[self
.span
] = self
.value
1235 def disassemble(self
, insn
,
1236 style
=Style
.NORMAL
, indent
=""):
1240 if style
>= Style
.VERBOSE
:
1241 span
= map(str, span
)
1242 yield f
"{indent}{self.name}"
1243 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1244 yield f
"{indent}{indent}{', '.join(span)}"
1246 yield str(int(value
))
1249 class SpanStaticOperand(StaticOperand
):
1250 def __init__(self
, record
, name
, value
, span
):
1251 self
.__span
= tuple(span
)
1252 return super().__init
__(record
=record
, name
=name
, value
=value
)
1255 yield ("span", self
.__span
)
1256 yield from super().__iter
__()
1263 class POStaticOperand(SpanStaticOperand
):
1264 def __init__(self
, record
, value
):
1265 return super().__init
__(record
=record
, name
="PO",
1266 value
=value
, span
=range(0, 6))
1269 for (key
, value
) in super().__iter
__():
1270 if key
not in {"name", "span"}:
1274 class XOStaticOperand(SpanStaticOperand
):
1275 def __init__(self
, record
, value
, span
):
1276 bits
= record
.section
.bitsel
1277 value
= _SelectableInt(value
=value
, bits
=len(bits
))
1278 span
= dict(zip(bits
, range(len(bits
))))
1279 span_rev
= {value
:key
for (key
, value
) in span
.items()}
1281 # This part is tricky: we cannot use record.operands,
1282 # as this code is called by record.static_operands method.
1283 for (cls
, kwargs
) in record
.mdwn
.operands
:
1284 operand
= cls(record
=record
, **kwargs
)
1285 for idx
in operand
.span
:
1286 rev
= span
.pop(idx
, None)
1288 span_rev
.pop(rev
, None)
1290 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1291 span
= tuple(span
.keys())
1293 return super().__init
__(record
=record
, name
="XO",
1294 value
=value
, span
=span
)
1297 for (key
, value
) in super().__iter
__():
1298 if key
not in {"name"}:
1302 class ImmediateOperand(DynamicOperand
):
1306 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1310 class NonZeroOperand(DynamicOperand
):
1311 def assemble(self
, insn
, value
):
1312 if isinstance(value
, str):
1313 value
= int(value
, 0)
1314 if not isinstance(value
, int):
1315 raise ValueError("non-integer operand")
1317 raise ValueError("non-zero operand")
1319 return super().assemble(value
=value
, insn
=insn
)
1321 def disassemble(self
, insn
,
1322 style
=Style
.NORMAL
, indent
=""):
1326 if style
>= Style
.VERBOSE
:
1327 span
= map(str, span
)
1328 yield f
"{indent}{self.name}"
1329 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1330 yield f
"{indent}{indent}{', '.join(span)}"
1332 yield str(int(value
) + 1)
1335 class ExtendableOperand(DynamicOperand
):
1336 def sv_spec_enter(self
, value
, span
):
1337 return (value
, span
)
1339 def sv_spec(self
, insn
):
1343 span
= tuple(map(str, span
))
1345 if isinstance(insn
, SVP64Instruction
):
1346 (origin_value
, origin_span
) = (value
, span
)
1347 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1349 for extra_idx
in self
.extra_idx
:
1350 if self
.record
.etype
is _SVEType
.EXTRA3
:
1351 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1352 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1353 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1355 raise ValueError(self
.record
.etype
)
1358 vector
= bool(spec
[0])
1359 spec_span
= spec
.__class
__
1360 if self
.record
.etype
is _SVEType
.EXTRA3
:
1361 spec_span
= tuple(map(str, spec_span
[1, 2]))
1363 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1364 spec_span
= tuple(map(str, spec_span
[1,]))
1365 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1368 spec_span
= (spec_span
+ ("{0}",))
1370 spec_span
= (("{0}",) + spec_span
)
1372 raise ValueError(self
.record
.etype
)
1374 vector_shift
= (2 + (5 - value
.bits
))
1375 scalar_shift
= value
.bits
1376 spec_shift
= (5 - value
.bits
)
1378 bits
= (len(span
) + len(spec_span
))
1379 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1380 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1382 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1383 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1385 value
= ((spec
<< scalar_shift
) | value
)
1386 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1388 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1389 origin_value
=origin_value
, origin_span
=origin_span
)
1391 return (vector
, value
, span
)
1393 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1394 return (value
, span
)
1397 def extra_idx(self
):
1398 for (key
, record
) in self
.record
.svp64
.extras
.items():
1399 if record
["reg"].alias
is self
.extra_reg
.alias
:
1403 def extra_reg(self
):
1404 return _Reg(self
.name
)
1406 def remap(self
, value
, vector
):
1407 raise NotImplementedError()
1409 def assemble(self
, value
, insn
, prefix
):
1412 if isinstance(value
, str):
1413 value
= value
.lower()
1414 if value
.startswith("%"):
1416 if value
.startswith("*"):
1417 if not isinstance(insn
, SVP64Instruction
):
1418 raise ValueError(value
)
1421 if value
.startswith(prefix
):
1422 if (self
.extra_reg
.or_zero
and (value
== f
"{prefix}0")):
1423 raise ValueError(value
)
1424 value
= value
[len(prefix
):]
1425 value
= int(value
, 0)
1427 if isinstance(insn
, SVP64Instruction
):
1428 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1430 for extra_idx
in self
.extra_idx
:
1431 if self
.record
.etype
is _SVEType
.EXTRA3
:
1432 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1433 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1434 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1436 raise ValueError(self
.record
.etype
)
1438 return super().assemble(value
=value
, insn
=insn
)
1440 def disassemble(self
, insn
,
1441 style
=Style
.NORMAL
, prefix
="", indent
=""):
1442 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1444 if (self
.extra_reg
.or_zero
and (value
== 0)):
1447 if style
>= Style
.VERBOSE
:
1448 mode
= "vector" if vector
else "scalar"
1449 yield f
"{indent}{self.name} ({mode})"
1450 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1451 yield f
"{indent}{indent}{', '.join(span)}"
1452 if isinstance(insn
, SVP64Instruction
):
1453 for extra_idx
in frozenset(self
.extra_idx
):
1454 if self
.record
.etype
is _SVEType
.NONE
:
1455 yield f
"{indent}{indent}extra[none]"
1457 etype
= repr(self
.record
.etype
).lower()
1458 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1460 vector
= "*" if vector
else ""
1461 yield f
"{vector}{prefix}{int(value)}"
1464 class SimpleRegisterOperand(ExtendableOperand
):
1465 def remap(self
, value
, vector
):
1467 extra
= (value
& 0b11)
1468 value
= (value
>> 2)
1470 extra
= (value
>> 5)
1471 value
= (value
& 0b11111)
1473 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1474 # (and shrink to a single bit if ok)
1475 if self
.record
.etype
is _SVEType
.EXTRA2
:
1477 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1478 assert (extra
& 0b01) == 0, \
1479 ("vector field %s cannot fit into EXTRA2" % value
)
1480 extra
= (0b10 |
(extra
>> 1))
1482 # range is r0-r63 in increments of 1
1483 assert (extra
>> 1) == 0, \
1484 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1486 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1488 # EXTRA3 vector bit needs marking
1491 raise ValueError(self
.record
.etype
)
1493 return (value
, extra
)
1496 class GPROperand(SimpleRegisterOperand
):
1497 def assemble(self
, insn
, value
):
1498 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1500 def disassemble(self
, insn
,
1501 style
=Style
.NORMAL
, indent
=""):
1502 prefix
= "" if (style
<= Style
.SHORT
) else "r"
1503 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1504 style
=style
, indent
=indent
)
1507 class GPRPairOperand(GPROperand
):
1511 class FPROperand(SimpleRegisterOperand
):
1512 def assemble(self
, insn
, value
):
1513 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1515 def disassemble(self
, insn
,
1516 style
=Style
.NORMAL
, indent
=""):
1517 prefix
= "" if (style
<= Style
.SHORT
) else "f"
1518 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1519 style
=style
, indent
=indent
)
1522 class FPRPairOperand(FPROperand
):
1526 class ConditionRegisterFieldOperand(ExtendableOperand
):
1527 def pattern(name_pattern
):
1528 (name
, pattern
) = name_pattern
1529 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1538 CR
= r
"(?:CR|cr)([0-9]+)"
1540 BIT
= rf
"({'|'.join(CONDS.keys())})"
1541 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1542 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1543 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1544 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1545 XCR
= fr
"{CR}\.{BIT}"
1546 PATTERNS
= tuple(map(pattern
, (
1551 ("BIT+CR", (LBIT
+ CR
)),
1552 ("CR+BIT", (CR
+ RBIT
)),
1553 ("BIT+CR*N", (LBIT
+ CRN
)),
1554 ("CR*N+BIT", (CRN
+ RBIT
)),
1555 ("BIT+N*CR", (LBIT
+ NCR
)),
1556 ("N*CR+BIT", (NCR
+ RBIT
)),
1559 def remap(self
, value
, vector
, regtype
):
1560 if regtype
is _RegType
.CR_5BIT
:
1561 subvalue
= (value
& 0b11)
1565 extra
= (value
& 0b1111)
1568 extra
= (value
>> 3)
1571 if self
.record
.etype
is _SVEType
.EXTRA2
:
1573 assert (extra
& 0b111) == 0, \
1574 "vector CR cannot fit into EXTRA2"
1575 extra
= (0b10 |
(extra
>> 3))
1577 assert (extra
>> 1) == 0, \
1578 "scalar CR cannot fit into EXTRA2"
1580 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1582 assert (extra
& 0b11) == 0, \
1583 "vector CR cannot fit into EXTRA3"
1584 extra
= (0b100 |
(extra
>> 2))
1586 assert (extra
>> 2) == 0, \
1587 "scalar CR cannot fit into EXTRA3"
1590 if regtype
is _RegType
.CR_5BIT
:
1591 value
= ((value
<< 2) | subvalue
)
1593 return (value
, extra
)
1595 def assemble(self
, insn
, value
):
1596 if isinstance(value
, str):
1599 if value
.startswith("*"):
1600 if not isinstance(insn
, SVP64Instruction
):
1601 raise ValueError(value
)
1605 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1606 match
= pattern
.match(value
)
1607 if match
is not None:
1608 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1609 values
= match
.groups()
1610 match
= dict(zip(keys
, values
))
1611 CR
= int(match
["CR"])
1615 N
= int(match
.get("N", "1"))
1616 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1617 value
= ((CR
* N
) + BIT
)
1624 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1626 def disassemble(self
, insn
,
1627 style
=Style
.NORMAL
, prefix
="", indent
=""):
1628 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1630 if style
>= Style
.VERBOSE
:
1631 mode
= "vector" if vector
else "scalar"
1632 yield f
"{indent}{self.name} ({mode})"
1633 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1634 yield f
"{indent}{indent}{', '.join(span)}"
1635 if isinstance(insn
, SVP64Instruction
):
1636 for extra_idx
in frozenset(self
.extra_idx
):
1637 if self
.record
.etype
is _SVEType
.NONE
:
1638 yield f
"{indent}{indent}extra[none]"
1640 etype
= repr(self
.record
.etype
).lower()
1641 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1643 vector
= "*" if vector
else ""
1644 CR
= int(value
>> 2)
1646 cond
= ("lt", "gt", "eq", "so")[CC
]
1647 if style
>= Style
.NORMAL
:
1649 if isinstance(insn
, SVP64Instruction
):
1650 yield f
"{vector}cr{CR}.{cond}"
1652 yield f
"4*cr{CR}+{cond}"
1656 yield f
"{vector}{prefix}{int(value)}"
1659 class CR3Operand(ConditionRegisterFieldOperand
):
1660 def remap(self
, value
, vector
):
1661 return super().remap(value
=value
, vector
=vector
,
1662 regtype
=_RegType
.CR_3BIT
)
1665 class CR5Operand(ConditionRegisterFieldOperand
):
1666 def remap(self
, value
, vector
):
1667 return super().remap(value
=value
, vector
=vector
,
1668 regtype
=_RegType
.CR_5BIT
)
1670 def sv_spec_enter(self
, value
, span
):
1671 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1672 return (value
, span
)
1674 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1675 value
= _selectconcat(value
, origin_value
[3:5])
1677 return (value
, span
)
1680 class EXTSOperand(SignedOperand
):
1681 field
: str # real name to report
1682 nz
: int = 0 # number of zeros
1683 fmt
: str = "d" # integer formatter
1685 def __init__(self
, record
, name
, field
, nz
=0, fmt
="d"):
1686 self
.__field
= field
1689 return super().__init
__(record
=record
, name
=name
)
1705 return self
.record
.fields
[self
.field
]
1707 def assemble(self
, insn
, value
):
1709 if isinstance(value
, str):
1710 value
= int(value
, 0)
1711 insn
[span
] = (value
>> self
.nz
)
1713 def disassemble(self
, insn
,
1714 style
=Style
.NORMAL
, indent
=""):
1716 value
= insn
[span
].to_signed_int()
1717 sign
= "-" if (value
< 0) else ""
1718 value
= (abs(value
) << self
.nz
)
1720 if style
>= Style
.VERBOSE
:
1721 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1722 zeros
= ("0" * self
.nz
)
1723 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1724 yield f
"{indent * 1}{hint}"
1725 yield f
"{indent * 2}{self.field}"
1726 yield f
"{indent * 3}{sign}{value:{self.fmt}}"
1727 yield f
"{indent * 3}{', '.join(span)}"
1729 yield f
"{sign}{value:{self.fmt}}"
1732 class TargetAddrOperand(EXTSOperand
):
1733 def __init__(self
, record
, name
, field
):
1734 return super().__init
__(record
=record
, name
=name
, field
=field
,
1738 class TargetAddrOperandLI(TargetAddrOperand
):
1739 def __init__(self
, record
, name
):
1740 return super().__init
__(record
=record
, name
=name
, field
="LI")
1743 class TargetAddrOperandBD(TargetAddrOperand
):
1744 def __init__(self
, record
, name
):
1745 return super().__init
__(record
=record
, name
=name
, field
="BD")
1748 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1749 def __init__(self
, record
, name
):
1750 return super().__init
__(record
=record
, name
=name
, field
="DS", nz
=2)
1753 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1754 def __init__(self
, record
, name
):
1755 return super().__init
__(record
=record
, name
=name
, field
="DQ", nz
=4)
1758 class DOperandDX(SignedOperand
):
1761 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1762 operands
= map(cls
, ("d0", "d1", "d2"))
1763 spans
= map(lambda operand
: operand
.span
, operands
)
1764 return sum(spans
, tuple())
1766 def disassemble(self
, insn
,
1767 style
=Style
.NORMAL
, indent
=""):
1769 value
= insn
[span
].to_signed_int()
1770 sign
= "-" if (value
< 0) else ""
1773 if style
>= Style
.VERBOSE
:
1780 for (subname
, subspan
) in mapping
.items():
1781 operand
= DynamicOperand(name
=subname
)
1783 span
= map(str, span
)
1784 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1785 yield f
"{indent}{indent}{indent}{sign}{value}"
1786 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1788 yield f
"{sign}{value}"
1791 class Instruction(_Mapping
):
1793 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1794 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1795 raise ValueError(bits
)
1797 if isinstance(value
, bytes
):
1798 if ((len(value
) * 8) != bits
):
1799 raise ValueError(f
"bit length mismatch")
1800 value
= int.from_bytes(value
, byteorder
=byteorder
)
1802 if isinstance(value
, int):
1803 value
= _SelectableInt(value
=value
, bits
=bits
)
1804 elif isinstance(value
, Instruction
):
1805 value
= value
.storage
1807 if not isinstance(value
, _SelectableInt
):
1808 raise ValueError(value
)
1811 if len(value
) != bits
:
1812 raise ValueError(value
)
1814 value
= _SelectableInt(value
=value
, bits
=bits
)
1816 return cls(storage
=value
)
1819 return hash(int(self
))
1821 def __getitem__(self
, key
):
1822 return self
.storage
.__getitem
__(key
)
1824 def __setitem__(self
, key
, value
):
1825 return self
.storage
.__setitem
__(key
, value
)
1827 def bytes(self
, byteorder
="little"):
1828 nr_bytes
= (len(self
.__class
__) // 8)
1829 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1832 def record(cls
, db
, entry
):
1835 raise KeyError(entry
)
1839 def operands(cls
, record
):
1840 yield from record
.operands
1843 def static_operands(cls
, record
):
1844 return filter(lambda operand
: isinstance(operand
, StaticOperand
),
1845 cls
.operands(record
=record
))
1848 def dynamic_operands(cls
, record
):
1849 return filter(lambda operand
: isinstance(operand
, DynamicOperand
),
1850 cls
.operands(record
=record
))
1852 def spec(self
, record
, prefix
):
1853 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1854 self
.spec_dynamic_operands(record
=record
)))
1856 static_operands
= []
1857 for (name
, value
) in self
.spec_static_operands(record
=record
):
1858 static_operands
.append(f
"{name}={value}")
1861 if dynamic_operands
:
1863 operands
+= ",".join(dynamic_operands
)
1866 operands
+= " ".join(static_operands
)
1868 return f
"{prefix}{record.name}{operands}"
1870 def spec_static_operands(self
, record
):
1871 for operand
in self
.static_operands(record
=record
):
1872 if not isinstance(operand
, (POStaticOperand
, XOStaticOperand
)):
1873 yield (operand
.name
, operand
.value
)
1875 def spec_dynamic_operands(self
, record
, style
=Style
.NORMAL
):
1879 for operand
in self
.dynamic_operands(record
=record
):
1881 value
= " ".join(operand
.disassemble(insn
=self
,
1882 style
=min(style
, Style
.NORMAL
)))
1884 name
= f
"{imm_name}({name})"
1885 value
= f
"{imm_value}({value})"
1887 if isinstance(operand
, ImmediateOperand
):
1895 def assemble(cls
, record
, arguments
=None):
1896 if arguments
is None:
1899 insn
= cls
.integer(value
=0)
1901 for operand
in cls
.static_operands(record
=record
):
1902 operand
.assemble(insn
=insn
)
1904 arguments
= Arguments(record
=record
,
1905 arguments
=arguments
, operands
=cls
.dynamic_operands(record
=record
))
1906 for (value
, operand
) in arguments
:
1907 operand
.assemble(insn
=insn
, value
=value
)
1911 def disassemble(self
, record
,
1913 style
=Style
.NORMAL
):
1914 raise NotImplementedError()
1917 class WordInstruction(Instruction
):
1918 _
: _Field
= range(0, 32)
1919 PO
: _Field
= range(0, 6)
1922 def integer(cls
, value
, byteorder
="little"):
1923 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1928 for idx
in range(32):
1929 bit
= int(self
[idx
])
1931 return "".join(map(str, bits
))
1933 def disassemble(self
, record
,
1935 style
=Style
.NORMAL
):
1936 if style
<= Style
.SHORT
:
1939 blob
= self
.bytes(byteorder
=byteorder
)
1940 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1944 yield f
"{blob}.long 0x{int(self):08x}"
1947 # awful temporary hack: workaround for ld-update
1948 # https://bugs.libre-soc.org/show_bug.cgi?id=1056#c2
1949 # XXX TODO must check that *EXTENDED* RA != extended-RT
1950 if (record
.svp64
is not None and
1951 record
.mode
== _SVMode
.LDST_IMM
and
1952 'u' in record
.name
):
1953 yield f
"{blob}.long 0x{int(self):08x}"
1957 if style
is Style
.LEGACY
:
1959 for operand
in self
.dynamic_operands(record
=record
):
1960 if isinstance(operand
, (GPRPairOperand
, FPRPairOperand
)):
1963 if style
is Style
.LEGACY
and (paired
or record
.ppc
.unofficial
):
1964 yield f
"{blob}.long 0x{int(self):08x}"
1966 operands
= tuple(map(_operator
.itemgetter(1),
1967 self
.spec_dynamic_operands(record
=record
, style
=style
)))
1969 operands
= ",".join(operands
)
1970 yield f
"{blob}{record.name} {operands}"
1972 yield f
"{blob}{record.name}"
1974 if style
>= Style
.VERBOSE
:
1976 binary
= self
.binary
1977 spec
= self
.spec(record
=record
, prefix
="")
1978 yield f
"{indent}spec"
1979 yield f
"{indent}{indent}{spec}"
1980 yield f
"{indent}pcode"
1981 for stmt
in record
.mdwn
.pcode
:
1982 yield f
"{indent}{indent}{stmt}"
1983 yield f
"{indent}binary"
1984 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1985 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1986 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1987 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1988 yield f
"{indent}opcodes"
1989 for opcode
in record
.opcodes
:
1990 yield f
"{indent}{indent}{opcode!r}"
1991 for operand
in self
.operands(record
=record
):
1992 yield from operand
.disassemble(insn
=self
,
1993 style
=style
, indent
=indent
)
1997 class PrefixedInstruction(Instruction
):
1998 class Prefix(WordInstruction
.remap(range(0, 32))):
2001 class Suffix(WordInstruction
.remap(range(32, 64))):
2004 _
: _Field
= range(64)
2010 def integer(cls
, value
, byteorder
="little"):
2011 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
2014 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
2015 def transform(value
):
2016 return WordInstruction
.integer(value
=value
,
2017 byteorder
=byteorder
)[0:32]
2019 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
2020 value
= _selectconcat(prefix
, suffix
)
2022 return super().integer(bits
=64, value
=value
)
2025 class Mode(_Mapping
):
2026 _
: _Field
= range(0, 5)
2027 sel
: _Field
= (0, 1)
2030 class ExtraRM(_Mapping
):
2031 _
: _Field
= range(0, 9)
2034 class Extra2RM(ExtraRM
):
2035 idx0
: _Field
= range(0, 2)
2036 idx1
: _Field
= range(2, 4)
2037 idx2
: _Field
= range(4, 6)
2038 idx3
: _Field
= range(6, 8)
2040 def __getitem__(self
, key
):
2046 _SVExtra
.Idx0
: self
.idx0
,
2047 _SVExtra
.Idx1
: self
.idx1
,
2048 _SVExtra
.Idx2
: self
.idx2
,
2049 _SVExtra
.Idx3
: self
.idx3
,
2052 def __setitem__(self
, key
, value
):
2053 self
[key
].assign(value
)
2056 class Extra3RM(ExtraRM
):
2057 idx0
: _Field
= range(0, 3)
2058 idx1
: _Field
= range(3, 6)
2059 idx2
: _Field
= range(6, 9)
2061 def __getitem__(self
, key
):
2066 _SVExtra
.Idx0
: self
.idx0
,
2067 _SVExtra
.Idx1
: self
.idx1
,
2068 _SVExtra
.Idx2
: self
.idx2
,
2071 def __setitem__(self
, key
, value
):
2072 self
[key
].assign(value
)
2075 class BaseRM(_Mapping
):
2076 _
: _Field
= range(24)
2077 mmode
: _Field
= (0,)
2078 mask
: _Field
= range(1, 4)
2079 elwidth
: _Field
= range(4, 6)
2080 ewsrc
: _Field
= range(6, 8)
2081 subvl
: _Field
= range(8, 10)
2082 mode
: Mode
.remap(range(19, 24))
2083 smask_extra322
: _Field
= (6,7,18,) # LDST_IDX is EXTRA332
2084 smask
: _Field
= range(16, 19) # everything else use this
2085 extra
: ExtraRM
.remap(range(10, 19))
2086 extra2
: Extra2RM
.remap(range(10, 19))
2087 extra3
: Extra3RM
.remap(range(10, 19))
2088 # XXX extra332 = (extra3[0], extra3[1], extra2[3])
2090 def specifiers(self
, record
):
2091 subvl
= int(self
.subvl
)
2099 def disassemble(self
, style
=Style
.NORMAL
):
2100 if style
>= Style
.VERBOSE
:
2102 for (name
, span
) in self
.traverse(path
="RM"):
2103 value
= self
.storage
[span
]
2105 yield f
"{indent}{int(value):0{value.bits}b}"
2106 yield f
"{indent}{', '.join(map(str, span))}"
2109 class FFRc1BaseRM(BaseRM
):
2110 def specifiers(self
, record
, mode
):
2111 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
2112 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
2113 mask
= int(_selectconcat(CR
, inv
))
2114 predicate
= PredicateBaseRM
.predicate(True, mask
)
2115 yield f
"{mode}={predicate}"
2117 yield from super().specifiers(record
=record
)
2120 class FFRc0BaseRM(BaseRM
):
2121 def specifiers(self
, record
, mode
):
2123 inv
= "~" if self
.inv
else ""
2124 yield f
"{mode}={inv}RC1"
2126 yield from super().specifiers(record
=record
)
2129 class SatBaseRM(BaseRM
):
2130 def specifiers(self
, record
):
2136 yield from super().specifiers(record
=record
)
2139 class ZZBaseRM(BaseRM
):
2140 def specifiers(self
, record
):
2144 yield from super().specifiers(record
=record
)
2147 class ZZCombinedBaseRM(BaseRM
):
2148 def specifiers(self
, record
):
2149 if self
.sz
and self
.dz
:
2156 yield from super().specifiers(record
=record
)
2159 class DZBaseRM(BaseRM
):
2160 def specifiers(self
, record
):
2164 yield from super().specifiers(record
=record
)
2167 class SZBaseRM(BaseRM
):
2168 def specifiers(self
, record
):
2172 yield from super().specifiers(record
=record
)
2175 class MRBaseRM(BaseRM
):
2176 def specifiers(self
, record
):
2182 yield from super().specifiers(record
=record
)
2185 class ElsBaseRM(BaseRM
):
2186 def specifiers(self
, record
):
2190 yield from super().specifiers(record
=record
)
2193 class WidthBaseRM(BaseRM
):
2195 def width(FP
, width
):
2204 width
= ("fp" + width
)
2207 def specifiers(self
, record
):
2208 # elwidths: use "w=" if same otherwise dw/sw
2209 # FIXME this should consider FP instructions
2211 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
2212 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2213 if record
.svp64
.mode
is _SVMode
.CROP
:
2217 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2226 yield from super().specifiers(record
=record
)
2229 class PredicateBaseRM(BaseRM
):
2231 def predicate(CR
, mask
):
2234 (False, 0b001): "1<<r3",
2235 (False, 0b010): "r3",
2236 (False, 0b011): "~r3",
2237 (False, 0b100): "r10",
2238 (False, 0b101): "~r10",
2239 (False, 0b110): "r30",
2240 (False, 0b111): "~r30",
2242 (True, 0b000): "lt",
2243 (True, 0b001): "ge",
2244 (True, 0b010): "gt",
2245 (True, 0b011): "le",
2246 (True, 0b100): "eq",
2247 (True, 0b101): "ne",
2248 (True, 0b110): "so",
2249 (True, 0b111): "ns",
2252 def specifiers(self
, record
):
2253 # predication - single and twin
2254 # use "m=" if same otherwise sm/dm
2255 CR
= (int(self
.mmode
) == 1)
2256 mask
= int(self
.mask
)
2257 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
2258 if record
.svp64
.ptype
is _SVPType
.P2
:
2259 # LDST_IDX smask moving to extra322 but not straight away (False)
2260 if False and record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2261 smask
= int(self
.smask_extra332
)
2263 smask
= int(self
.smask
)
2264 sm
= PredicateBaseRM
.predicate(CR
, smask
)
2273 yield from super().specifiers(record
=record
)
2276 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
2280 class SEABaseRM(BaseRM
):
2281 def specifiers(self
, record
):
2285 yield from super().specifiers(record
=record
)
2288 class VLiBaseRM(BaseRM
):
2289 def specifiers(self
, record
):
2293 yield from super().specifiers(record
=record
)
2296 class NormalBaseRM(PredicateWidthBaseRM
):
2299 https://libre-soc.org/openpower/sv/normal/
2304 class NormalSimpleRM(ZZCombinedBaseRM
, NormalBaseRM
):
2305 """normal: simple mode"""
2309 def specifiers(self
, record
):
2310 yield from super().specifiers(record
=record
)
2313 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
2314 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
2318 class NormalFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, NormalBaseRM
):
2319 """normal: Rc=1: ffirst CR sel"""
2322 CR
: BaseRM
.mode
[3, 4]
2324 def specifiers(self
, record
):
2325 yield from super().specifiers(record
=record
, mode
="ff")
2328 class NormalFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
2329 """normal: Rc=0: ffirst z/nonz"""
2334 def specifiers(self
, record
):
2335 yield from super().specifiers(record
=record
, mode
="ff")
2338 class NormalSatRM(SatBaseRM
, ZZCombinedBaseRM
, NormalBaseRM
):
2339 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2345 class NormalRM(NormalBaseRM
):
2346 simple
: NormalSimpleRM
2348 ffrc1
: NormalFFRc1RM
2349 ffrc0
: NormalFFRc0RM
2353 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2355 LD/ST Immediate mode
2356 https://libre-soc.org/openpower/sv/ldst/
2361 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2362 """ld/st immediate: simple mode"""
2363 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2364 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2370 def specifiers(self
, record
):
2376 yield from super().specifiers(record
=record
)
2379 class LDSTFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2380 """ld/st immediate&indexed: Rc=1: ffirst CR sel"""
2383 CR
: BaseRM
.mode
[3, 4]
2385 def specifiers(self
, record
):
2386 yield from super().specifiers(record
=record
, mode
="ff")
2389 class LDSTFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2390 """ld/st immediate&indexed: Rc=0: ffirst z/nonz"""
2395 def specifiers(self
, record
):
2396 yield from super().specifiers(record
=record
, mode
="ff")
2399 class LDSTImmRM(LDSTImmBaseRM
):
2400 simple
: LDSTImmSimpleRM
2405 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2408 https://libre-soc.org/openpower/sv/ldst/
2413 class LDSTIdxSimpleRM(SEABaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2414 """ld/st index: simple mode (includes element-strided and Signed-EA)"""
2415 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2422 def specifiers(self
, record
):
2428 yield from super().specifiers(record
=record
)
2431 class LDSTIdxRM(LDSTIdxBaseRM
):
2432 simple
: LDSTIdxSimpleRM
2438 class CROpBaseRM(BaseRM
):
2441 https://libre-soc.org/openpower/sv/cr_ops/
2446 class CROpSimpleRM(PredicateBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2447 """crop: simple mode"""
2452 def specifiers(self
, record
):
2454 yield "rg" # simple CR Mode reports /rg
2456 yield from super().specifiers(record
=record
)
2459 class CROpMRRM(MRBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2460 """crop: scalar reduce mode (mapreduce)"""
2466 class CROpFF5RM(FFRc0BaseRM
, PredicateBaseRM
, VLiBaseRM
, DZBaseRM
,
2467 SZBaseRM
, CROpBaseRM
):
2468 """crop: ffirst 5-bit mode"""
2475 def specifiers(self
, record
):
2476 yield from super().specifiers(record
=record
, mode
="ff")
2479 # FIXME: almost everything in this class contradicts the specs (it doesn't)
2480 # The modes however are swapped: 5-bit is 3-bit, 3-bit is 5-bit
2481 class CROpFF3RM(FFRc1BaseRM
, PredicateBaseRM
, VLiBaseRM
, ZZBaseRM
, CROpBaseRM
):
2482 """cr_op: ffirst 3-bit mode"""
2488 def specifiers(self
, record
):
2489 yield from super().specifiers(record
=record
, mode
="ff")
2492 class CROpRM(CROpBaseRM
):
2493 simple
: CROpSimpleRM
2499 # ********************
2501 # https://libre-soc.org/openpower/sv/branches/
2502 class BranchBaseRM(BaseRM
):
2512 def specifiers(self
, record
):
2524 raise ValueError(self
.sz
)
2536 # Branch modes lack source mask.
2537 # Therefore a custom code is needed.
2538 CR
= (int(self
.mmode
) == 1)
2539 mask
= int(self
.mask
)
2540 m
= PredicateBaseRM
.predicate(CR
, mask
)
2544 yield from super().specifiers(record
=record
)
2547 class BranchSimpleRM(BranchBaseRM
):
2548 """branch: simple mode"""
2552 class BranchVLSRM(BranchBaseRM
):
2553 """branch: VLSET mode"""
2557 def specifiers(self
, record
):
2563 }[int(self
.VSb
), int(self
.VLi
)]
2565 yield from super().specifiers(record
=record
)
2568 class BranchCTRRM(BranchBaseRM
):
2569 """branch: CTR-test mode"""
2572 def specifiers(self
, record
):
2578 yield from super().specifiers(record
=record
)
2581 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2582 """branch: CTR-test+VLSET mode"""
2586 class BranchRM(BranchBaseRM
):
2587 simple
: BranchSimpleRM
2590 ctrvls
: BranchCTRVLSRM
2601 @_dataclasses.dataclass(eq
=True, frozen
=True)
2606 def match(cls
, desc
, record
):
2607 raise NotImplementedError()
2609 def validate(self
, others
):
2612 def assemble(self
, insn
):
2613 raise NotImplementedError()
2616 @_dataclasses.dataclass(eq
=True, frozen
=True)
2617 class SpecifierWidth(Specifier
):
2621 def match(cls
, desc
, record
, etalon
):
2622 (mode
, _
, value
) = desc
.partition("=")
2624 value
= value
.strip()
2627 width
= _SVP64Width(value
)
2629 return cls(record
=record
, width
=width
)
2632 @_dataclasses.dataclass(eq
=True, frozen
=True)
2633 class SpecifierW(SpecifierWidth
):
2635 def match(cls
, desc
, record
):
2636 return super().match(desc
=desc
, record
=record
, etalon
="w")
2638 def assemble(self
, insn
):
2639 selector
= insn
.select(record
=self
.record
)
2640 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2641 selector
.ewsrc
= self
.width
.value
2642 selector
.elwidth
= self
.width
.value
2645 @_dataclasses.dataclass(eq
=True, frozen
=True)
2646 class SpecifierSW(SpecifierWidth
):
2648 def match(cls
, desc
, record
):
2649 if record
.svp64
.mode
is _SVMode
.CROP
:
2651 return super().match(desc
=desc
, record
=record
, etalon
="sw")
2653 def assemble(self
, insn
):
2654 selector
= insn
.select(record
=self
.record
)
2655 selector
.ewsrc
= self
.width
.value
2658 @_dataclasses.dataclass(eq
=True, frozen
=True)
2659 class SpecifierDW(SpecifierWidth
):
2661 def match(cls
, desc
, record
):
2662 return super().match(desc
=desc
, record
=record
, etalon
="dw")
2664 def assemble(self
, insn
):
2665 selector
= insn
.select(record
=self
.record
)
2666 selector
.elwidth
= self
.width
.value
2669 @_dataclasses.dataclass(eq
=True, frozen
=True)
2670 class SpecifierSubVL(Specifier
):
2674 def match(cls
, desc
, record
):
2676 value
= _SVP64SubVL(desc
)
2680 return cls(record
=record
, value
=value
)
2682 def assemble(self
, insn
):
2683 selector
= insn
.select(record
=self
.record
)
2684 selector
.subvl
= int(self
.value
.value
)
2687 @_dataclasses.dataclass(eq
=True, frozen
=True)
2688 class SpecifierPredicate(Specifier
):
2693 def match(cls
, desc
, record
, mode_match
, pred_match
):
2694 (mode
, _
, pred
) = desc
.partition("=")
2697 if not mode_match(mode
):
2700 pred
= _SVP64Pred(pred
.strip())
2701 if not pred_match(pred
):
2702 raise ValueError(pred
)
2704 return cls(record
=record
, mode
=mode
, pred
=pred
)
2707 @_dataclasses.dataclass(eq
=True, frozen
=True)
2708 class SpecifierFF(SpecifierPredicate
):
2710 def match(cls
, desc
, record
):
2711 return super().match(desc
=desc
, record
=record
,
2712 mode_match
=lambda mode_arg
: mode_arg
== "ff",
2713 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2718 def assemble(self
, insn
):
2719 selector
= insn
.select(record
=self
.record
)
2720 if selector
.mode
.sel
!= 0:
2721 raise ValueError("cannot override mode")
2722 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2723 selector
.mode
.sel
= 0b01
2724 # HACK: please finally provide correct logic for CRs.
2725 if self
.pred
in (_SVP64Pred
.RC1
, _SVP64Pred
.RC1_N
):
2726 selector
.mode
[2] = (self
.pred
is _SVP64Pred
.RC1_N
)
2728 selector
.mode
[2] = self
.pred
.inv
2729 selector
.mode
[3, 4] = self
.pred
.state
2731 selector
.mode
.sel
= 0b01 if self
.mode
== "ff" else 0b11
2732 selector
.inv
= self
.pred
.inv
2734 selector
.CR
= self
.pred
.state
2736 selector
.RC1
= self
.pred
.state
2739 @_dataclasses.dataclass(eq
=True, frozen
=True)
2740 class SpecifierMask(SpecifierPredicate
):
2742 def match(cls
, desc
, record
, mode
):
2743 return super().match(desc
=desc
, record
=record
,
2744 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2745 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2750 def assemble(self
, insn
):
2751 raise NotImplementedError()
2754 @_dataclasses.dataclass(eq
=True, frozen
=True)
2755 class SpecifierM(SpecifierMask
):
2757 def match(cls
, desc
, record
):
2758 return super().match(desc
=desc
, record
=record
, mode
="m")
2760 def validate(self
, others
):
2762 if isinstance(spec
, SpecifierSM
):
2763 raise ValueError("source-mask and predicate mask conflict")
2764 elif isinstance(spec
, SpecifierDM
):
2765 raise ValueError("dest-mask and predicate mask conflict")
2767 def assemble(self
, insn
):
2768 selector
= insn
.select(record
=self
.record
)
2769 selector
.mask
= int(self
.pred
)
2770 if ((self
.record
.ptype
is _SVPType
.P2
) and
2771 (self
.record
.svp64
.mode
is not _SVMode
.BRANCH
)):
2772 selector
.smask
= int(self
.pred
)
2773 # LDST_IDX smask moving to extra322 but not straight away (False)
2774 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2775 selector
.smask_extra332
= int(self
.pred
)
2777 selector
.smask
= int(self
.pred
)
2779 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2782 @_dataclasses.dataclass(eq
=True, frozen
=True)
2783 class SpecifierSM(SpecifierMask
):
2785 def match(cls
, desc
, record
):
2786 return super().match(desc
=desc
, record
=record
, mode
="sm")
2788 def validate(self
, others
):
2789 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2790 raise ValueError("source-mask on non-twin predicate")
2792 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2795 if isinstance(spec
, SpecifierDM
):
2799 raise ValueError("missing dest-mask in CR twin predication")
2800 if self
.pred
.mode
!= twin
.pred
.mode
:
2801 raise ValueError(f
"predicate masks mismatch: "
2802 f
"{self.pred!r} vs {twin.pred!r}")
2804 def assemble(self
, insn
):
2805 selector
= insn
.select(record
=self
.record
)
2806 # LDST_IDX smask moving to extra322 but not straight away (False)
2807 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2808 selector
.smask_extra332
= int(self
.pred
)
2810 selector
.smask
= int(self
.pred
)
2811 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2814 @_dataclasses.dataclass(eq
=True, frozen
=True)
2815 class SpecifierDM(SpecifierMask
):
2817 def match(cls
, desc
, record
):
2818 return super().match(desc
=desc
, record
=record
, mode
="dm")
2820 def validate(self
, others
):
2821 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2822 raise ValueError("dest-mask on non-twin predicate")
2824 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2827 if isinstance(spec
, SpecifierSM
):
2831 raise ValueError("missing source-mask in CR twin predication")
2832 if self
.pred
.mode
!= twin
.pred
.mode
:
2833 raise ValueError(f
"predicate masks mismatch: "
2834 f
"{self.pred!r} vs {twin.pred!r}")
2836 def assemble(self
, insn
):
2837 selector
= insn
.select(record
=self
.record
)
2838 selector
.mask
= int(self
.pred
)
2839 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2842 @_dataclasses.dataclass(eq
=True, frozen
=True)
2843 class SpecifierZZ(Specifier
):
2845 def match(cls
, desc
, record
):
2849 return cls(record
=record
)
2851 def validate(self
, others
):
2853 # Since zz takes precedence (overrides) sz and dz,
2854 # treat them as mutually exclusive.
2855 if isinstance(spec
, (SpecifierSZ
, SpecifierDZ
)):
2856 raise ValueError("mutually exclusive predicate masks")
2858 def assemble(self
, insn
):
2859 selector
= insn
.select(record
=self
.record
)
2860 if hasattr(selector
, "zz"): # this should be done in a different way
2867 @_dataclasses.dataclass(eq
=True, frozen
=True)
2868 class SpecifierXZ(Specifier
):
2870 hint
: str = _dataclasses
.field(repr=False)
2873 def match(cls
, desc
, record
, etalon
, hint
):
2877 return cls(desc
=desc
, record
=record
, hint
=hint
)
2879 def validate(self
, others
):
2880 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2881 raise ValueError(f
"{self.hint} on non-twin predicate")
2883 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2886 if isinstance(spec
, SpecifierXZ
):
2890 raise ValueError(f
"missing {self.hint} in CR twin predication")
2891 if self
.pred
!= twin
.pred
:
2892 raise ValueError(f
"predicate masks mismatch: "
2893 f
"{self.pred!r} vs {twin.pred!r}")
2895 def assemble(self
, insn
):
2896 selector
= insn
.select(record
=self
.record
)
2897 setattr(selector
, self
.desc
, 1)
2900 @_dataclasses.dataclass(eq
=True, frozen
=True)
2901 class SpecifierSZ(SpecifierXZ
):
2903 def match(cls
, desc
, record
):
2904 return super().match(desc
=desc
, record
=record
,
2905 etalon
="sz", hint
="source-mask")
2907 def validate(self
, others
):
2909 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2910 if isinstance(spec
, SpecifierFF
):
2911 raise ValueError("source-zero not allowed in ff mode")
2914 @_dataclasses.dataclass(eq
=True, frozen
=True)
2915 class SpecifierDZ(SpecifierXZ
):
2917 def match(cls
, desc
, record
):
2918 return super().match(desc
=desc
, record
=record
,
2919 etalon
="dz", hint
="dest-mask")
2921 def validate(self
, others
):
2923 if ((self
.record
.svp64
.mode
is not _SVMode
.CROP
) and
2924 isinstance(spec
, SpecifierFF
) and
2925 (spec
.pred
.mode
is _SVP64PredMode
.RC1
)):
2926 raise ValueError(f
"dest-zero not allowed in ff mode BO")
2929 @_dataclasses.dataclass(eq
=True, frozen
=True)
2930 class SpecifierEls(Specifier
):
2932 def match(cls
, desc
, record
):
2936 if record
.svp64
.mode
not in (_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
):
2937 raise ValueError("els is only valid in ld/st modes, not "
2938 "%s" % str(self
.record
.svp64
.mode
))
2940 return cls(record
=record
)
2942 def assemble(self
, insn
):
2943 if self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
: # stride mode
2944 insn
.prefix
.rm
.mode
[1] = 0
2946 selector
= insn
.select(record
=self
.record
)
2951 @_dataclasses.dataclass(eq
=True, frozen
=True)
2952 class SpecifierSEA(Specifier
):
2954 def match(cls
, desc
, record
):
2958 return cls(record
=record
)
2960 def validate(self
, others
):
2961 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
:
2962 raise ValueError("sea is only valid in ld/st modes, not "
2963 "%s" % str(self
.record
.svp64
.mode
))
2966 if isinstance(spec
, SpecifierFF
):
2967 raise ValueError(f
"sea cannot be used in ff mode")
2969 def assemble(self
, insn
):
2970 selector
= insn
.select(record
=self
.record
)
2971 if selector
.mode
.sel
not in (0b10, 0b00):
2972 raise ValueError("sea is only valid for normal and els modes, "
2973 "not %d" % int(selector
.mode
.sel
))
2977 @_dataclasses.dataclass(eq
=True, frozen
=True)
2978 class SpecifierSat(Specifier
):
2983 def match(cls
, desc
, record
, etalon
, sign
):
2987 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.LDST_IMM
,
2989 raise ValueError("only normal, ld/st imm and "
2990 "ld/st idx modes supported")
2992 return cls(record
=record
, desc
=desc
, sign
=sign
)
2994 def assemble(self
, insn
):
2995 selector
= insn
.select(record
=self
.record
)
2996 selector
.mode
[0] = 0b1
2997 selector
.mode
[1] = 0b0
2998 selector
.N
= int(self
.sign
)
3001 @_dataclasses.dataclass(eq
=True, frozen
=True)
3002 class SpecifierSatS(SpecifierSat
):
3004 def match(cls
, desc
, record
):
3005 return super().match(desc
=desc
, record
=record
,
3006 etalon
="sats", sign
=True)
3009 @_dataclasses.dataclass(eq
=True, frozen
=True)
3010 class SpecifierSatU(SpecifierSat
):
3012 def match(cls
, desc
, record
):
3013 return super().match(desc
=desc
, record
=record
,
3014 etalon
="satu", sign
=False)
3017 @_dataclasses.dataclass(eq
=True, frozen
=True)
3018 class SpecifierMapReduce(Specifier
):
3022 def match(cls
, record
, RG
):
3023 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
3024 raise ValueError("only normal and crop modes supported")
3026 return cls(record
=record
, RG
=RG
)
3028 def assemble(self
, insn
):
3029 selector
= insn
.select(record
=self
.record
)
3030 if self
.record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
3031 raise ValueError("only normal and crop modes supported")
3032 selector
.mode
[0] = 0
3033 selector
.mode
[1] = 0
3034 selector
.mode
[2] = 1
3035 selector
.RG
= self
.RG
3038 @_dataclasses.dataclass(eq
=True, frozen
=True)
3039 class SpecifierMR(SpecifierMapReduce
):
3041 def match(cls
, desc
, record
):
3045 return super().match(record
=record
, RG
=False)
3048 @_dataclasses.dataclass(eq
=True, frozen
=True)
3049 class SpecifierMRR(SpecifierMapReduce
):
3051 def match(cls
, desc
, record
):
3055 return super().match(record
=record
, RG
=True)
3058 @_dataclasses.dataclass(eq
=True, frozen
=True)
3059 class SpecifierBranch(Specifier
):
3061 def match(cls
, desc
, record
, etalon
):
3065 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3066 raise ValueError("only branch modes supported")
3068 return cls(record
=record
)
3071 @_dataclasses.dataclass(eq
=True, frozen
=True)
3072 class SpecifierAll(SpecifierBranch
):
3074 def match(cls
, desc
, record
):
3075 return super().match(desc
=desc
, record
=record
, etalon
="all")
3077 def assemble(self
, insn
):
3078 selector
= insn
.select(record
=self
.record
)
3082 @_dataclasses.dataclass(eq
=True, frozen
=True)
3083 class SpecifierSNZ(Specifier
):
3085 def match(cls
, desc
, record
):
3089 if record
.svp64
.mode
not in (_SVMode
.BRANCH
, _SVMode
.CROP
):
3090 raise ValueError("only branch and crop modes supported")
3092 return cls(record
=record
)
3094 def assemble(self
, insn
):
3095 selector
= insn
.select(record
=self
.record
)
3096 if self
.record
.svp64
.mode
in (_SVMode
.CROP
, _SVMode
.BRANCH
):
3098 if self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3101 raise ValueError("only branch and crop modes supported")
3104 @_dataclasses.dataclass(eq
=True, frozen
=True)
3105 class SpecifierSL(SpecifierBranch
):
3107 def match(cls
, desc
, record
):
3108 return super().match(desc
=desc
, record
=record
, etalon
="sl")
3110 def assemble(self
, insn
):
3111 selector
= insn
.select(record
=self
.record
)
3115 @_dataclasses.dataclass(eq
=True, frozen
=True)
3116 class SpecifierSLu(SpecifierBranch
):
3118 def match(cls
, desc
, record
):
3119 return super().match(desc
=desc
, record
=record
, etalon
="slu")
3121 def assemble(self
, insn
):
3122 selector
= insn
.select(record
=self
.record
)
3126 @_dataclasses.dataclass(eq
=True, frozen
=True)
3127 class SpecifierLRu(SpecifierBranch
):
3129 def match(cls
, desc
, record
):
3130 return super().match(desc
=desc
, record
=record
, etalon
="lru")
3132 def assemble(self
, insn
):
3133 selector
= insn
.select(record
=self
.record
)
3137 @_dataclasses.dataclass(eq
=True, frozen
=True)
3138 class SpecifierVSXX(SpecifierBranch
):
3143 def match(cls
, desc
, record
, etalon
, VSb
, VLi
):
3147 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3148 raise ValueError("only branch modes supported")
3150 return cls(record
=record
, VSb
=VSb
, VLi
=VLi
)
3152 def assemble(self
, insn
):
3153 selector
= insn
.select(record
=self
.record
)
3155 selector
.VSb
= int(self
.VSb
)
3156 selector
.VLi
= int(self
.VLi
)
3159 @_dataclasses.dataclass(eq
=True, frozen
=True)
3160 class SpecifierVS(SpecifierVSXX
):
3162 def match(cls
, desc
, record
):
3163 return super().match(desc
=desc
, record
=record
,
3164 etalon
="vs", VSb
=False, VLi
=False)
3167 @_dataclasses.dataclass(eq
=True, frozen
=True)
3168 class SpecifierVSi(SpecifierVSXX
):
3170 def match(cls
, desc
, record
):
3171 return super().match(desc
=desc
, record
=record
,
3172 etalon
="vsi", VSb
=False, VLi
=True)
3175 @_dataclasses.dataclass(eq
=True, frozen
=True)
3176 class SpecifierVSb(SpecifierVSXX
):
3178 def match(cls
, desc
, record
):
3179 return super().match(desc
=desc
, record
=record
,
3180 etalon
="vsb", VSb
=True, VLi
=False)
3183 @_dataclasses.dataclass(eq
=True, frozen
=True)
3184 class SpecifierVSbi(SpecifierVSXX
):
3186 def match(cls
, desc
, record
):
3187 return super().match(desc
=desc
, record
=record
,
3188 etalon
="vsbi", VSb
=True, VLi
=True)
3191 @_dataclasses.dataclass(eq
=True, frozen
=True)
3192 class SpecifierCTX(Specifier
):
3196 def match(cls
, desc
, record
, etalon
, CTi
):
3200 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3201 raise ValueError("only branch modes supported")
3203 return cls(record
=record
, CTi
=CTi
)
3205 def assemble(self
, insn
):
3206 selector
= insn
.select(record
=self
.record
)
3208 selector
.CTi
= int(self
.CTi
)
3211 @_dataclasses.dataclass(eq
=True, frozen
=True)
3212 class SpecifierCTR(SpecifierCTX
):
3214 def match(cls
, desc
, record
):
3215 return super().match(desc
=desc
, record
=record
,
3216 etalon
="ctr", CTi
=False)
3219 @_dataclasses.dataclass(eq
=True, frozen
=True)
3220 class SpecifierCTi(SpecifierCTX
):
3222 def match(cls
, desc
, record
):
3223 return super().match(desc
=desc
, record
=record
,
3224 etalon
="cti", CTi
=True)
3227 @_dataclasses.dataclass(eq
=True, frozen
=True)
3228 class SpecifierPI(Specifier
):
3230 def match(cls
, desc
, record
):
3234 if record
.svp64
.mode
not in [_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
]:
3235 raise ValueError("only ld/st imm/idx mode supported")
3237 return cls(record
=record
)
3239 def assemble(self
, insn
):
3240 selector
= insn
.select(record
=self
.record
)
3241 selector
.mode
[2] = 0b1
3245 @_dataclasses.dataclass(eq
=True, frozen
=True)
3246 class SpecifierLF(Specifier
):
3248 def match(cls
, desc
, record
):
3252 if record
.svp64
.mode
is not _SVMode
.LDST_IMM
:
3253 raise ValueError("only ld/st imm mode supported")
3255 return cls(record
=record
)
3257 def assemble(self
, insn
):
3258 selector
= insn
.select(record
=self
.record
)
3259 selector
.mode
[1] = 0
3263 @_dataclasses.dataclass(eq
=True, frozen
=True)
3264 class SpecifierVLi(Specifier
):
3266 def match(cls
, desc
, record
):
3270 return cls(record
=record
)
3272 def validate(self
, others
):
3274 if isinstance(spec
, SpecifierFF
):
3277 raise ValueError("VLi only allowed in failfirst")
3279 def assemble(self
, insn
):
3280 selector
= insn
.select(record
=self
.record
)
3281 selector
.mode
[1] = 1
3285 class Specifiers(tuple):
3320 def __new__(cls
, items
, record
):
3321 def transform(item
):
3322 for spec_cls
in cls
.SPECS
:
3323 spec
= spec_cls
.match(item
, record
=record
)
3324 if spec
is not None:
3326 raise ValueError(item
)
3328 # TODO: remove this hack
3329 items
= dict.fromkeys(items
)
3333 items
= tuple(items
)
3335 specs
= tuple(map(transform
, items
))
3336 for (index
, spec
) in enumerate(specs
):
3337 head
= specs
[:index
]
3338 tail
= specs
[index
+ 1:]
3339 spec
.validate(others
=(head
+ tail
))
3341 return super().__new
__(cls
, specs
)
3344 class SVP64OperandMeta(type):
3345 class SVP64NonZeroOperand(NonZeroOperand
):
3346 def assemble(self
, insn
, value
):
3347 if isinstance(value
, str):
3348 value
= int(value
, 0)
3349 if not isinstance(value
, int):
3350 raise ValueError("non-integer operand")
3352 # FIXME: this is really weird
3353 if self
.record
.name
in ("svstep", "svstep."):
3354 value
+= 1 # compensation
3356 return super().assemble(value
=value
, insn
=insn
)
3358 class SVP64XOStaticOperand(SpanStaticOperand
):
3359 def __init__(self
, record
, value
, span
):
3360 return super().__init
__(record
=record
, name
="XO",
3361 value
=value
, span
=span
)
3364 NonZeroOperand
: SVP64NonZeroOperand
,
3365 XOStaticOperand
: SVP64XOStaticOperand
,
3368 def __new__(metacls
, name
, bases
, ns
):
3370 for (index
, base_cls
) in enumerate(bases
):
3371 bases
[index
] = metacls
.__TRANSFORM
.get(base_cls
, base_cls
)
3373 bases
= tuple(bases
)
3375 return super().__new
__(metacls
, name
, bases
, ns
)
3378 class SVP64Operand(Operand
, metaclass
=SVP64OperandMeta
):
3381 return tuple(map(lambda bit
: (bit
+ 32), super().span
))
3385 def __init__(self
, insn
, record
):
3387 self
.__record
= record
3388 return super().__init
__()
3391 return self
.rm
.__doc
__
3394 return repr(self
.rm
)
3402 return self
.__record
3406 rm
= getattr(self
.insn
.prefix
.rm
, self
.record
.svp64
.mode
.name
.lower())
3408 # The idea behind these tables is that they are now literally
3409 # in identical format to insndb.csv and minor_xx.csv and can
3410 # be done precisely as that. The only thing to watch out for
3411 # is the insertion of Rc=1 as a "mask/value" bit and likewise
3412 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
3415 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
3416 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3417 # mode Rc mask Rc member
3419 (0b000000, 0b111000, "simple"), # simple (no Rc)
3420 (0b001000, 0b111100, "mr"), # mapreduce (no Rc)
3421 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3422 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3423 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3424 (0b001100, 0b111100, "rsvd"), # reserved
3426 mode
= int(self
.insn
.prefix
.rm
.normal
.mode
)
3427 search
= ((mode
<< 1) | self
.record
.Rc
)
3429 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
3430 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3431 # mode Rc mask Rc member
3432 # ironically/coincidentally this table is identical to NORMAL
3433 # mode except reserved in place of mr
3435 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3436 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3437 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3439 search
= ((int(self
.insn
.prefix
.rm
.ldst_imm
.mode
) << 1) |
3442 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
3443 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3444 # mode Rc mask Rc member
3446 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3447 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3448 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3450 search
= ((int(self
.insn
.prefix
.rm
.ldst_idx
.mode
) << 1) |
3453 elif self
.record
.svp64
.mode
is _SVMode
.CROP
:
3454 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
3455 # mode 3b mask 3b member
3457 (0b000000, 0b111000, "simple"), # simple
3458 (0b001000, 0b111000, "mr"), # mapreduce
3459 (0b010001, 0b010001, "ff3"), # ffirst, 3-bit CR
3460 (0b010000, 0b010000, "ff5"), # ffirst, 5-bit CR
3462 search
= ((int(self
.insn
.prefix
.rm
.crop
.mode
) << 1) |
3463 int(self
.record
.svp64
.extra_CR_3bit
))
3465 elif self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3469 (0b00, 0b11, "simple"), # simple
3470 (0b01, 0b11, "vls"), # VLset
3471 (0b10, 0b11, "ctr"), # CTR mode
3472 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
3474 # slightly weird: doesn't have a 5-bit "mode" field like others
3475 search
= int(self
.insn
.prefix
.rm
.branch
.mode
.sel
)
3478 if table
is not None:
3479 for (value
, mask
, field
) in table
:
3480 if field
.startswith("rsvd"):
3482 if ((value
& mask
) == (search
& mask
)):
3483 return getattr(rm
, field
)
3487 def __getattr__(self
, key
):
3488 if key
.startswith(f
"_{self.__class__.__name__}__"):
3489 return super().__getattribute
__(key
)
3491 return getattr(self
.rm
, key
)
3493 def __setattr__(self
, key
, value
):
3494 if key
.startswith(f
"_{self.__class__.__name__}__"):
3495 return super().__setattr
__(key
, value
)
3498 if not hasattr(rm
, key
):
3499 raise AttributeError(key
)
3501 return setattr(rm
, key
, value
)
3504 class SVP64Instruction(PrefixedInstruction
):
3505 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
3506 class Prefix(PrefixedInstruction
.Prefix
):
3508 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
3512 def select(self
, record
):
3513 return RMSelector(insn
=self
, record
=record
)
3518 for idx
in range(64):
3519 bit
= int(self
[idx
])
3521 return "".join(map(str, bits
))
3524 def assemble(cls
, record
, arguments
=None, specifiers
=None):
3525 insn
= super().assemble(record
=record
, arguments
=arguments
)
3527 specifiers
= Specifiers(items
=specifiers
, record
=record
)
3528 for specifier
in specifiers
:
3529 specifier
.assemble(insn
=insn
)
3531 insn
.prefix
.PO
= 0x1
3532 insn
.prefix
.id = 0x3
3536 def disassemble(self
, record
,
3538 style
=Style
.NORMAL
):
3540 if style
<= Style
.SHORT
:
3543 blob
= insn
.bytes(byteorder
=byteorder
)
3544 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
3547 blob_prefix
= blob(self
.prefix
)
3548 blob_suffix
= blob(self
.suffix
)
3550 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3551 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
3554 assert record
.svp64
is not None
3556 name
= f
"sv.{record.name}"
3558 rm
= self
.select(record
=record
)
3560 # convert specifiers to /x/y/z (sorted lexicographically)
3561 specifiers
= sorted(rm
.specifiers(record
=record
))
3562 if specifiers
: # if any add one extra to get the extra "/"
3563 specifiers
= ([""] + specifiers
)
3564 specifiers
= "/".join(specifiers
)
3566 # convert operands to " ,x,y,z"
3567 operands
= tuple(map(_operator
.itemgetter(1),
3568 self
.spec_dynamic_operands(record
=record
, style
=style
)))
3569 operands
= ",".join(operands
)
3570 if len(operands
) > 0: # if any separate with a space
3571 operands
= (" " + operands
)
3573 if style
<= Style
.LEGACY
:
3574 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3575 suffix
= WordInstruction
.integer(value
=int(self
.suffix
))
3576 yield from suffix
.disassemble(record
=record
,
3577 byteorder
=byteorder
, style
=style
)
3579 yield f
"{blob_prefix}{name}{specifiers}{operands}"
3581 yield f
"{blob_suffix}"
3583 if style
>= Style
.VERBOSE
:
3585 binary
= self
.binary
3586 spec
= self
.spec(record
=record
, prefix
="sv.")
3588 yield f
"{indent}spec"
3589 yield f
"{indent}{indent}{spec}"
3590 yield f
"{indent}pcode"
3591 for stmt
in record
.mdwn
.pcode
:
3592 yield f
"{indent}{indent}{stmt}"
3593 yield f
"{indent}binary"
3594 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
3595 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
3596 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
3597 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
3598 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
3599 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
3600 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
3601 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
3602 yield f
"{indent}opcodes"
3603 for opcode
in record
.opcodes
:
3604 yield f
"{indent}{indent}{opcode!r}"
3605 for operand
in self
.operands(record
=record
):
3606 yield from operand
.disassemble(insn
=self
,
3607 style
=style
, indent
=indent
)
3609 yield f
"{indent}{indent}{str(rm)}"
3610 for line
in rm
.disassemble(style
=style
):
3611 yield f
"{indent}{indent}{line}"
3615 def operands(cls
, record
):
3616 for operand
in super().operands(record
=record
):
3617 parent
= operand
.__class
__
3618 name
= f
"SVP64{parent.__name__}"
3619 bases
= (SVP64Operand
, parent
)
3620 child
= type(name
, bases
, {})
3621 yield child(**dict(operand
))
3624 def parse(stream
, factory
):
3626 return ("TODO" not in frozenset(entry
.values()))
3628 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
3629 entries
= _csv
.DictReader(lines
)
3630 entries
= filter(match
, entries
)
3631 return tuple(map(factory
, entries
))
3634 class MarkdownDatabase
:
3637 for (name
, desc
) in _ISA():
3640 (dynamic
, *static
) = desc
.regs
3641 operands
.extend(dynamic
)
3642 operands
.extend(static
)
3643 pcode
= PCode(iterable
=filter(str.strip
, desc
.pcode
))
3644 operands
= Operands(insn
=name
, operands
=operands
)
3645 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
3647 self
.__db
= dict(sorted(db
.items()))
3649 return super().__init
__()
3652 yield from self
.__db
.items()
3654 def __contains__(self
, key
):
3655 return self
.__db
.__contains
__(key
)
3657 def __getitem__(self
, key
):
3658 return self
.__db
.__getitem
__(key
)
3661 class FieldsDatabase
:
3664 df
= _DecodeFields()
3666 for (form
, fields
) in df
.instrs
.items():
3667 if form
in {"DQE", "TX"}:
3671 db
[_Form
[form
]] = Fields(fields
)
3675 return super().__init
__()
3677 def __getitem__(self
, key
):
3678 return self
.__db
.__getitem
__(key
)
3682 def __init__(self
, root
, mdwndb
):
3683 # The code below groups the instructions by name:section.
3684 # There can be multiple names for the same instruction.
3685 # The point is to capture different opcodes for the same instruction.
3687 records
= _collections
.defaultdict(set)
3688 path
= (root
/ "insndb.csv")
3689 with
open(path
, "r", encoding
="UTF-8") as stream
:
3690 for section
in sorted(parse(stream
, Section
.CSV
)):
3691 path
= (root
/ section
.csv
)
3693 section
.Mode
.INTEGER
: IntegerOpcode
,
3694 section
.Mode
.PATTERN
: PatternOpcode
,
3696 factory
= _functools
.partial(
3697 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
3698 with
open(path
, "r", encoding
="UTF-8") as stream
:
3699 for insn
in parse(stream
, factory
):
3700 for name
in insn
.names
:
3701 records
[name
].add(insn
)
3702 sections
[name
] = section
3704 items
= sorted(records
.items())
3706 for (name
, multirecord
) in items
:
3707 records
[name
] = PPCMultiRecord(sorted(multirecord
))
3709 def exact_match(name
):
3710 record
= records
.get(name
)
3716 if not name
.endswith("l"):
3718 alias
= exact_match(name
[:-1])
3721 record
= records
[alias
]
3722 if "lk" not in record
.flags
:
3723 raise ValueError(record
)
3727 if not name
.endswith("a"):
3729 alias
= LK_match(name
[:-1])
3732 record
= records
[alias
]
3733 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
3734 raise ValueError(record
)
3735 if "AA" not in mdwndb
[name
].operands
:
3736 raise ValueError(record
)
3740 if not name
.endswith("."):
3742 alias
= exact_match(name
[:-1])
3745 record
= records
[alias
]
3746 if record
.Rc
is _RCOE
.NONE
:
3747 raise ValueError(record
)
3751 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
3752 for (name
, _
) in mdwndb
:
3753 if name
.startswith("sv."):
3756 for match
in matches
:
3758 if alias
is not None:
3762 section
= sections
[alias
]
3763 record
= records
[alias
]
3764 db
[name
] = (section
, record
)
3766 self
.__db
= dict(sorted(db
.items()))
3768 return super().__init
__()
3770 @_functools.lru_cache(maxsize
=512, typed
=False)
3771 def __getitem__(self
, key
):
3772 return self
.__db
.get(key
, (None, None))
3775 class SVP64Database
:
3776 def __init__(self
, root
, ppcdb
):
3778 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
3779 for (prefix
, _
, names
) in _os
.walk(root
):
3780 prefix
= _pathlib
.Path(prefix
)
3781 for name
in filter(lambda name
: pattern
.match(name
), names
):
3782 path
= (prefix
/ _pathlib
.Path(name
))
3783 with
open(path
, "r", encoding
="UTF-8") as stream
:
3784 db
.update(parse(stream
, SVP64Record
.CSV
))
3785 db
= {record
.name
:record
for record
in db
}
3787 self
.__db
= dict(sorted(db
.items()))
3788 self
.__ppcdb
= ppcdb
3790 return super().__init
__()
3792 def __getitem__(self
, key
):
3793 (_
, record
) = self
.__ppcdb
[key
]
3797 for name
in record
.names
:
3798 record
= self
.__db
.get(name
, None)
3799 if record
is not None:
3805 class Records(Tuple
, datatype
=Record
):
3806 def __new__(cls
, records
):
3807 return super().__new
__(cls
, sorted(records
))
3810 class Database(Node
):
3811 def __init__(self
, root
):
3812 root
= _pathlib
.Path(root
)
3813 mdwndb
= MarkdownDatabase()
3814 fieldsdb
= FieldsDatabase()
3815 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
3816 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
3820 opcodes
= _collections
.defaultdict(
3821 lambda: _collections
.defaultdict(set))
3823 for (name
, mdwn
) in mdwndb
:
3824 if name
.startswith("sv."):
3826 (section
, ppc
) = ppcdb
[name
]
3829 svp64
= svp64db
[name
]
3830 fields
= fieldsdb
[ppc
.form
]
3831 record
= Record(name
=name
,
3832 section
=section
, ppc
=ppc
, svp64
=svp64
,
3833 mdwn
=mdwn
, fields
=fields
)
3835 names
[record
.name
] = record
3836 opcodes
[section
][record
.PO
].add(record
)
3838 self
.__db
= Records(db
)
3839 self
.__names
= dict(sorted(names
.items()))
3840 self
.__opcodes
= dict(sorted(opcodes
.items()))
3842 return super().__init
__()
3845 def walk(clsself
, match
=lambda _
: True):
3846 if isinstance(clsself
, type):
3847 yield ("records", Records
)
3849 if match(clsself
.__db
):
3850 yield ("records", clsself
.__db
)
3853 return repr(self
.__db
)
3856 yield from self
.__db
3858 @_functools.lru_cache(maxsize
=None)
3859 def __contains__(self
, key
):
3860 return self
.__getitem
__(key
) is not None
3862 @_functools.lru_cache(maxsize
=None)
3863 def __getitem__(self
, key
):
3864 if isinstance(key
, SVP64Instruction
):
3867 if isinstance(key
, Instruction
):
3870 sections
= sorted(self
.__opcodes
)
3871 for section
in sections
:
3872 group
= self
.__opcodes
[section
]
3873 for record
in group
[PO
]:
3874 if record
.match(key
=key
):
3879 elif isinstance(key
, str):
3880 return self
.__names
.get(key
)
3882 raise ValueError("instruction or name expected")