1 import collections
as _collections
2 import contextlib
as _contextlib
4 import dataclasses
as _dataclasses
6 import functools
as _functools
8 import operator
as _operator
9 import pathlib
as _pathlib
11 import types
as _types
12 import typing
as _typing
15 from functools
import cached_property
17 from cached_property
import cached_property
19 from openpower
.decoder
.power_enums
import (
20 Function
as _Function
,
27 CRIn2Sel
as _CRIn2Sel
,
28 CROutSel
as _CROutSel
,
30 LDSTMode
as _LDSTMode
,
35 SVMaskSrc
as _SVMaskSrc
,
42 SVP64SubVL
as _SVP64SubVL
,
43 SVP64Pred
as _SVP64Pred
,
44 SVP64PredMode
as _SVP64PredMode
,
45 SVP64Width
as _SVP64Width
,
47 from openpower
.decoder
.selectable_int
import (
48 SelectableInt
as _SelectableInt
,
49 selectconcat
as _selectconcat
,
51 from openpower
.decoder
.power_fields
import (
54 DecodeFields
as _DecodeFields
,
56 from openpower
.decoder
.pseudo
.pagereader
import ISA
as _ISA
60 def subnodes(self
, match
=None):
64 class String(Node
, str):
68 class Path(Node
, type(_pathlib
.Path())):
72 @_dataclasses.dataclass(eq
=True, frozen
=True)
74 def subnodes(self
, match
=None):
76 match
= lambda subnode
: True
79 return getattr(self
, field
.name
)
81 yield from filter(match
, map(subnode
, _dataclasses
.fields()))
85 @_contextlib.contextmanager
86 def __call__(self
, node
):
90 def walk(root
, match
=None):
91 nodes
= _collections
.deque([root
])
93 node
= nodes
.popleft()
94 nodes
.extend(node
.subnodes(match
=match
))
98 def visit(visitor
, node
):
99 with
visitor(node
=node
):
100 for subnode
in node
.subnodes():
101 visit(visitor
=visitor
, node
=subnode
)
104 @_functools.total_ordering
105 class Style(_enum
.Enum
):
106 LEGACY
= _enum
.auto()
108 NORMAL
= _enum
.auto()
109 VERBOSE
= _enum
.auto()
111 def __lt__(self
, other
):
112 if not isinstance(other
, self
.__class
__):
113 return NotImplemented
114 return (self
.value
< other
.value
)
117 @_functools.total_ordering
118 class Priority(_enum
.Enum
):
124 def _missing_(cls
, value
):
125 if isinstance(value
, str):
126 value
= value
.upper()
130 return super()._missing
_(value
)
132 def __lt__(self
, other
):
133 if not isinstance(other
, self
.__class
__):
134 return NotImplemented
136 # NOTE: the order is inversed, LOW < NORMAL < HIGH
137 return (self
.value
> other
.value
)
140 def dataclass(cls
, record
, keymap
=None, typemap
=None):
144 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
146 def transform(key_value
):
147 (key
, value
) = key_value
148 key
= keymap
.get(key
, key
)
149 hook
= typemap
.get(key
, lambda value
: value
)
150 if hook
is bool and value
in ("", "0"):
156 record
= dict(map(transform
, record
.items()))
157 for key
in frozenset(record
.keys()):
158 if record
[key
] == "":
164 @_functools.total_ordering
165 @_dataclasses.dataclass(eq
=True, frozen
=True)
168 def __new__(cls
, value
):
169 if isinstance(value
, str):
170 value
= int(value
, 0)
171 if not isinstance(value
, int):
172 raise ValueError(value
)
174 if value
.bit_length() > 64:
175 raise ValueError(value
)
177 return super().__new
__(cls
, value
)
180 return self
.__repr
__()
183 return f
"{self:0{self.bit_length()}b}"
185 def bit_length(self
):
186 if super().bit_length() > 32:
190 class Value(Integer
):
199 def __lt__(self
, other
):
200 if not isinstance(other
, Opcode
):
201 return NotImplemented
202 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
205 return (self
.value
& self
.mask
)
208 return int(self
).__index
__()
211 def pattern(value
, mask
, bit_length
):
212 for bit
in range(bit_length
):
213 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
215 elif (value
& (1 << (bit_length
- bit
- 1))):
220 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
222 def match(self
, key
):
223 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
226 @_functools.total_ordering
227 @_dataclasses.dataclass(eq
=True, frozen
=True)
228 class IntegerOpcode(Opcode
):
229 def __init__(self
, value
):
230 if value
.startswith("0b"):
231 mask
= int(("1" * len(value
[2:])), 2)
235 value
= Opcode
.Value(value
)
236 mask
= Opcode
.Mask(mask
)
238 return super().__init
__(value
=value
, mask
=mask
)
241 @_functools.total_ordering
242 @_dataclasses.dataclass(eq
=True, frozen
=True)
243 class PatternOpcode(Opcode
):
244 def __init__(self
, pattern
):
245 if not isinstance(pattern
, str):
246 raise ValueError(pattern
)
248 (value
, mask
) = (0, 0)
249 for symbol
in pattern
:
250 if symbol
not in {"0", "1", "-"}:
251 raise ValueError(pattern
)
252 value |
= (symbol
== "1")
253 mask |
= (symbol
!= "-")
259 value
= Opcode
.Value(value
)
260 mask
= Opcode
.Mask(mask
)
262 return super().__init
__(value
=value
, mask
=mask
)
265 @_dataclasses.dataclass(eq
=True, frozen
=True)
267 class FlagsMeta(type):
282 class Flags(tuple, metaclass
=FlagsMeta
):
283 def __new__(cls
, flags
=frozenset()):
284 flags
= frozenset(flags
)
285 diff
= (flags
- frozenset(cls
))
287 raise ValueError(flags
)
288 return super().__new
__(cls
, sorted(flags
))
292 flags
: Flags
= Flags()
293 comment2
: String
= String()
294 function
: _Function
= _Function
.NONE
295 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
296 in1
: _In1Sel
= _In1Sel
.NONE
297 in2
: _In2Sel
= _In2Sel
.NONE
298 in3
: _In3Sel
= _In3Sel
.NONE
299 out
: _OutSel
= _OutSel
.NONE
300 cr_in
: _CRInSel
= _CRInSel
.NONE
301 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
302 cr_out
: _CROutSel
= _CROutSel
.NONE
303 cry_in
: _CryIn
= _CryIn
.ZERO
304 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
305 upd
: _LDSTMode
= _LDSTMode
.NONE
306 Rc
: _RCOE
= _RCOE
.NONE
307 form
: _Form
= _Form
.NONE
308 conditions
: String
= String()
309 unofficial
: bool = False
313 "internal op": "intop",
317 "ldst len": "ldst_len",
319 "CONDITIONS": "conditions",
322 def __lt__(self
, other
):
323 if not isinstance(other
, self
.__class
__):
324 return NotImplemented
325 lhs
= (self
.opcode
, self
.comment
)
326 rhs
= (other
.opcode
, other
.comment
)
330 def CSV(cls
, record
, opcode_cls
):
331 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
332 typemap
["opcode"] = opcode_cls
334 if record
["CR in"] == "BA_BB":
335 record
["cr_in"] = "BA"
336 record
["cr_in2"] = "BB"
340 for flag
in frozenset(PPCRecord
.Flags
):
341 if bool(record
.pop(flag
, "")):
343 record
["flags"] = PPCRecord
.Flags(flags
)
345 return dataclass(cls
, record
,
346 keymap
=PPCRecord
.__KEYMAP
,
351 return frozenset(self
.comment
.split("=")[-1].split("/"))
354 class PPCMultiRecord(tuple):
355 def __getattr__(self
, attr
):
358 raise AttributeError(attr
)
359 return getattr(self
[0], attr
)
362 @_dataclasses.dataclass(eq
=True, frozen
=True)
364 class ExtraMap(tuple):
366 @_dataclasses.dataclass(eq
=True, frozen
=True)
368 seltype
: _SelType
= _SelType
.NONE
369 reg
: _Reg
= _Reg
.NONE
372 return f
"{self.seltype.value}:{self.reg.name}"
374 def __new__(cls
, value
="0"):
375 if isinstance(value
, str):
376 def transform(value
):
377 (seltype
, reg
) = value
.split(":")
378 seltype
= _SelType(seltype
)
380 return cls
.Entry(seltype
=seltype
, reg
=reg
)
385 value
= map(transform
, value
.split(";"))
387 return super().__new
__(cls
, value
)
390 return repr(list(self
))
392 def __new__(cls
, value
=tuple()):
396 return super().__new
__(cls
, map(cls
.Extra
, value
))
399 return repr({index
:self
[index
] for index
in range(0, 4)})
402 ptype
: _SVPType
= _SVPType
.NONE
403 etype
: _SVEType
= _SVEType
.NONE
404 msrc
: _SVMaskSrc
= _SVMaskSrc
.NO
# MASK_SRC is active
405 in1
: _In1Sel
= _In1Sel
.NONE
406 in2
: _In2Sel
= _In2Sel
.NONE
407 in3
: _In3Sel
= _In3Sel
.NONE
408 out
: _OutSel
= _OutSel
.NONE
409 out2
: _OutSel
= _OutSel
.NONE
410 cr_in
: _CRInSel
= _CRInSel
.NONE
411 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
412 cr_out
: _CROutSel
= _CROutSel
.NONE
413 extra
: ExtraMap
= ExtraMap()
414 conditions
: String
= String()
415 mode
: _SVMode
= _SVMode
.NORMAL
419 "CONDITIONS": "conditions",
428 def CSV(cls
, record
):
429 record
["insn"] = record
["insn"].split("=")[-1]
431 for key
in frozenset({
432 "in1", "in2", "in3", "CR in",
433 "out", "out2", "CR out",
439 if record
["CR in"] == "BA_BB":
440 record
["cr_in"] = "BA"
441 record
["cr_in2"] = "BB"
445 for idx
in range(0, 4):
446 extra
.append(record
.pop(f
"{idx}"))
448 record
["extra"] = cls
.ExtraMap(extra
)
450 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
455 "in1", "in2", "in3", "cr_in", "cr_in2",
456 "out", "out2", "cr_out",
471 for index
in range(0, 4):
472 for entry
in self
.extra
[index
]:
473 extras
[entry
.seltype
][entry
.reg
] = idxmap
[index
]
475 for (seltype
, regs
) in extras
.items():
476 idx
= regs
.get(reg
, _SVExtra
.NONE
)
477 if idx
is not _SVExtra
.NONE
:
478 yield (reg
, seltype
, idx
)
485 # has the word "in", it is a SelType.SRC "out" -> DST
486 # in1/2/3 and CR in are SRC, and must match only against "s:NN"
487 # out/out1 and CR out are DST, and must match only against "d:NN"
488 keytype
= _SelType
.SRC
if ("in" in key
) else _SelType
.DST
489 sel
= sels
[key
] = getattr(self
, key
)
490 reg
= regs
[key
] = _Reg(sel
)
491 seltypes
[key
] = _SelType
.NONE
492 idxs
[key
] = _SVExtra
.NONE
493 for (reg
, seltype
, idx
) in extra(reg
.alias
):
494 if keytype
!= seltype
: # only check SRC-to-SRC and DST-to-DST
496 if idx
!= idxs
[key
] and idxs
[key
] is not _SVExtra
.NONE
:
497 raise ValueError(idx
)
500 seltypes
[key
] = seltype
502 if sels
["cr_in"] is _CRInSel
.BA_BB
:
503 sels
["cr_in"] = _CRIn2Sel
.BA
504 sels
["cr_in2"] = _CRIn2Sel
.BB
505 idxs
["cr_in2"] = idxs
["cr_in"]
506 for key
in ("cr_in", "cr_in2"):
507 regs
[key
] = _Reg(sels
[key
])
508 seltype
[key
] = _SelType
.SRC
515 "seltype": seltypes
[key
],
519 return _types
.MappingProxyType(records
)
521 extra_idx_in1
= property(lambda self
: self
.extras
["in1"]["idx"])
522 extra_idx_in2
= property(lambda self
: self
.extras
["in2"]["idx"])
523 extra_idx_in3
= property(lambda self
: self
.extras
["in3"]["idx"])
524 extra_idx_out
= property(lambda self
: self
.extras
["out"]["idx"])
525 extra_idx_out2
= property(lambda self
: self
.extras
["out2"]["idx"])
526 extra_idx_cr_in
= property(lambda self
: self
.extras
["cr_in"]["idx"])
527 extra_idx_cr_in2
= property(lambda self
: self
.extras
["cr_in2"]["idx"])
528 extra_idx_cr_out
= property(lambda self
: self
.extras
["cr_out"]["idx"])
533 for idx
in range(0, 4):
534 for entry
in self
.extra
[idx
]:
535 if entry
.seltype
is _SelType
.DST
:
536 if extra
is not None:
537 raise ValueError(self
.svp64
)
541 if _RegType(extra
.reg
) not in (_RegType
.CR_3BIT
, _RegType
.CR_5BIT
):
542 raise ValueError(self
.svp64
)
547 def extra_CR_3bit(self
):
548 return (_RegType(self
.extra_CR
.reg
) is _RegType
.CR_3BIT
)
552 def __init__(self
, value
=(0, 32)):
553 if isinstance(value
, str):
554 (start
, end
) = map(int, value
.split(":"))
557 if start
< 0 or end
< 0 or start
>= end
:
558 raise ValueError(value
)
563 return super().__init
__()
566 return (self
.__end
- self
.__start
+ 1)
569 return f
"[{self.__start}:{self.__end}]"
572 yield from range(self
.start
, (self
.end
+ 1))
574 def __reversed__(self
):
575 return tuple(reversed(tuple(self
)))
586 @_dataclasses.dataclass(eq
=True, frozen
=True)
588 class Mode(_enum
.Enum
):
589 INTEGER
= _enum
.auto()
590 PATTERN
= _enum
.auto()
593 def _missing_(cls
, value
):
594 if isinstance(value
, str):
595 return cls
[value
.upper()]
596 return super()._missing
_(value
)
599 def __new__(cls
, value
=None):
600 if isinstance(value
, str):
601 if value
.upper() == "NONE":
604 value
= int(value
, 0)
608 return super().__new
__(cls
, value
)
614 return (bin(self
) if self
else "None")
620 opcode
: IntegerOpcode
= None
621 priority
: Priority
= Priority
.NORMAL
623 def __lt__(self
, other
):
624 if not isinstance(other
, self
.__class
__):
625 return NotImplemented
626 return (self
.priority
< other
.priority
)
629 def CSV(cls
, record
):
630 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
631 if record
["opcode"] == "NONE":
632 typemap
["opcode"] = lambda _
: None
634 return dataclass(cls
, record
, typemap
=typemap
)
638 def __init__(self
, items
):
639 if isinstance(items
, dict):
640 items
= items
.items()
643 (name
, bitrange
) = item
644 return (name
, tuple(bitrange
.values()))
646 self
.__mapping
= dict(map(transform
, items
))
648 return super().__init
__()
651 return repr(self
.__mapping
)
654 yield from self
.__mapping
.items()
656 def __contains__(self
, key
):
657 return self
.__mapping
.__contains
__(key
)
659 def __getitem__(self
, key
):
660 return self
.__mapping
.get(key
, None)
675 def __init__(self
, insn
, operands
):
677 "b": {"target_addr": TargetAddrOperandLI
},
678 "ba": {"target_addr": TargetAddrOperandLI
},
679 "bl": {"target_addr": TargetAddrOperandLI
},
680 "bla": {"target_addr": TargetAddrOperandLI
},
681 "bc": {"target_addr": TargetAddrOperandBD
},
682 "bca": {"target_addr": TargetAddrOperandBD
},
683 "bcl": {"target_addr": TargetAddrOperandBD
},
684 "bcla": {"target_addr": TargetAddrOperandBD
},
685 "addpcis": {"D": DOperandDX
},
686 "fishmv": {"D": DOperandDX
},
687 "fmvis": {"D": DOperandDX
},
690 "SVi": NonZeroOperand
,
691 "SVd": NonZeroOperand
,
692 "SVxd": NonZeroOperand
,
693 "SVyd": NonZeroOperand
,
694 "SVzd": NonZeroOperand
,
696 "D": SignedImmediateOperand
,
700 "SIM": SignedOperand
,
701 "SVD": SignedOperand
,
702 "SVDS": SignedOperand
,
703 "RSp": GPRPairOperand
,
704 "RTp": GPRPairOperand
,
705 "FRAp": FPRPairOperand
,
706 "FRBp": FPRPairOperand
,
707 "FRSp": FPRPairOperand
,
708 "FRTp": FPRPairOperand
,
710 custom_immediates
= {
716 for operand
in operands
:
720 (name
, value
) = operand
.split("=")
721 mapping
[name
] = (StaticOperand
, {
727 if name
.endswith(")"):
728 name
= name
.replace("(", " ").replace(")", "")
729 (imm_name
, _
, name
) = name
.partition(" ")
733 if imm_name
is not None:
734 imm_cls
= custom_immediates
.get(imm_name
, ImmediateOperand
)
736 if insn
in custom_insns
and name
in custom_insns
[insn
]:
737 cls
= custom_insns
[insn
][name
]
738 elif name
in custom_fields
:
739 cls
= custom_fields
[name
]
740 elif name
in _Reg
.__members
__:
742 if reg
in self
.__class
__.__GPR
_PAIRS
:
744 elif reg
in self
.__class
__.__FPR
_PAIRS
:
747 regtype
= _RegType
[name
]
748 if regtype
is _RegType
.GPR
:
750 elif regtype
is _RegType
.FPR
:
752 elif regtype
is _RegType
.CR_3BIT
:
754 elif regtype
is _RegType
.CR_5BIT
:
757 if imm_name
is not None:
758 mapping
[imm_name
] = (imm_cls
, {"name": imm_name
})
759 mapping
[name
] = (cls
, {"name": name
})
763 for (name
, (cls
, kwargs
)) in mapping
.items():
764 kwargs
= dict(kwargs
)
765 kwargs
["name"] = name
766 if issubclass(cls
, StaticOperand
):
767 static
.append((cls
, kwargs
))
768 elif issubclass(cls
, DynamicOperand
):
769 dynamic
.append((cls
, kwargs
))
771 raise ValueError(name
)
773 self
.__mapping
= mapping
774 self
.__static
= tuple(static
)
775 self
.__dynamic
= tuple(dynamic
)
777 return super().__init
__()
780 for (_
, items
) in self
.__mapping
.items():
781 (cls
, kwargs
) = items
785 return self
.__mapping
.__repr
__()
787 def __contains__(self
, key
):
788 return self
.__mapping
.__contains
__(key
)
790 def __getitem__(self
, key
):
791 return self
.__mapping
.__getitem
__(key
)
799 return self
.__dynamic
802 class Arguments(tuple):
803 def __new__(cls
, record
, arguments
, operands
):
804 operands
= iter(tuple(operands
))
805 arguments
= iter(tuple(arguments
))
810 operand
= next(operands
)
811 except StopIteration:
815 argument
= next(arguments
)
816 except StopIteration:
817 raise ValueError("operands count mismatch")
819 if isinstance(operand
, ImmediateOperand
):
820 argument
= argument
.replace("(", " ").replace(")", "")
821 (imm_argument
, _
, argument
) = argument
.partition(" ")
823 (imm_operand
, operand
) = (operand
, next(operands
))
824 except StopIteration:
825 raise ValueError("operands count mismatch")
826 items
.append((imm_argument
, imm_operand
))
827 items
.append((argument
, operand
))
831 except StopIteration:
834 raise ValueError("operands count mismatch")
836 return super().__new
__(cls
, items
)
840 def __init__(self
, iterable
):
841 self
.__pcode
= tuple(iterable
)
842 return super().__init
__()
845 yield from self
.__pcode
848 return self
.__pcode
.__repr
__()
851 @_dataclasses.dataclass(eq
=True, frozen
=True)
852 class MarkdownRecord
:
857 @_dataclasses.dataclass(eq
=True, frozen
=True)
861 _In1Sel
, _In2Sel
, _In3Sel
, _CRInSel
, _CRIn2Sel
,
869 @_functools.total_ordering
870 @_dataclasses.dataclass(eq
=True, frozen
=True)
877 svp64
: SVP64Record
= None
879 def subnodes(self
, match
=None):
881 for (name
, fields
) in self
.extras
.items():
882 extras
.append(Extra(name
=name
, **fields
))
883 yield from filter(match
, extras
)
887 if self
.svp64
is not None:
888 return self
.svp64
.extras
890 return _types
.MappingProxyType({})
894 return self
.mdwn
.pcode
896 def __lt__(self
, other
):
897 if not isinstance(other
, Record
):
898 return NotImplemented
899 lhs
= (min(self
.opcodes
), self
.name
)
900 rhs
= (min(other
.opcodes
), other
.name
)
905 return (self
.static_operands
+ self
.dynamic_operands
)
908 def static_operands(self
):
910 operands
.append(POStaticOperand(record
=self
, value
=self
.PO
))
912 operands
.append(XOStaticOperand(
914 value
=ppc
.opcode
.value
,
915 span
=self
.section
.bitsel
,
917 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
918 operands
.append(cls(record
=self
, **kwargs
))
919 return tuple(operands
)
922 def dynamic_operands(self
):
924 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
925 operands
.append(cls(record
=self
, **kwargs
))
926 return tuple(operands
)
931 return int("".join(str(int(mapping
[bit
])) \
932 for bit
in sorted(mapping
)), 2)
934 def PO_XO(value
, mask
, opcode
, bits
):
937 for (src
, dst
) in enumerate(reversed(bits
)):
938 value
[dst
] = ((opcode
.value
& (1 << src
)) != 0)
939 mask
[dst
] = ((opcode
.mask
& (1 << src
)) != 0)
942 def PO(value
, mask
, opcode
, bits
):
943 return PO_XO(value
=value
, mask
=mask
, opcode
=opcode
, bits
=bits
)
945 def XO(value
, mask
, opcode
, bits
):
946 (value
, mask
) = PO_XO(value
=value
, mask
=mask
,
947 opcode
=opcode
, bits
=bits
)
948 for (op_cls
, op_kwargs
) in self
.mdwn
.operands
.static
:
949 operand
= op_cls(record
=self
, **op_kwargs
)
950 for (src
, dst
) in enumerate(reversed(operand
.span
)):
951 value
[dst
] = ((operand
.value
& (1 << src
)) != 0)
956 value
= {bit
:False for bit
in range(32)}
957 mask
= {bit
:False for bit
in range(32)}
958 if self
.section
.opcode
is not None:
959 (value
, mask
) = PO(value
=value
, mask
=mask
,
960 opcode
=self
.section
.opcode
, bits
=range(0, 6))
962 pairs
.append(XO(value
=value
, mask
=mask
,
963 opcode
=ppc
.opcode
, bits
=self
.section
.bitsel
))
966 for (value
, mask
) in pairs
:
967 value
= Opcode
.Value(binary(value
))
968 mask
= Opcode
.Mask(binary(mask
))
969 result
.append(Opcode(value
=value
, mask
=mask
))
975 opcode
= self
.section
.opcode
977 opcode
= self
.ppc
[0].opcode
978 if isinstance(opcode
, PatternOpcode
):
979 value
= int(opcode
.value
)
980 bits
= opcode
.value
.bit_length()
981 return int(_SelectableInt(value
=value
, bits
=bits
)[0:6])
983 return int(opcode
.value
)
987 return tuple(ppc
.opcode
for ppc
in self
.ppc
)
989 def match(self
, key
):
990 for opcode
in self
.opcodes
:
991 if opcode
.match(key
):
998 return self
.svp64
.mode
1018 if self
.svp64
is None:
1024 return self
.ppc
.cr_in
1028 return self
.ppc
.cr_in2
1032 return self
.ppc
.cr_out
1034 ptype
= property(lambda self
: self
.svp64
.ptype
)
1035 etype
= property(lambda self
: self
.svp64
.etype
)
1037 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
1038 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
1039 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
1040 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
1041 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
1042 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
1043 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
1044 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
1046 def __contains__(self
, key
):
1047 return self
.mdwn
.operands
.__contains
__(key
)
1049 def __getitem__(self
, key
):
1050 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
1051 return cls(record
=self
, **kwargs
)
1055 if "Rc" not in self
:
1057 return self
["Rc"].value
1061 def __init__(self
, record
, name
):
1062 self
.__record
= record
1066 yield ("record", self
.record
)
1067 yield ("name", self
.__name
)
1070 return f
"{self.__class__.__name__}({self.name})"
1078 return self
.__record
1082 return self
.record
.fields
[self
.name
]
1084 def assemble(self
, insn
):
1085 raise NotImplementedError()
1087 def disassemble(self
, insn
,
1088 style
=Style
.NORMAL
, indent
=""):
1089 raise NotImplementedError()
1092 class DynamicOperand(Operand
):
1093 def assemble(self
, insn
, value
):
1095 if isinstance(value
, str):
1096 value
= int(value
, 0)
1098 raise ValueError("signed operands not allowed")
1101 def disassemble(self
, insn
,
1102 style
=Style
.NORMAL
, indent
=""):
1106 if style
>= Style
.VERBOSE
:
1107 span
= map(str, span
)
1108 yield f
"{indent}{self.name}"
1109 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1110 yield f
"{indent}{indent}{', '.join(span)}"
1112 yield str(int(value
))
1115 class SignedOperand(DynamicOperand
):
1116 def assemble(self
, insn
, value
):
1117 if isinstance(value
, str):
1118 value
= int(value
, 0)
1119 return super().assemble(value
=value
, insn
=insn
)
1121 def assemble(self
, insn
, value
):
1123 if isinstance(value
, str):
1124 value
= int(value
, 0)
1127 def disassemble(self
, insn
,
1128 style
=Style
.NORMAL
, indent
=""):
1130 value
= insn
[span
].to_signed_int()
1131 sign
= "-" if (value
< 0) else ""
1134 if style
>= Style
.VERBOSE
:
1135 span
= map(str, span
)
1136 yield f
"{indent}{self.name}"
1137 yield f
"{indent}{indent}{sign}{value}"
1138 yield f
"{indent}{indent}{', '.join(span)}"
1140 yield f
"{sign}{value}"
1143 class StaticOperand(Operand
):
1144 def __init__(self
, record
, name
, value
):
1145 self
.__value
= value
1146 return super().__init
__(record
=record
, name
=name
)
1149 yield ("value", self
.__value
)
1150 yield from super().__iter
__()
1153 return f
"{self.__class__.__name__}({self.name}, value={self.value})"
1159 def assemble(self
, insn
):
1160 insn
[self
.span
] = self
.value
1162 def disassemble(self
, insn
,
1163 style
=Style
.NORMAL
, indent
=""):
1167 if style
>= Style
.VERBOSE
:
1168 span
= map(str, span
)
1169 yield f
"{indent}{self.name}"
1170 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1171 yield f
"{indent}{indent}{', '.join(span)}"
1173 yield str(int(value
))
1176 class SpanStaticOperand(StaticOperand
):
1177 def __init__(self
, record
, name
, value
, span
):
1178 self
.__span
= tuple(span
)
1179 return super().__init
__(record
=record
, name
=name
, value
=value
)
1182 yield ("span", self
.__span
)
1183 yield from super().__iter
__()
1190 class POStaticOperand(SpanStaticOperand
):
1191 def __init__(self
, record
, value
):
1192 return super().__init
__(record
=record
, name
="PO",
1193 value
=value
, span
=range(0, 6))
1196 for (key
, value
) in super().__iter
__():
1197 if key
not in {"name", "span"}:
1201 class XOStaticOperand(SpanStaticOperand
):
1202 def __init__(self
, record
, value
, span
):
1203 bits
= record
.section
.bitsel
1204 value
= _SelectableInt(value
=value
, bits
=len(bits
))
1205 span
= dict(zip(bits
, range(len(bits
))))
1206 span_rev
= {value
:key
for (key
, value
) in span
.items()}
1208 # This part is tricky: we cannot use record.operands,
1209 # as this code is called by record.static_operands method.
1210 for (cls
, kwargs
) in record
.mdwn
.operands
:
1211 operand
= cls(record
=record
, **kwargs
)
1212 for idx
in operand
.span
:
1213 rev
= span
.pop(idx
, None)
1215 span_rev
.pop(rev
, None)
1217 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1218 span
= tuple(span
.keys())
1220 return super().__init
__(record
=record
, name
="XO",
1221 value
=value
, span
=span
)
1224 for (key
, value
) in super().__iter
__():
1225 if key
not in {"name"}:
1229 class ImmediateOperand(DynamicOperand
):
1233 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1237 class NonZeroOperand(DynamicOperand
):
1238 def assemble(self
, insn
, value
):
1239 if isinstance(value
, str):
1240 value
= int(value
, 0)
1241 if not isinstance(value
, int):
1242 raise ValueError("non-integer operand")
1244 raise ValueError("non-zero operand")
1246 return super().assemble(value
=value
, insn
=insn
)
1248 def disassemble(self
, insn
,
1249 style
=Style
.NORMAL
, indent
=""):
1253 if style
>= Style
.VERBOSE
:
1254 span
= map(str, span
)
1255 yield f
"{indent}{self.name}"
1256 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1257 yield f
"{indent}{indent}{', '.join(span)}"
1259 yield str(int(value
) + 1)
1262 class ExtendableOperand(DynamicOperand
):
1263 def sv_spec_enter(self
, value
, span
):
1264 return (value
, span
)
1266 def sv_spec(self
, insn
):
1270 span
= tuple(map(str, span
))
1272 if isinstance(insn
, SVP64Instruction
):
1273 (origin_value
, origin_span
) = (value
, span
)
1274 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1276 for extra_idx
in self
.extra_idx
:
1277 if self
.record
.etype
is _SVEType
.EXTRA3
:
1278 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1279 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1280 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1282 raise ValueError(self
.record
.etype
)
1285 vector
= bool(spec
[0])
1286 spec_span
= spec
.__class
__
1287 if self
.record
.etype
is _SVEType
.EXTRA3
:
1288 spec_span
= tuple(map(str, spec_span
[1, 2]))
1290 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1291 spec_span
= tuple(map(str, spec_span
[1,]))
1292 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1295 spec_span
= (spec_span
+ ("{0}",))
1297 spec_span
= (("{0}",) + spec_span
)
1299 raise ValueError(self
.record
.etype
)
1301 vector_shift
= (2 + (5 - value
.bits
))
1302 scalar_shift
= value
.bits
1303 spec_shift
= (5 - value
.bits
)
1305 bits
= (len(span
) + len(spec_span
))
1306 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1307 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1309 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1310 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1312 value
= ((spec
<< scalar_shift
) | value
)
1313 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1315 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1316 origin_value
=origin_value
, origin_span
=origin_span
)
1318 return (vector
, value
, span
)
1320 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1321 return (value
, span
)
1324 def extra_idx(self
):
1325 for (key
, record
) in self
.record
.svp64
.extras
.items():
1326 if record
["reg"].alias
is self
.extra_reg
.alias
:
1330 def extra_reg(self
):
1331 return _Reg(self
.name
)
1333 def remap(self
, value
, vector
):
1334 raise NotImplementedError()
1336 def assemble(self
, value
, insn
, prefix
):
1339 if isinstance(value
, str):
1340 value
= value
.lower()
1341 if value
.startswith("%"):
1343 if value
.startswith("*"):
1344 if not isinstance(insn
, SVP64Instruction
):
1345 raise ValueError(value
)
1348 if value
.startswith(prefix
):
1349 if (self
.extra_reg
.or_zero
and (value
== f
"{prefix}0")):
1350 raise ValueError(value
)
1351 value
= value
[len(prefix
):]
1352 value
= int(value
, 0)
1354 if isinstance(insn
, SVP64Instruction
):
1355 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1357 for extra_idx
in self
.extra_idx
:
1358 if self
.record
.etype
is _SVEType
.EXTRA3
:
1359 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1360 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1361 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1363 raise ValueError(self
.record
.etype
)
1365 return super().assemble(value
=value
, insn
=insn
)
1367 def disassemble(self
, insn
,
1368 style
=Style
.NORMAL
, prefix
="", indent
=""):
1369 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1371 if (self
.extra_reg
.or_zero
and (value
== 0)):
1374 if style
>= Style
.VERBOSE
:
1375 mode
= "vector" if vector
else "scalar"
1376 yield f
"{indent}{self.name} ({mode})"
1377 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1378 yield f
"{indent}{indent}{', '.join(span)}"
1379 if isinstance(insn
, SVP64Instruction
):
1380 for extra_idx
in frozenset(self
.extra_idx
):
1381 if self
.record
.etype
is _SVEType
.NONE
:
1382 yield f
"{indent}{indent}extra[none]"
1384 etype
= repr(self
.record
.etype
).lower()
1385 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1387 vector
= "*" if vector
else ""
1388 yield f
"{vector}{prefix}{int(value)}"
1391 class SimpleRegisterOperand(ExtendableOperand
):
1392 def remap(self
, value
, vector
):
1394 extra
= (value
& 0b11)
1395 value
= (value
>> 2)
1397 extra
= (value
>> 5)
1398 value
= (value
& 0b11111)
1400 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1401 # (and shrink to a single bit if ok)
1402 if self
.record
.etype
is _SVEType
.EXTRA2
:
1404 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1405 assert (extra
& 0b01) == 0, \
1406 ("vector field %s cannot fit into EXTRA2" % value
)
1407 extra
= (0b10 |
(extra
>> 1))
1409 # range is r0-r63 in increments of 1
1410 assert (extra
>> 1) == 0, \
1411 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1413 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1415 # EXTRA3 vector bit needs marking
1418 raise ValueError(self
.record
.etype
)
1420 return (value
, extra
)
1423 class GPROperand(SimpleRegisterOperand
):
1424 def assemble(self
, insn
, value
):
1425 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1427 def disassemble(self
, insn
,
1428 style
=Style
.NORMAL
, indent
=""):
1429 prefix
= "" if (style
<= Style
.SHORT
) else "r"
1430 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1431 style
=style
, indent
=indent
)
1434 class GPRPairOperand(GPROperand
):
1438 class FPROperand(SimpleRegisterOperand
):
1439 def assemble(self
, insn
, value
):
1440 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1442 def disassemble(self
, insn
,
1443 style
=Style
.NORMAL
, indent
=""):
1444 prefix
= "" if (style
<= Style
.SHORT
) else "f"
1445 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1446 style
=style
, indent
=indent
)
1449 class FPRPairOperand(FPROperand
):
1453 class ConditionRegisterFieldOperand(ExtendableOperand
):
1454 def pattern(name_pattern
):
1455 (name
, pattern
) = name_pattern
1456 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1465 CR
= r
"(?:CR|cr)([0-9]+)"
1467 BIT
= rf
"({'|'.join(CONDS.keys())})"
1468 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1469 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1470 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1471 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1472 XCR
= fr
"{CR}\.{BIT}"
1473 PATTERNS
= tuple(map(pattern
, (
1478 ("BIT+CR", (LBIT
+ CR
)),
1479 ("CR+BIT", (CR
+ RBIT
)),
1480 ("BIT+CR*N", (LBIT
+ CRN
)),
1481 ("CR*N+BIT", (CRN
+ RBIT
)),
1482 ("BIT+N*CR", (LBIT
+ NCR
)),
1483 ("N*CR+BIT", (NCR
+ RBIT
)),
1486 def remap(self
, value
, vector
, regtype
):
1487 if regtype
is _RegType
.CR_5BIT
:
1488 subvalue
= (value
& 0b11)
1492 extra
= (value
& 0b1111)
1495 extra
= (value
>> 3)
1498 if self
.record
.etype
is _SVEType
.EXTRA2
:
1500 assert (extra
& 0b111) == 0, \
1501 "vector CR cannot fit into EXTRA2"
1502 extra
= (0b10 |
(extra
>> 3))
1504 assert (extra
>> 1) == 0, \
1505 "scalar CR cannot fit into EXTRA2"
1507 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1509 assert (extra
& 0b11) == 0, \
1510 "vector CR cannot fit into EXTRA3"
1511 extra
= (0b100 |
(extra
>> 2))
1513 assert (extra
>> 2) == 0, \
1514 "scalar CR cannot fit into EXTRA3"
1517 if regtype
is _RegType
.CR_5BIT
:
1518 value
= ((value
<< 2) | subvalue
)
1520 return (value
, extra
)
1522 def assemble(self
, insn
, value
):
1523 if isinstance(value
, str):
1526 if value
.startswith("*"):
1527 if not isinstance(insn
, SVP64Instruction
):
1528 raise ValueError(value
)
1532 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1533 match
= pattern
.match(value
)
1534 if match
is not None:
1535 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1536 values
= match
.groups()
1537 match
= dict(zip(keys
, values
))
1538 CR
= int(match
["CR"])
1542 N
= int(match
.get("N", "1"))
1543 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1544 value
= ((CR
* N
) + BIT
)
1551 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1553 def disassemble(self
, insn
,
1554 style
=Style
.NORMAL
, prefix
="", indent
=""):
1555 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1557 if style
>= Style
.VERBOSE
:
1558 mode
= "vector" if vector
else "scalar"
1559 yield f
"{indent}{self.name} ({mode})"
1560 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1561 yield f
"{indent}{indent}{', '.join(span)}"
1562 if isinstance(insn
, SVP64Instruction
):
1563 for extra_idx
in frozenset(self
.extra_idx
):
1564 if self
.record
.etype
is _SVEType
.NONE
:
1565 yield f
"{indent}{indent}extra[none]"
1567 etype
= repr(self
.record
.etype
).lower()
1568 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1570 vector
= "*" if vector
else ""
1571 CR
= int(value
>> 2)
1573 cond
= ("lt", "gt", "eq", "so")[CC
]
1574 if style
>= Style
.NORMAL
:
1576 if isinstance(insn
, SVP64Instruction
):
1577 yield f
"{vector}cr{CR}.{cond}"
1579 yield f
"4*cr{CR}+{cond}"
1583 yield f
"{vector}{prefix}{int(value)}"
1586 class CR3Operand(ConditionRegisterFieldOperand
):
1587 def remap(self
, value
, vector
):
1588 return super().remap(value
=value
, vector
=vector
,
1589 regtype
=_RegType
.CR_3BIT
)
1592 class CR5Operand(ConditionRegisterFieldOperand
):
1593 def remap(self
, value
, vector
):
1594 return super().remap(value
=value
, vector
=vector
,
1595 regtype
=_RegType
.CR_5BIT
)
1597 def sv_spec_enter(self
, value
, span
):
1598 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1599 return (value
, span
)
1601 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1602 value
= _selectconcat(value
, origin_value
[3:5])
1604 return (value
, span
)
1607 class EXTSOperand(SignedOperand
):
1608 field
: str # real name to report
1609 nz
: int = 0 # number of zeros
1610 fmt
: str = "d" # integer formatter
1612 def __init__(self
, record
, name
, field
, nz
=0, fmt
="d"):
1613 self
.__field
= field
1616 return super().__init
__(record
=record
, name
=name
)
1632 return self
.record
.fields
[self
.field
]
1634 def assemble(self
, insn
, value
):
1636 if isinstance(value
, str):
1637 value
= int(value
, 0)
1638 insn
[span
] = (value
>> self
.nz
)
1640 def disassemble(self
, insn
,
1641 style
=Style
.NORMAL
, indent
=""):
1643 value
= insn
[span
].to_signed_int()
1644 sign
= "-" if (value
< 0) else ""
1645 value
= (abs(value
) << self
.nz
)
1647 if style
>= Style
.VERBOSE
:
1648 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1649 zeros
= ("0" * self
.nz
)
1650 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1651 yield f
"{indent * 1}{hint}"
1652 yield f
"{indent * 2}{self.field}"
1653 yield f
"{indent * 3}{sign}{value:{self.fmt}}"
1654 yield f
"{indent * 3}{', '.join(span)}"
1656 yield f
"{sign}{value:{self.fmt}}"
1659 class TargetAddrOperand(EXTSOperand
):
1660 def __init__(self
, record
, name
, field
):
1661 return super().__init
__(record
=record
, name
=name
, field
=field
,
1665 class TargetAddrOperandLI(TargetAddrOperand
):
1666 def __init__(self
, record
, name
):
1667 return super().__init
__(record
=record
, name
=name
, field
="LI")
1670 class TargetAddrOperandBD(TargetAddrOperand
):
1671 def __init__(self
, record
, name
):
1672 return super().__init
__(record
=record
, name
=name
, field
="BD")
1675 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1676 def __init__(self
, record
, name
):
1677 return super().__init
__(record
=record
, name
=name
, field
="DS", nz
=2)
1680 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1681 def __init__(self
, record
, name
):
1682 return super().__init
__(record
=record
, name
=name
, field
="DQ", nz
=4)
1685 class DOperandDX(SignedOperand
):
1688 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1689 operands
= map(cls
, ("d0", "d1", "d2"))
1690 spans
= map(lambda operand
: operand
.span
, operands
)
1691 return sum(spans
, tuple())
1693 def disassemble(self
, insn
,
1694 style
=Style
.NORMAL
, indent
=""):
1696 value
= insn
[span
].to_signed_int()
1697 sign
= "-" if (value
< 0) else ""
1700 if style
>= Style
.VERBOSE
:
1707 for (subname
, subspan
) in mapping
.items():
1708 operand
= DynamicOperand(name
=subname
)
1710 span
= map(str, span
)
1711 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1712 yield f
"{indent}{indent}{indent}{sign}{value}"
1713 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1715 yield f
"{sign}{value}"
1718 class Instruction(_Mapping
):
1720 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1721 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1722 raise ValueError(bits
)
1724 if isinstance(value
, bytes
):
1725 if ((len(value
) * 8) != bits
):
1726 raise ValueError(f
"bit length mismatch")
1727 value
= int.from_bytes(value
, byteorder
=byteorder
)
1729 if isinstance(value
, int):
1730 value
= _SelectableInt(value
=value
, bits
=bits
)
1731 elif isinstance(value
, Instruction
):
1732 value
= value
.storage
1734 if not isinstance(value
, _SelectableInt
):
1735 raise ValueError(value
)
1738 if len(value
) != bits
:
1739 raise ValueError(value
)
1741 value
= _SelectableInt(value
=value
, bits
=bits
)
1743 return cls(storage
=value
)
1746 return hash(int(self
))
1748 def __getitem__(self
, key
):
1749 return self
.storage
.__getitem
__(key
)
1751 def __setitem__(self
, key
, value
):
1752 return self
.storage
.__setitem
__(key
, value
)
1754 def bytes(self
, byteorder
="little"):
1755 nr_bytes
= (len(self
.__class
__) // 8)
1756 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1759 def record(cls
, db
, entry
):
1762 raise KeyError(entry
)
1766 def operands(cls
, record
):
1767 yield from record
.operands
1770 def static_operands(cls
, record
):
1771 return filter(lambda operand
: isinstance(operand
, StaticOperand
),
1772 cls
.operands(record
=record
))
1775 def dynamic_operands(cls
, record
):
1776 return filter(lambda operand
: isinstance(operand
, DynamicOperand
),
1777 cls
.operands(record
=record
))
1779 def spec(self
, record
, prefix
):
1780 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1781 self
.spec_dynamic_operands(record
=record
)))
1783 static_operands
= []
1784 for (name
, value
) in self
.spec_static_operands(record
=record
):
1785 static_operands
.append(f
"{name}={value}")
1788 if dynamic_operands
:
1790 operands
+= ",".join(dynamic_operands
)
1793 operands
+= " ".join(static_operands
)
1795 return f
"{prefix}{record.name}{operands}"
1797 def spec_static_operands(self
, record
):
1798 for operand
in self
.static_operands(record
=record
):
1799 if not isinstance(operand
, (POStaticOperand
, XOStaticOperand
)):
1800 yield (operand
.name
, operand
.value
)
1802 def spec_dynamic_operands(self
, record
, style
=Style
.NORMAL
):
1806 for operand
in self
.dynamic_operands(record
=record
):
1808 value
= " ".join(operand
.disassemble(insn
=self
,
1809 style
=min(style
, Style
.NORMAL
)))
1811 name
= f
"{imm_name}({name})"
1812 value
= f
"{imm_value}({value})"
1814 if isinstance(operand
, ImmediateOperand
):
1822 def assemble(cls
, record
, arguments
=None):
1823 if arguments
is None:
1826 insn
= cls
.integer(value
=0)
1828 for operand
in cls
.static_operands(record
=record
):
1829 operand
.assemble(insn
=insn
)
1831 arguments
= Arguments(record
=record
,
1832 arguments
=arguments
, operands
=cls
.dynamic_operands(record
=record
))
1833 for (value
, operand
) in arguments
:
1834 operand
.assemble(insn
=insn
, value
=value
)
1838 def disassemble(self
, record
,
1840 style
=Style
.NORMAL
):
1841 raise NotImplementedError()
1844 class WordInstruction(Instruction
):
1845 _
: _Field
= range(0, 32)
1846 PO
: _Field
= range(0, 6)
1849 def integer(cls
, value
, byteorder
="little"):
1850 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1855 for idx
in range(32):
1856 bit
= int(self
[idx
])
1858 return "".join(map(str, bits
))
1860 def disassemble(self
, record
,
1862 style
=Style
.NORMAL
):
1863 if style
<= Style
.SHORT
:
1866 blob
= self
.bytes(byteorder
=byteorder
)
1867 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1871 yield f
"{blob}.long 0x{int(self):08x}"
1874 # awful temporary hack: workaround for ld-update
1875 # https://bugs.libre-soc.org/show_bug.cgi?id=1056#c2
1876 # XXX TODO must check that *EXTENDED* RA != extended-RT
1877 if (record
.svp64
is not None and
1878 record
.mode
== _SVMode
.LDST_IMM
and
1879 'u' in record
.name
):
1880 yield f
"{blob}.long 0x{int(self):08x}"
1884 if style
is Style
.LEGACY
:
1886 for operand
in self
.dynamic_operands(record
=record
):
1887 if isinstance(operand
, (GPRPairOperand
, FPRPairOperand
)):
1890 if style
is Style
.LEGACY
and (paired
or record
.ppc
.unofficial
):
1891 yield f
"{blob}.long 0x{int(self):08x}"
1893 operands
= tuple(map(_operator
.itemgetter(1),
1894 self
.spec_dynamic_operands(record
=record
, style
=style
)))
1896 operands
= ",".join(operands
)
1897 yield f
"{blob}{record.name} {operands}"
1899 yield f
"{blob}{record.name}"
1901 if style
>= Style
.VERBOSE
:
1903 binary
= self
.binary
1904 spec
= self
.spec(record
=record
, prefix
="")
1905 yield f
"{indent}spec"
1906 yield f
"{indent}{indent}{spec}"
1907 yield f
"{indent}pcode"
1908 for stmt
in record
.mdwn
.pcode
:
1909 yield f
"{indent}{indent}{stmt}"
1910 yield f
"{indent}binary"
1911 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1912 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1913 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1914 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1915 yield f
"{indent}opcodes"
1916 for opcode
in record
.opcodes
:
1917 yield f
"{indent}{indent}{opcode!r}"
1918 for operand
in self
.operands(record
=record
):
1919 yield from operand
.disassemble(insn
=self
,
1920 style
=style
, indent
=indent
)
1924 class PrefixedInstruction(Instruction
):
1925 class Prefix(WordInstruction
.remap(range(0, 32))):
1928 class Suffix(WordInstruction
.remap(range(32, 64))):
1931 _
: _Field
= range(64)
1937 def integer(cls
, value
, byteorder
="little"):
1938 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
1941 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
1942 def transform(value
):
1943 return WordInstruction
.integer(value
=value
,
1944 byteorder
=byteorder
)[0:32]
1946 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
1947 value
= _selectconcat(prefix
, suffix
)
1949 return super().integer(bits
=64, value
=value
)
1952 class Mode(_Mapping
):
1953 _
: _Field
= range(0, 5)
1954 sel
: _Field
= (0, 1)
1957 class ExtraRM(_Mapping
):
1958 _
: _Field
= range(0, 9)
1961 class Extra2RM(ExtraRM
):
1962 idx0
: _Field
= range(0, 2)
1963 idx1
: _Field
= range(2, 4)
1964 idx2
: _Field
= range(4, 6)
1965 idx3
: _Field
= range(6, 8)
1967 def __getitem__(self
, key
):
1973 _SVExtra
.Idx0
: self
.idx0
,
1974 _SVExtra
.Idx1
: self
.idx1
,
1975 _SVExtra
.Idx2
: self
.idx2
,
1976 _SVExtra
.Idx3
: self
.idx3
,
1979 def __setitem__(self
, key
, value
):
1980 self
[key
].assign(value
)
1983 class Extra3RM(ExtraRM
):
1984 idx0
: _Field
= range(0, 3)
1985 idx1
: _Field
= range(3, 6)
1986 idx2
: _Field
= range(6, 9)
1988 def __getitem__(self
, key
):
1993 _SVExtra
.Idx0
: self
.idx0
,
1994 _SVExtra
.Idx1
: self
.idx1
,
1995 _SVExtra
.Idx2
: self
.idx2
,
1998 def __setitem__(self
, key
, value
):
1999 self
[key
].assign(value
)
2002 class BaseRM(_Mapping
):
2003 _
: _Field
= range(24)
2004 mmode
: _Field
= (0,)
2005 mask
: _Field
= range(1, 4)
2006 elwidth
: _Field
= range(4, 6)
2007 ewsrc
: _Field
= range(6, 8)
2008 subvl
: _Field
= range(8, 10)
2009 mode
: Mode
.remap(range(19, 24))
2010 smask_extra322
: _Field
= (6,7,18,) # LDST_IDX is EXTRA332
2011 smask
: _Field
= range(16, 19) # everything else use this
2012 extra
: ExtraRM
.remap(range(10, 19))
2013 extra2
: Extra2RM
.remap(range(10, 19))
2014 extra3
: Extra3RM
.remap(range(10, 19))
2015 # XXX extra332 = (extra3[0], extra3[1], extra2[3])
2017 def specifiers(self
, record
):
2018 subvl
= int(self
.subvl
)
2026 def disassemble(self
, style
=Style
.NORMAL
):
2027 if style
>= Style
.VERBOSE
:
2029 for (name
, span
) in self
.traverse(path
="RM"):
2030 value
= self
.storage
[span
]
2032 yield f
"{indent}{int(value):0{value.bits}b}"
2033 yield f
"{indent}{', '.join(map(str, span))}"
2036 class FFRc1BaseRM(BaseRM
):
2037 def specifiers(self
, record
, mode
):
2038 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
2039 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
2040 mask
= int(_selectconcat(CR
, inv
))
2041 predicate
= PredicateBaseRM
.predicate(True, mask
)
2042 yield f
"{mode}={predicate}"
2044 yield from super().specifiers(record
=record
)
2047 class FFRc0BaseRM(BaseRM
):
2048 def specifiers(self
, record
, mode
):
2050 inv
= "~" if self
.inv
else ""
2051 yield f
"{mode}={inv}RC1"
2053 yield from super().specifiers(record
=record
)
2056 class SatBaseRM(BaseRM
):
2057 def specifiers(self
, record
):
2063 yield from super().specifiers(record
=record
)
2066 class ZZBaseRM(BaseRM
):
2067 def specifiers(self
, record
):
2071 yield from super().specifiers(record
=record
)
2074 class ZZCombinedBaseRM(BaseRM
):
2075 def specifiers(self
, record
):
2076 if self
.sz
and self
.dz
:
2083 yield from super().specifiers(record
=record
)
2086 class DZBaseRM(BaseRM
):
2087 def specifiers(self
, record
):
2091 yield from super().specifiers(record
=record
)
2094 class SZBaseRM(BaseRM
):
2095 def specifiers(self
, record
):
2099 yield from super().specifiers(record
=record
)
2102 class MRBaseRM(BaseRM
):
2103 def specifiers(self
, record
):
2109 yield from super().specifiers(record
=record
)
2112 class ElsBaseRM(BaseRM
):
2113 def specifiers(self
, record
):
2117 yield from super().specifiers(record
=record
)
2120 class WidthBaseRM(BaseRM
):
2122 def width(FP
, width
):
2131 width
= ("fp" + width
)
2134 def specifiers(self
, record
):
2135 # elwidths: use "w=" if same otherwise dw/sw
2136 # FIXME this should consider FP instructions
2138 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
2139 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2140 if record
.svp64
.mode
is _SVMode
.CROP
:
2144 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2153 yield from super().specifiers(record
=record
)
2156 class PredicateBaseRM(BaseRM
):
2158 def predicate(CR
, mask
):
2161 (False, 0b001): "1<<r3",
2162 (False, 0b010): "r3",
2163 (False, 0b011): "~r3",
2164 (False, 0b100): "r10",
2165 (False, 0b101): "~r10",
2166 (False, 0b110): "r30",
2167 (False, 0b111): "~r30",
2169 (True, 0b000): "lt",
2170 (True, 0b001): "ge",
2171 (True, 0b010): "gt",
2172 (True, 0b011): "le",
2173 (True, 0b100): "eq",
2174 (True, 0b101): "ne",
2175 (True, 0b110): "so",
2176 (True, 0b111): "ns",
2179 def specifiers(self
, record
):
2180 # predication - single and twin
2181 # use "m=" if same otherwise sm/dm
2182 CR
= (int(self
.mmode
) == 1)
2183 mask
= int(self
.mask
)
2184 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
2185 if record
.svp64
.ptype
is _SVPType
.P2
:
2186 # LDST_IDX smask moving to extra322 but not straight away (False)
2187 if False and record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2188 smask
= int(self
.smask_extra332
)
2190 smask
= int(self
.smask
)
2191 sm
= PredicateBaseRM
.predicate(CR
, smask
)
2200 yield from super().specifiers(record
=record
)
2203 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
2207 class SEABaseRM(BaseRM
):
2208 def specifiers(self
, record
):
2212 yield from super().specifiers(record
=record
)
2215 class VLiBaseRM(BaseRM
):
2216 def specifiers(self
, record
):
2220 yield from super().specifiers(record
=record
)
2223 class NormalBaseRM(PredicateWidthBaseRM
):
2226 https://libre-soc.org/openpower/sv/normal/
2231 class NormalSimpleRM(ZZCombinedBaseRM
, NormalBaseRM
):
2232 """normal: simple mode"""
2236 def specifiers(self
, record
):
2237 yield from super().specifiers(record
=record
)
2240 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
2241 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
2245 class NormalFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, NormalBaseRM
):
2246 """normal: Rc=1: ffirst CR sel"""
2249 CR
: BaseRM
.mode
[3, 4]
2251 def specifiers(self
, record
):
2252 yield from super().specifiers(record
=record
, mode
="ff")
2255 class NormalFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
2256 """normal: Rc=0: ffirst z/nonz"""
2261 def specifiers(self
, record
):
2262 yield from super().specifiers(record
=record
, mode
="ff")
2265 class NormalSatRM(SatBaseRM
, ZZCombinedBaseRM
, NormalBaseRM
):
2266 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2272 class NormalRM(NormalBaseRM
):
2273 simple
: NormalSimpleRM
2275 ffrc1
: NormalFFRc1RM
2276 ffrc0
: NormalFFRc0RM
2280 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2282 LD/ST Immediate mode
2283 https://libre-soc.org/openpower/sv/ldst/
2288 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2289 """ld/st immediate: simple mode"""
2290 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2291 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2297 def specifiers(self
, record
):
2303 yield from super().specifiers(record
=record
)
2306 class LDSTFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2307 """ld/st immediate&indexed: Rc=1: ffirst CR sel"""
2310 CR
: BaseRM
.mode
[3, 4]
2312 def specifiers(self
, record
):
2313 yield from super().specifiers(record
=record
, mode
="ff")
2316 class LDSTFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2317 """ld/st immediate&indexed: Rc=0: ffirst z/nonz"""
2322 def specifiers(self
, record
):
2323 yield from super().specifiers(record
=record
, mode
="ff")
2326 class LDSTImmRM(LDSTImmBaseRM
):
2327 simple
: LDSTImmSimpleRM
2332 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2335 https://libre-soc.org/openpower/sv/ldst/
2340 class LDSTIdxSimpleRM(SEABaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2341 """ld/st index: simple mode (includes element-strided and Signed-EA)"""
2342 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2349 def specifiers(self
, record
):
2355 yield from super().specifiers(record
=record
)
2358 class LDSTIdxRM(LDSTIdxBaseRM
):
2359 simple
: LDSTIdxSimpleRM
2365 class CROpBaseRM(BaseRM
):
2368 https://libre-soc.org/openpower/sv/cr_ops/
2373 class CROpSimpleRM(PredicateBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2374 """crop: simple mode"""
2379 def specifiers(self
, record
):
2381 yield "rg" # simple CR Mode reports /rg
2383 yield from super().specifiers(record
=record
)
2386 class CROpMRRM(MRBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2387 """crop: scalar reduce mode (mapreduce)"""
2393 class CROpFF5RM(FFRc0BaseRM
, PredicateBaseRM
, VLiBaseRM
, DZBaseRM
,
2394 SZBaseRM
, CROpBaseRM
):
2395 """crop: ffirst 5-bit mode"""
2402 def specifiers(self
, record
):
2403 yield from super().specifiers(record
=record
, mode
="ff")
2406 # FIXME: almost everything in this class contradicts the specs (it doesn't)
2407 # The modes however are swapped: 5-bit is 3-bit, 3-bit is 5-bit
2408 class CROpFF3RM(FFRc1BaseRM
, PredicateBaseRM
, VLiBaseRM
, ZZBaseRM
, CROpBaseRM
):
2409 """cr_op: ffirst 3-bit mode"""
2415 def specifiers(self
, record
):
2416 yield from super().specifiers(record
=record
, mode
="ff")
2419 class CROpRM(CROpBaseRM
):
2420 simple
: CROpSimpleRM
2426 # ********************
2428 # https://libre-soc.org/openpower/sv/branches/
2429 class BranchBaseRM(BaseRM
):
2439 def specifiers(self
, record
):
2451 raise ValueError(self
.sz
)
2463 # Branch modes lack source mask.
2464 # Therefore a custom code is needed.
2465 CR
= (int(self
.mmode
) == 1)
2466 mask
= int(self
.mask
)
2467 m
= PredicateBaseRM
.predicate(CR
, mask
)
2471 yield from super().specifiers(record
=record
)
2474 class BranchSimpleRM(BranchBaseRM
):
2475 """branch: simple mode"""
2479 class BranchVLSRM(BranchBaseRM
):
2480 """branch: VLSET mode"""
2484 def specifiers(self
, record
):
2490 }[int(self
.VSb
), int(self
.VLi
)]
2492 yield from super().specifiers(record
=record
)
2495 class BranchCTRRM(BranchBaseRM
):
2496 """branch: CTR-test mode"""
2499 def specifiers(self
, record
):
2505 yield from super().specifiers(record
=record
)
2508 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2509 """branch: CTR-test+VLSET mode"""
2513 class BranchRM(BranchBaseRM
):
2514 simple
: BranchSimpleRM
2517 ctrvls
: BranchCTRVLSRM
2528 @_dataclasses.dataclass(eq
=True, frozen
=True)
2533 def match(cls
, desc
, record
):
2534 raise NotImplementedError()
2536 def validate(self
, others
):
2539 def assemble(self
, insn
):
2540 raise NotImplementedError()
2543 @_dataclasses.dataclass(eq
=True, frozen
=True)
2544 class SpecifierWidth(Specifier
):
2548 def match(cls
, desc
, record
, etalon
):
2549 (mode
, _
, value
) = desc
.partition("=")
2551 value
= value
.strip()
2554 width
= _SVP64Width(value
)
2556 return cls(record
=record
, width
=width
)
2559 @_dataclasses.dataclass(eq
=True, frozen
=True)
2560 class SpecifierW(SpecifierWidth
):
2562 def match(cls
, desc
, record
):
2563 return super().match(desc
=desc
, record
=record
, etalon
="w")
2565 def assemble(self
, insn
):
2566 selector
= insn
.select(record
=self
.record
)
2567 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2568 selector
.ewsrc
= self
.width
.value
2569 selector
.elwidth
= self
.width
.value
2572 @_dataclasses.dataclass(eq
=True, frozen
=True)
2573 class SpecifierSW(SpecifierWidth
):
2575 def match(cls
, desc
, record
):
2576 if record
.svp64
.mode
is _SVMode
.CROP
:
2578 return super().match(desc
=desc
, record
=record
, etalon
="sw")
2580 def assemble(self
, insn
):
2581 selector
= insn
.select(record
=self
.record
)
2582 selector
.ewsrc
= self
.width
.value
2585 @_dataclasses.dataclass(eq
=True, frozen
=True)
2586 class SpecifierDW(SpecifierWidth
):
2588 def match(cls
, desc
, record
):
2589 return super().match(desc
=desc
, record
=record
, etalon
="dw")
2591 def assemble(self
, insn
):
2592 selector
= insn
.select(record
=self
.record
)
2593 selector
.elwidth
= self
.width
.value
2596 @_dataclasses.dataclass(eq
=True, frozen
=True)
2597 class SpecifierSubVL(Specifier
):
2601 def match(cls
, desc
, record
):
2603 value
= _SVP64SubVL(desc
)
2607 return cls(record
=record
, value
=value
)
2609 def assemble(self
, insn
):
2610 selector
= insn
.select(record
=self
.record
)
2611 selector
.subvl
= int(self
.value
.value
)
2614 @_dataclasses.dataclass(eq
=True, frozen
=True)
2615 class SpecifierPredicate(Specifier
):
2620 def match(cls
, desc
, record
, mode_match
, pred_match
):
2621 (mode
, _
, pred
) = desc
.partition("=")
2624 if not mode_match(mode
):
2627 pred
= _SVP64Pred(pred
.strip())
2628 if not pred_match(pred
):
2629 raise ValueError(pred
)
2631 return cls(record
=record
, mode
=mode
, pred
=pred
)
2634 @_dataclasses.dataclass(eq
=True, frozen
=True)
2635 class SpecifierFF(SpecifierPredicate
):
2637 def match(cls
, desc
, record
):
2638 return super().match(desc
=desc
, record
=record
,
2639 mode_match
=lambda mode_arg
: mode_arg
== "ff",
2640 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2645 def assemble(self
, insn
):
2646 selector
= insn
.select(record
=self
.record
)
2647 if selector
.mode
.sel
!= 0:
2648 raise ValueError("cannot override mode")
2649 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2650 selector
.mode
.sel
= 0b01
2651 # HACK: please finally provide correct logic for CRs.
2652 if self
.pred
in (_SVP64Pred
.RC1
, _SVP64Pred
.RC1_N
):
2653 selector
.mode
[2] = (self
.pred
is _SVP64Pred
.RC1_N
)
2655 selector
.mode
[2] = self
.pred
.inv
2656 selector
.mode
[3, 4] = self
.pred
.state
2658 selector
.mode
.sel
= 0b01 if self
.mode
== "ff" else 0b11
2659 selector
.inv
= self
.pred
.inv
2661 selector
.CR
= self
.pred
.state
2663 selector
.RC1
= self
.pred
.state
2666 @_dataclasses.dataclass(eq
=True, frozen
=True)
2667 class SpecifierMask(SpecifierPredicate
):
2669 def match(cls
, desc
, record
, mode
):
2670 return super().match(desc
=desc
, record
=record
,
2671 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2672 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2677 def assemble(self
, insn
):
2678 raise NotImplementedError()
2681 @_dataclasses.dataclass(eq
=True, frozen
=True)
2682 class SpecifierM(SpecifierMask
):
2684 def match(cls
, desc
, record
):
2685 return super().match(desc
=desc
, record
=record
, mode
="m")
2687 def validate(self
, others
):
2689 if isinstance(spec
, SpecifierSM
):
2690 raise ValueError("source-mask and predicate mask conflict")
2691 elif isinstance(spec
, SpecifierDM
):
2692 raise ValueError("dest-mask and predicate mask conflict")
2694 def assemble(self
, insn
):
2695 selector
= insn
.select(record
=self
.record
)
2696 selector
.mask
= int(self
.pred
)
2697 if ((self
.record
.ptype
is _SVPType
.P2
) and
2698 (self
.record
.svp64
.mode
is not _SVMode
.BRANCH
)):
2699 selector
.smask
= int(self
.pred
)
2700 # LDST_IDX smask moving to extra322 but not straight away (False)
2701 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2702 selector
.smask_extra332
= int(self
.pred
)
2704 selector
.smask
= int(self
.pred
)
2706 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2709 @_dataclasses.dataclass(eq
=True, frozen
=True)
2710 class SpecifierSM(SpecifierMask
):
2712 def match(cls
, desc
, record
):
2713 return super().match(desc
=desc
, record
=record
, mode
="sm")
2715 def validate(self
, others
):
2716 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2717 raise ValueError("source-mask on non-twin predicate")
2719 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2722 if isinstance(spec
, SpecifierDM
):
2726 raise ValueError("missing dest-mask in CR twin predication")
2727 if self
.pred
.mode
!= twin
.pred
.mode
:
2728 raise ValueError(f
"predicate masks mismatch: "
2729 f
"{self.pred!r} vs {twin.pred!r}")
2731 def assemble(self
, insn
):
2732 selector
= insn
.select(record
=self
.record
)
2733 # LDST_IDX smask moving to extra322 but not straight away (False)
2734 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2735 selector
.smask_extra332
= int(self
.pred
)
2737 selector
.smask
= int(self
.pred
)
2738 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2741 @_dataclasses.dataclass(eq
=True, frozen
=True)
2742 class SpecifierDM(SpecifierMask
):
2744 def match(cls
, desc
, record
):
2745 return super().match(desc
=desc
, record
=record
, mode
="dm")
2747 def validate(self
, others
):
2748 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2749 raise ValueError("dest-mask on non-twin predicate")
2751 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2754 if isinstance(spec
, SpecifierSM
):
2758 raise ValueError("missing source-mask in CR twin predication")
2759 if self
.pred
.mode
!= twin
.pred
.mode
:
2760 raise ValueError(f
"predicate masks mismatch: "
2761 f
"{self.pred!r} vs {twin.pred!r}")
2763 def assemble(self
, insn
):
2764 selector
= insn
.select(record
=self
.record
)
2765 selector
.mask
= int(self
.pred
)
2766 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2769 @_dataclasses.dataclass(eq
=True, frozen
=True)
2770 class SpecifierZZ(Specifier
):
2772 def match(cls
, desc
, record
):
2776 return cls(record
=record
)
2778 def validate(self
, others
):
2780 # Since zz takes precedence (overrides) sz and dz,
2781 # treat them as mutually exclusive.
2782 if isinstance(spec
, (SpecifierSZ
, SpecifierDZ
)):
2783 raise ValueError("mutually exclusive predicate masks")
2785 def assemble(self
, insn
):
2786 selector
= insn
.select(record
=self
.record
)
2787 if hasattr(selector
, "zz"): # this should be done in a different way
2794 @_dataclasses.dataclass(eq
=True, frozen
=True)
2795 class SpecifierXZ(Specifier
):
2797 hint
: str = _dataclasses
.field(repr=False)
2800 def match(cls
, desc
, record
, etalon
, hint
):
2804 return cls(desc
=desc
, record
=record
, hint
=hint
)
2806 def validate(self
, others
):
2807 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2808 raise ValueError(f
"{self.hint} on non-twin predicate")
2810 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2813 if isinstance(spec
, SpecifierXZ
):
2817 raise ValueError(f
"missing {self.hint} in CR twin predication")
2818 if self
.pred
!= twin
.pred
:
2819 raise ValueError(f
"predicate masks mismatch: "
2820 f
"{self.pred!r} vs {twin.pred!r}")
2822 def assemble(self
, insn
):
2823 selector
= insn
.select(record
=self
.record
)
2824 setattr(selector
, self
.desc
, 1)
2827 @_dataclasses.dataclass(eq
=True, frozen
=True)
2828 class SpecifierSZ(SpecifierXZ
):
2830 def match(cls
, desc
, record
):
2831 return super().match(desc
=desc
, record
=record
,
2832 etalon
="sz", hint
="source-mask")
2834 def validate(self
, others
):
2836 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2837 if isinstance(spec
, SpecifierFF
):
2838 raise ValueError("source-zero not allowed in ff mode")
2841 @_dataclasses.dataclass(eq
=True, frozen
=True)
2842 class SpecifierDZ(SpecifierXZ
):
2844 def match(cls
, desc
, record
):
2845 return super().match(desc
=desc
, record
=record
,
2846 etalon
="dz", hint
="dest-mask")
2848 def validate(self
, others
):
2850 if ((self
.record
.svp64
.mode
is not _SVMode
.CROP
) and
2851 isinstance(spec
, SpecifierFF
) and
2852 (spec
.pred
.mode
is _SVP64PredMode
.RC1
)):
2853 raise ValueError(f
"dest-zero not allowed in ff mode BO")
2856 @_dataclasses.dataclass(eq
=True, frozen
=True)
2857 class SpecifierEls(Specifier
):
2859 def match(cls
, desc
, record
):
2863 if record
.svp64
.mode
not in (_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
):
2864 raise ValueError("els is only valid in ld/st modes, not "
2865 "%s" % str(self
.record
.svp64
.mode
))
2867 return cls(record
=record
)
2869 def assemble(self
, insn
):
2870 if self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
: # stride mode
2871 insn
.prefix
.rm
.mode
[1] = 0
2873 selector
= insn
.select(record
=self
.record
)
2878 @_dataclasses.dataclass(eq
=True, frozen
=True)
2879 class SpecifierSEA(Specifier
):
2881 def match(cls
, desc
, record
):
2885 return cls(record
=record
)
2887 def validate(self
, others
):
2888 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
:
2889 raise ValueError("sea is only valid in ld/st modes, not "
2890 "%s" % str(self
.record
.svp64
.mode
))
2893 if isinstance(spec
, SpecifierFF
):
2894 raise ValueError(f
"sea cannot be used in ff mode")
2896 def assemble(self
, insn
):
2897 selector
= insn
.select(record
=self
.record
)
2898 if selector
.mode
.sel
not in (0b10, 0b00):
2899 raise ValueError("sea is only valid for normal and els modes, "
2900 "not %d" % int(selector
.mode
.sel
))
2904 @_dataclasses.dataclass(eq
=True, frozen
=True)
2905 class SpecifierSat(Specifier
):
2910 def match(cls
, desc
, record
, etalon
, sign
):
2914 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.LDST_IMM
,
2916 raise ValueError("only normal, ld/st imm and "
2917 "ld/st idx modes supported")
2919 return cls(record
=record
, desc
=desc
, sign
=sign
)
2921 def assemble(self
, insn
):
2922 selector
= insn
.select(record
=self
.record
)
2923 selector
.mode
[0] = 0b1
2924 selector
.mode
[1] = 0b0
2925 selector
.N
= int(self
.sign
)
2928 @_dataclasses.dataclass(eq
=True, frozen
=True)
2929 class SpecifierSatS(SpecifierSat
):
2931 def match(cls
, desc
, record
):
2932 return super().match(desc
=desc
, record
=record
,
2933 etalon
="sats", sign
=True)
2936 @_dataclasses.dataclass(eq
=True, frozen
=True)
2937 class SpecifierSatU(SpecifierSat
):
2939 def match(cls
, desc
, record
):
2940 return super().match(desc
=desc
, record
=record
,
2941 etalon
="satu", sign
=False)
2944 @_dataclasses.dataclass(eq
=True, frozen
=True)
2945 class SpecifierMapReduce(Specifier
):
2949 def match(cls
, record
, RG
):
2950 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2951 raise ValueError("only normal and crop modes supported")
2953 return cls(record
=record
, RG
=RG
)
2955 def assemble(self
, insn
):
2956 selector
= insn
.select(record
=self
.record
)
2957 if self
.record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2958 raise ValueError("only normal and crop modes supported")
2959 selector
.mode
[0] = 0
2960 selector
.mode
[1] = 0
2961 selector
.mode
[2] = 1
2962 selector
.RG
= self
.RG
2965 @_dataclasses.dataclass(eq
=True, frozen
=True)
2966 class SpecifierMR(SpecifierMapReduce
):
2968 def match(cls
, desc
, record
):
2972 return super().match(record
=record
, RG
=False)
2975 @_dataclasses.dataclass(eq
=True, frozen
=True)
2976 class SpecifierMRR(SpecifierMapReduce
):
2978 def match(cls
, desc
, record
):
2982 return super().match(record
=record
, RG
=True)
2985 @_dataclasses.dataclass(eq
=True, frozen
=True)
2986 class SpecifierBranch(Specifier
):
2988 def match(cls
, desc
, record
, etalon
):
2992 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
2993 raise ValueError("only branch modes supported")
2995 return cls(record
=record
)
2998 @_dataclasses.dataclass(eq
=True, frozen
=True)
2999 class SpecifierAll(SpecifierBranch
):
3001 def match(cls
, desc
, record
):
3002 return super().match(desc
=desc
, record
=record
, etalon
="all")
3004 def assemble(self
, insn
):
3005 selector
= insn
.select(record
=self
.record
)
3009 @_dataclasses.dataclass(eq
=True, frozen
=True)
3010 class SpecifierSNZ(Specifier
):
3012 def match(cls
, desc
, record
):
3016 if record
.svp64
.mode
not in (_SVMode
.BRANCH
, _SVMode
.CROP
):
3017 raise ValueError("only branch and crop modes supported")
3019 return cls(record
=record
)
3021 def assemble(self
, insn
):
3022 selector
= insn
.select(record
=self
.record
)
3023 if self
.record
.svp64
.mode
in (_SVMode
.CROP
, _SVMode
.BRANCH
):
3025 if self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3028 raise ValueError("only branch and crop modes supported")
3031 @_dataclasses.dataclass(eq
=True, frozen
=True)
3032 class SpecifierSL(SpecifierBranch
):
3034 def match(cls
, desc
, record
):
3035 return super().match(desc
=desc
, record
=record
, etalon
="sl")
3037 def assemble(self
, insn
):
3038 selector
= insn
.select(record
=self
.record
)
3042 @_dataclasses.dataclass(eq
=True, frozen
=True)
3043 class SpecifierSLu(SpecifierBranch
):
3045 def match(cls
, desc
, record
):
3046 return super().match(desc
=desc
, record
=record
, etalon
="slu")
3048 def assemble(self
, insn
):
3049 selector
= insn
.select(record
=self
.record
)
3053 @_dataclasses.dataclass(eq
=True, frozen
=True)
3054 class SpecifierLRu(SpecifierBranch
):
3056 def match(cls
, desc
, record
):
3057 return super().match(desc
=desc
, record
=record
, etalon
="lru")
3059 def assemble(self
, insn
):
3060 selector
= insn
.select(record
=self
.record
)
3064 @_dataclasses.dataclass(eq
=True, frozen
=True)
3065 class SpecifierVSXX(SpecifierBranch
):
3070 def match(cls
, desc
, record
, etalon
, VSb
, VLi
):
3074 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3075 raise ValueError("only branch modes supported")
3077 return cls(record
=record
, VSb
=VSb
, VLi
=VLi
)
3079 def assemble(self
, insn
):
3080 selector
= insn
.select(record
=self
.record
)
3082 selector
.VSb
= int(self
.VSb
)
3083 selector
.VLi
= int(self
.VLi
)
3086 @_dataclasses.dataclass(eq
=True, frozen
=True)
3087 class SpecifierVS(SpecifierVSXX
):
3089 def match(cls
, desc
, record
):
3090 return super().match(desc
=desc
, record
=record
,
3091 etalon
="vs", VSb
=False, VLi
=False)
3094 @_dataclasses.dataclass(eq
=True, frozen
=True)
3095 class SpecifierVSi(SpecifierVSXX
):
3097 def match(cls
, desc
, record
):
3098 return super().match(desc
=desc
, record
=record
,
3099 etalon
="vsi", VSb
=False, VLi
=True)
3102 @_dataclasses.dataclass(eq
=True, frozen
=True)
3103 class SpecifierVSb(SpecifierVSXX
):
3105 def match(cls
, desc
, record
):
3106 return super().match(desc
=desc
, record
=record
,
3107 etalon
="vsb", VSb
=True, VLi
=False)
3110 @_dataclasses.dataclass(eq
=True, frozen
=True)
3111 class SpecifierVSbi(SpecifierVSXX
):
3113 def match(cls
, desc
, record
):
3114 return super().match(desc
=desc
, record
=record
,
3115 etalon
="vsbi", VSb
=True, VLi
=True)
3118 @_dataclasses.dataclass(eq
=True, frozen
=True)
3119 class SpecifierCTX(Specifier
):
3123 def match(cls
, desc
, record
, etalon
, CTi
):
3127 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3128 raise ValueError("only branch modes supported")
3130 return cls(record
=record
, CTi
=CTi
)
3132 def assemble(self
, insn
):
3133 selector
= insn
.select(record
=self
.record
)
3135 selector
.CTi
= int(self
.CTi
)
3138 @_dataclasses.dataclass(eq
=True, frozen
=True)
3139 class SpecifierCTR(SpecifierCTX
):
3141 def match(cls
, desc
, record
):
3142 return super().match(desc
=desc
, record
=record
,
3143 etalon
="ctr", CTi
=False)
3146 @_dataclasses.dataclass(eq
=True, frozen
=True)
3147 class SpecifierCTi(SpecifierCTX
):
3149 def match(cls
, desc
, record
):
3150 return super().match(desc
=desc
, record
=record
,
3151 etalon
="cti", CTi
=True)
3154 @_dataclasses.dataclass(eq
=True, frozen
=True)
3155 class SpecifierPI(Specifier
):
3157 def match(cls
, desc
, record
):
3161 if record
.svp64
.mode
not in [_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
]:
3162 raise ValueError("only ld/st imm/idx mode supported")
3164 return cls(record
=record
)
3166 def assemble(self
, insn
):
3167 selector
= insn
.select(record
=self
.record
)
3168 selector
.mode
[2] = 0b1
3172 @_dataclasses.dataclass(eq
=True, frozen
=True)
3173 class SpecifierLF(Specifier
):
3175 def match(cls
, desc
, record
):
3179 if record
.svp64
.mode
is not _SVMode
.LDST_IMM
:
3180 raise ValueError("only ld/st imm mode supported")
3182 return cls(record
=record
)
3184 def assemble(self
, insn
):
3185 selector
= insn
.select(record
=self
.record
)
3186 selector
.mode
[1] = 0
3190 @_dataclasses.dataclass(eq
=True, frozen
=True)
3191 class SpecifierVLi(Specifier
):
3193 def match(cls
, desc
, record
):
3197 return cls(record
=record
)
3199 def validate(self
, others
):
3201 if isinstance(spec
, SpecifierFF
):
3204 raise ValueError("VLi only allowed in failfirst")
3206 def assemble(self
, insn
):
3207 selector
= insn
.select(record
=self
.record
)
3208 selector
.mode
[1] = 1
3212 class Specifiers(tuple):
3247 def __new__(cls
, items
, record
):
3248 def transform(item
):
3249 for spec_cls
in cls
.SPECS
:
3250 spec
= spec_cls
.match(item
, record
=record
)
3251 if spec
is not None:
3253 raise ValueError(item
)
3255 # TODO: remove this hack
3256 items
= dict.fromkeys(items
)
3260 items
= tuple(items
)
3262 specs
= tuple(map(transform
, items
))
3263 for (index
, spec
) in enumerate(specs
):
3264 head
= specs
[:index
]
3265 tail
= specs
[index
+ 1:]
3266 spec
.validate(others
=(head
+ tail
))
3268 return super().__new
__(cls
, specs
)
3271 class SVP64OperandMeta(type):
3272 class SVP64NonZeroOperand(NonZeroOperand
):
3273 def assemble(self
, insn
, value
):
3274 if isinstance(value
, str):
3275 value
= int(value
, 0)
3276 if not isinstance(value
, int):
3277 raise ValueError("non-integer operand")
3279 # FIXME: this is really weird
3280 if self
.record
.name
in ("svstep", "svstep."):
3281 value
+= 1 # compensation
3283 return super().assemble(value
=value
, insn
=insn
)
3285 class SVP64XOStaticOperand(SpanStaticOperand
):
3286 def __init__(self
, record
, value
, span
):
3287 return super().__init
__(record
=record
, name
="XO",
3288 value
=value
, span
=span
)
3291 NonZeroOperand
: SVP64NonZeroOperand
,
3292 XOStaticOperand
: SVP64XOStaticOperand
,
3295 def __new__(metacls
, name
, bases
, ns
):
3297 for (index
, base_cls
) in enumerate(bases
):
3298 bases
[index
] = metacls
.__TRANSFORM
.get(base_cls
, base_cls
)
3300 bases
= tuple(bases
)
3302 return super().__new
__(metacls
, name
, bases
, ns
)
3305 class SVP64Operand(Operand
, metaclass
=SVP64OperandMeta
):
3308 return tuple(map(lambda bit
: (bit
+ 32), super().span
))
3312 def __init__(self
, insn
, record
):
3314 self
.__record
= record
3315 return super().__init
__()
3318 return self
.rm
.__doc
__
3321 return repr(self
.rm
)
3329 return self
.__record
3333 rm
= getattr(self
.insn
.prefix
.rm
, self
.record
.svp64
.mode
.name
.lower())
3335 # The idea behind these tables is that they are now literally
3336 # in identical format to insndb.csv and minor_xx.csv and can
3337 # be done precisely as that. The only thing to watch out for
3338 # is the insertion of Rc=1 as a "mask/value" bit and likewise
3339 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
3342 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
3343 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3344 # mode Rc mask Rc member
3346 (0b000000, 0b111000, "simple"), # simple (no Rc)
3347 (0b001000, 0b111100, "mr"), # mapreduce (no Rc)
3348 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3349 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3350 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3351 (0b001100, 0b111100, "rsvd"), # reserved
3353 mode
= int(self
.insn
.prefix
.rm
.normal
.mode
)
3354 search
= ((mode
<< 1) | self
.record
.Rc
)
3356 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
3357 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3358 # mode Rc mask Rc member
3359 # ironically/coincidentally this table is identical to NORMAL
3360 # mode except reserved in place of mr
3362 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3363 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3364 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3366 search
= ((int(self
.insn
.prefix
.rm
.ldst_imm
.mode
) << 1) |
3369 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
3370 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3371 # mode Rc mask Rc member
3373 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3374 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3375 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3377 search
= ((int(self
.insn
.prefix
.rm
.ldst_idx
.mode
) << 1) |
3380 elif self
.record
.svp64
.mode
is _SVMode
.CROP
:
3381 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
3382 # mode 3b mask 3b member
3384 (0b000000, 0b111000, "simple"), # simple
3385 (0b001000, 0b111000, "mr"), # mapreduce
3386 (0b010001, 0b010001, "ff3"), # ffirst, 3-bit CR
3387 (0b010000, 0b010000, "ff5"), # ffirst, 5-bit CR
3389 search
= ((int(self
.insn
.prefix
.rm
.crop
.mode
) << 1) |
3390 int(self
.record
.svp64
.extra_CR_3bit
))
3392 elif self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3396 (0b00, 0b11, "simple"), # simple
3397 (0b01, 0b11, "vls"), # VLset
3398 (0b10, 0b11, "ctr"), # CTR mode
3399 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
3401 # slightly weird: doesn't have a 5-bit "mode" field like others
3402 search
= int(self
.insn
.prefix
.rm
.branch
.mode
.sel
)
3405 if table
is not None:
3406 for (value
, mask
, field
) in table
:
3407 if field
.startswith("rsvd"):
3409 if ((value
& mask
) == (search
& mask
)):
3410 return getattr(rm
, field
)
3414 def __getattr__(self
, key
):
3415 if key
.startswith(f
"_{self.__class__.__name__}__"):
3416 return super().__getattribute
__(key
)
3418 return getattr(self
.rm
, key
)
3420 def __setattr__(self
, key
, value
):
3421 if key
.startswith(f
"_{self.__class__.__name__}__"):
3422 return super().__setattr
__(key
, value
)
3425 if not hasattr(rm
, key
):
3426 raise AttributeError(key
)
3428 return setattr(rm
, key
, value
)
3431 class SVP64Instruction(PrefixedInstruction
):
3432 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
3433 class Prefix(PrefixedInstruction
.Prefix
):
3435 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
3439 def select(self
, record
):
3440 return RMSelector(insn
=self
, record
=record
)
3445 for idx
in range(64):
3446 bit
= int(self
[idx
])
3448 return "".join(map(str, bits
))
3451 def assemble(cls
, record
, arguments
=None, specifiers
=None):
3452 insn
= super().assemble(record
=record
, arguments
=arguments
)
3454 specifiers
= Specifiers(items
=specifiers
, record
=record
)
3455 for specifier
in specifiers
:
3456 specifier
.assemble(insn
=insn
)
3458 insn
.prefix
.PO
= 0x1
3459 insn
.prefix
.id = 0x3
3463 def disassemble(self
, record
,
3465 style
=Style
.NORMAL
):
3467 if style
<= Style
.SHORT
:
3470 blob
= insn
.bytes(byteorder
=byteorder
)
3471 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
3474 blob_prefix
= blob(self
.prefix
)
3475 blob_suffix
= blob(self
.suffix
)
3477 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3478 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
3481 assert record
.svp64
is not None
3483 name
= f
"sv.{record.name}"
3485 rm
= self
.select(record
=record
)
3487 # convert specifiers to /x/y/z (sorted lexicographically)
3488 specifiers
= sorted(rm
.specifiers(record
=record
))
3489 if specifiers
: # if any add one extra to get the extra "/"
3490 specifiers
= ([""] + specifiers
)
3491 specifiers
= "/".join(specifiers
)
3493 # convert operands to " ,x,y,z"
3494 operands
= tuple(map(_operator
.itemgetter(1),
3495 self
.spec_dynamic_operands(record
=record
, style
=style
)))
3496 operands
= ",".join(operands
)
3497 if len(operands
) > 0: # if any separate with a space
3498 operands
= (" " + operands
)
3500 if style
<= Style
.LEGACY
:
3501 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3502 suffix
= WordInstruction
.integer(value
=int(self
.suffix
))
3503 yield from suffix
.disassemble(record
=record
,
3504 byteorder
=byteorder
, style
=style
)
3506 yield f
"{blob_prefix}{name}{specifiers}{operands}"
3508 yield f
"{blob_suffix}"
3510 if style
>= Style
.VERBOSE
:
3512 binary
= self
.binary
3513 spec
= self
.spec(record
=record
, prefix
="sv.")
3515 yield f
"{indent}spec"
3516 yield f
"{indent}{indent}{spec}"
3517 yield f
"{indent}pcode"
3518 for stmt
in record
.mdwn
.pcode
:
3519 yield f
"{indent}{indent}{stmt}"
3520 yield f
"{indent}binary"
3521 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
3522 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
3523 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
3524 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
3525 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
3526 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
3527 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
3528 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
3529 yield f
"{indent}opcodes"
3530 for opcode
in record
.opcodes
:
3531 yield f
"{indent}{indent}{opcode!r}"
3532 for operand
in self
.operands(record
=record
):
3533 yield from operand
.disassemble(insn
=self
,
3534 style
=style
, indent
=indent
)
3536 yield f
"{indent}{indent}{str(rm)}"
3537 for line
in rm
.disassemble(style
=style
):
3538 yield f
"{indent}{indent}{line}"
3542 def operands(cls
, record
):
3543 for operand
in super().operands(record
=record
):
3544 parent
= operand
.__class
__
3545 name
= f
"SVP64{parent.__name__}"
3546 bases
= (SVP64Operand
, parent
)
3547 child
= type(name
, bases
, {})
3548 yield child(**dict(operand
))
3551 def parse(stream
, factory
):
3553 return ("TODO" not in frozenset(entry
.values()))
3555 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
3556 entries
= _csv
.DictReader(lines
)
3557 entries
= filter(match
, entries
)
3558 return tuple(map(factory
, entries
))
3561 class MarkdownDatabase
:
3564 for (name
, desc
) in _ISA():
3567 (dynamic
, *static
) = desc
.regs
3568 operands
.extend(dynamic
)
3569 operands
.extend(static
)
3570 pcode
= PCode(iterable
=filter(str.strip
, desc
.pcode
))
3571 operands
= Operands(insn
=name
, operands
=operands
)
3572 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
3574 self
.__db
= dict(sorted(db
.items()))
3576 return super().__init
__()
3579 yield from self
.__db
.items()
3581 def __contains__(self
, key
):
3582 return self
.__db
.__contains
__(key
)
3584 def __getitem__(self
, key
):
3585 return self
.__db
.__getitem
__(key
)
3588 class FieldsDatabase
:
3591 df
= _DecodeFields()
3593 for (form
, fields
) in df
.instrs
.items():
3594 if form
in {"DQE", "TX"}:
3598 db
[_Form
[form
]] = Fields(fields
)
3602 return super().__init
__()
3604 def __getitem__(self
, key
):
3605 return self
.__db
.__getitem
__(key
)
3609 def __init__(self
, root
, mdwndb
):
3610 # The code below groups the instructions by name:section.
3611 # There can be multiple names for the same instruction.
3612 # The point is to capture different opcodes for the same instruction.
3614 records
= _collections
.defaultdict(set)
3615 path
= (root
/ "insndb.csv")
3616 with
open(path
, "r", encoding
="UTF-8") as stream
:
3617 for section
in sorted(parse(stream
, Section
.CSV
)):
3618 path
= (root
/ section
.path
)
3620 section
.Mode
.INTEGER
: IntegerOpcode
,
3621 section
.Mode
.PATTERN
: PatternOpcode
,
3623 factory
= _functools
.partial(
3624 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
3625 with
open(path
, "r", encoding
="UTF-8") as stream
:
3626 for insn
in parse(stream
, factory
):
3627 for name
in insn
.names
:
3628 records
[name
].add(insn
)
3629 sections
[name
] = section
3631 items
= sorted(records
.items())
3633 for (name
, multirecord
) in items
:
3634 records
[name
] = PPCMultiRecord(sorted(multirecord
))
3636 def exact_match(name
):
3637 record
= records
.get(name
)
3643 if not name
.endswith("l"):
3645 alias
= exact_match(name
[:-1])
3648 record
= records
[alias
]
3649 if "lk" not in record
.flags
:
3650 raise ValueError(record
)
3654 if not name
.endswith("a"):
3656 alias
= LK_match(name
[:-1])
3659 record
= records
[alias
]
3660 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
3661 raise ValueError(record
)
3662 if "AA" not in mdwndb
[name
].operands
:
3663 raise ValueError(record
)
3667 if not name
.endswith("."):
3669 alias
= exact_match(name
[:-1])
3672 record
= records
[alias
]
3673 if record
.Rc
is _RCOE
.NONE
:
3674 raise ValueError(record
)
3678 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
3679 for (name
, _
) in mdwndb
:
3680 if name
.startswith("sv."):
3683 for match
in matches
:
3685 if alias
is not None:
3689 section
= sections
[alias
]
3690 record
= records
[alias
]
3691 db
[name
] = (section
, record
)
3693 self
.__db
= dict(sorted(db
.items()))
3695 return super().__init
__()
3697 @_functools.lru_cache(maxsize
=512, typed
=False)
3698 def __getitem__(self
, key
):
3699 return self
.__db
.get(key
, (None, None))
3702 class SVP64Database
:
3703 def __init__(self
, root
, ppcdb
):
3705 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
3706 for (prefix
, _
, names
) in _os
.walk(root
):
3707 prefix
= _pathlib
.Path(prefix
)
3708 for name
in filter(lambda name
: pattern
.match(name
), names
):
3709 path
= (prefix
/ _pathlib
.Path(name
))
3710 with
open(path
, "r", encoding
="UTF-8") as stream
:
3711 db
.update(parse(stream
, SVP64Record
.CSV
))
3712 db
= {record
.name
:record
for record
in db
}
3714 self
.__db
= dict(sorted(db
.items()))
3715 self
.__ppcdb
= ppcdb
3717 return super().__init
__()
3719 def __getitem__(self
, key
):
3720 (_
, record
) = self
.__ppcdb
[key
]
3724 for name
in record
.names
:
3725 record
= self
.__db
.get(name
, None)
3726 if record
is not None:
3732 class Database(Node
):
3733 def __init__(self
, root
):
3734 root
= _pathlib
.Path(root
)
3735 mdwndb
= MarkdownDatabase()
3736 fieldsdb
= FieldsDatabase()
3737 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
3738 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
3742 opcodes
= _collections
.defaultdict(
3743 lambda: _collections
.defaultdict(set))
3745 for (name
, mdwn
) in mdwndb
:
3746 if name
.startswith("sv."):
3748 (section
, ppc
) = ppcdb
[name
]
3751 svp64
= svp64db
[name
]
3752 fields
= fieldsdb
[ppc
.form
]
3753 record
= Record(name
=name
,
3754 section
=section
, ppc
=ppc
, svp64
=svp64
,
3755 mdwn
=mdwn
, fields
=fields
)
3757 names
[record
.name
] = record
3758 opcodes
[section
][record
.PO
].add(record
)
3760 self
.__db
= sorted(db
)
3761 self
.__names
= dict(sorted(names
.items()))
3762 self
.__opcodes
= dict(sorted(opcodes
.items()))
3764 return super().__init
__()
3766 def subnodes(self
, match
=None):
3768 match
= lambda subnode
: True
3770 yield from filter(match
, self
)
3773 return repr(self
.__db
)
3776 yield from self
.__db
3778 @_functools.lru_cache(maxsize
=None)
3779 def __contains__(self
, key
):
3780 return self
.__getitem
__(key
) is not None
3782 @_functools.lru_cache(maxsize
=None)
3783 def __getitem__(self
, key
):
3784 if isinstance(key
, SVP64Instruction
):
3787 if isinstance(key
, Instruction
):
3790 sections
= sorted(self
.__opcodes
)
3791 for section
in sections
:
3792 group
= self
.__opcodes
[section
]
3793 for record
in group
[PO
]:
3794 if record
.match(key
=key
):
3799 elif isinstance(key
, str):
3800 return self
.__names
.get(key
)
3802 raise ValueError("instruction or name expected")