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 visit(self
, handler
, matcher
, depth
):
61 if matcher(node
=self
, depth
=depth
):
62 with
handler(node
=self
, depth
=depth
):
67 def __init__(self
, **parameters
):
68 self
.__parameters
= _types
.MappingProxyType(parameters
)
69 return super().__init
__()
71 def __contains__(self
, key
):
72 return self
.__parameters
.__contains
__(key
)
74 def __getitem__(self
, key
):
75 return self
.__parameters
.__getitem
__(key
)
77 def Node(self
, node
, depth
):
78 raise NotImplementedError()
80 def __call__(self
, node
, depth
):
81 method
= node
.__class
__.__name
__
82 method
= getattr(self
, method
, self
.Node
)
83 return method(node
=node
, depth
=depth
)
86 class Matcher(Visitor
):
87 def Node(self
, node
, depth
):
91 class Handler(Visitor
):
92 @_contextlib.contextmanager
93 def Node(self
, node
, depth
):
97 def visit(node
, handler
, matcher
=Matcher()):
98 node
.visit(handler
=handler
, matcher
=matcher
, depth
=0)
101 @_functools.total_ordering
102 class Style(_enum
.Enum
):
103 LEGACY
= _enum
.auto()
105 NORMAL
= _enum
.auto()
106 VERBOSE
= _enum
.auto()
108 def __lt__(self
, other
):
109 if not isinstance(other
, self
.__class
__):
110 return NotImplemented
111 return (self
.value
< other
.value
)
114 @_functools.total_ordering
115 class Priority(_enum
.Enum
):
121 def _missing_(cls
, value
):
122 if isinstance(value
, str):
123 value
= value
.upper()
127 return super()._missing
_(value
)
129 def __lt__(self
, other
):
130 if not isinstance(other
, self
.__class
__):
131 return NotImplemented
133 # NOTE: the order is inversed, LOW < NORMAL < HIGH
134 return (self
.value
> other
.value
)
137 def dataclass(cls
, record
, keymap
=None, typemap
=None):
141 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
143 def transform(key_value
):
144 (key
, value
) = key_value
145 key
= keymap
.get(key
, key
)
146 hook
= typemap
.get(key
, lambda value
: value
)
147 if hook
is bool and value
in ("", "0"):
153 record
= dict(map(transform
, record
.items()))
154 for key
in frozenset(record
.keys()):
155 if record
[key
] == "":
161 @_functools.total_ordering
162 @_dataclasses.dataclass(eq
=True, frozen
=True)
165 def __new__(cls
, value
):
166 if isinstance(value
, str):
167 value
= int(value
, 0)
168 if not isinstance(value
, int):
169 raise ValueError(value
)
171 if value
.bit_length() > 64:
172 raise ValueError(value
)
174 return super().__new
__(cls
, value
)
177 return self
.__repr
__()
180 return f
"{self:0{self.bit_length()}b}"
182 def bit_length(self
):
183 if super().bit_length() > 32:
187 class Value(Integer
):
196 def __lt__(self
, other
):
197 if not isinstance(other
, Opcode
):
198 return NotImplemented
199 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
202 return (self
.value
& self
.mask
)
205 return int(self
).__index
__()
208 def pattern(value
, mask
, bit_length
):
209 for bit
in range(bit_length
):
210 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
212 elif (value
& (1 << (bit_length
- bit
- 1))):
217 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
219 def match(self
, key
):
220 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
223 @_functools.total_ordering
224 @_dataclasses.dataclass(eq
=True, frozen
=True)
225 class IntegerOpcode(Opcode
):
226 def __init__(self
, value
):
227 if value
.startswith("0b"):
228 mask
= int(("1" * len(value
[2:])), 2)
232 value
= Opcode
.Value(value
)
233 mask
= Opcode
.Mask(mask
)
235 return super().__init
__(value
=value
, mask
=mask
)
238 @_functools.total_ordering
239 @_dataclasses.dataclass(eq
=True, frozen
=True)
240 class PatternOpcode(Opcode
):
241 def __init__(self
, pattern
):
242 if not isinstance(pattern
, str):
243 raise ValueError(pattern
)
245 (value
, mask
) = (0, 0)
246 for symbol
in pattern
:
247 if symbol
not in {"0", "1", "-"}:
248 raise ValueError(pattern
)
249 value |
= (symbol
== "1")
250 mask |
= (symbol
!= "-")
256 value
= Opcode
.Value(value
)
257 mask
= Opcode
.Mask(mask
)
259 return super().__init
__(value
=value
, mask
=mask
)
262 @_dataclasses.dataclass(eq
=True, frozen
=True)
264 class FlagsMeta(type):
279 class Flags(tuple, metaclass
=FlagsMeta
):
280 def __new__(cls
, flags
=frozenset()):
281 flags
= frozenset(flags
)
282 diff
= (flags
- frozenset(cls
))
284 raise ValueError(flags
)
285 return super().__new
__(cls
, sorted(flags
))
289 flags
: Flags
= Flags()
291 function
: _Function
= _Function
.NONE
292 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
293 in1
: _In1Sel
= _In1Sel
.NONE
294 in2
: _In2Sel
= _In2Sel
.NONE
295 in3
: _In3Sel
= _In3Sel
.NONE
296 out
: _OutSel
= _OutSel
.NONE
297 cr_in
: _CRInSel
= _CRInSel
.NONE
298 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
299 cr_out
: _CROutSel
= _CROutSel
.NONE
300 cry_in
: _CryIn
= _CryIn
.ZERO
301 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
302 upd
: _LDSTMode
= _LDSTMode
.NONE
303 Rc
: _RCOE
= _RCOE
.NONE
304 form
: _Form
= _Form
.NONE
306 unofficial
: bool = False
310 "internal op": "intop",
314 "ldst len": "ldst_len",
316 "CONDITIONS": "conditions",
319 def __lt__(self
, other
):
320 if not isinstance(other
, self
.__class
__):
321 return NotImplemented
322 lhs
= (self
.opcode
, self
.comment
)
323 rhs
= (other
.opcode
, other
.comment
)
327 def CSV(cls
, record
, opcode_cls
):
328 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
329 typemap
["opcode"] = opcode_cls
331 if record
["CR in"] == "BA_BB":
332 record
["cr_in"] = "BA"
333 record
["cr_in2"] = "BB"
337 for flag
in frozenset(PPCRecord
.Flags
):
338 if bool(record
.pop(flag
, "")):
340 record
["flags"] = PPCRecord
.Flags(flags
)
342 return dataclass(cls
, record
,
343 keymap
=PPCRecord
.__KEYMAP
,
348 return frozenset(self
.comment
.split("=")[-1].split("/"))
351 class PPCMultiRecord(tuple):
352 def __getattr__(self
, attr
):
355 raise AttributeError(attr
)
356 return getattr(self
[0], attr
)
359 @_dataclasses.dataclass(eq
=True, frozen
=True)
361 class ExtraMap(tuple):
363 @_dataclasses.dataclass(eq
=True, frozen
=True)
365 seltype
: _SelType
= _SelType
.NONE
366 reg
: _Reg
= _Reg
.NONE
369 return f
"{self.seltype.value}:{self.reg.name}"
371 def __new__(cls
, value
="0"):
372 if isinstance(value
, str):
373 def transform(value
):
374 (seltype
, reg
) = value
.split(":")
375 seltype
= _SelType(seltype
)
377 return cls
.Entry(seltype
=seltype
, reg
=reg
)
382 value
= map(transform
, value
.split(";"))
384 return super().__new
__(cls
, value
)
387 return repr(list(self
))
389 def __new__(cls
, value
=tuple()):
393 return super().__new
__(cls
, map(cls
.Extra
, value
))
396 return repr({index
:self
[index
] for index
in range(0, 4)})
399 ptype
: _SVPType
= _SVPType
.NONE
400 etype
: _SVEType
= _SVEType
.NONE
401 msrc
: _SVMaskSrc
= _SVMaskSrc
.NO
# MASK_SRC is active
402 in1
: _In1Sel
= _In1Sel
.NONE
403 in2
: _In2Sel
= _In2Sel
.NONE
404 in3
: _In3Sel
= _In3Sel
.NONE
405 out
: _OutSel
= _OutSel
.NONE
406 out2
: _OutSel
= _OutSel
.NONE
407 cr_in
: _CRInSel
= _CRInSel
.NONE
408 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
409 cr_out
: _CROutSel
= _CROutSel
.NONE
410 extra
: ExtraMap
= ExtraMap()
412 mode
: _SVMode
= _SVMode
.NORMAL
416 "CONDITIONS": "conditions",
425 def CSV(cls
, record
):
426 record
["insn"] = record
["insn"].split("=")[-1]
428 for key
in frozenset({
429 "in1", "in2", "in3", "CR in",
430 "out", "out2", "CR out",
436 if record
["CR in"] == "BA_BB":
437 record
["cr_in"] = "BA"
438 record
["cr_in2"] = "BB"
442 for idx
in range(0, 4):
443 extra
.append(record
.pop(f
"{idx}"))
445 record
["extra"] = cls
.ExtraMap(extra
)
447 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
452 "in1", "in2", "in3", "cr_in", "cr_in2",
453 "out", "out2", "cr_out",
468 for index
in range(0, 4):
469 for entry
in self
.extra
[index
]:
470 extras
[entry
.seltype
][entry
.reg
] = idxmap
[index
]
472 for (seltype
, regs
) in extras
.items():
473 idx
= regs
.get(reg
, _SVExtra
.NONE
)
474 if idx
is not _SVExtra
.NONE
:
475 yield (reg
, seltype
, idx
)
482 # has the word "in", it is a SelType.SRC "out" -> DST
483 # in1/2/3 and CR in are SRC, and must match only against "s:NN"
484 # out/out1 and CR out are DST, and must match only against "d:NN"
485 keytype
= _SelType
.SRC
if ("in" in key
) else _SelType
.DST
486 sel
= sels
[key
] = getattr(self
, key
)
487 reg
= regs
[key
] = _Reg(sel
)
488 seltypes
[key
] = _SelType
.NONE
489 idxs
[key
] = _SVExtra
.NONE
490 for (reg
, seltype
, idx
) in extra(reg
.alias
):
491 if keytype
!= seltype
: # only check SRC-to-SRC and DST-to-DST
493 if idx
!= idxs
[key
] and idxs
[key
] is not _SVExtra
.NONE
:
494 raise ValueError(idx
)
497 seltypes
[key
] = seltype
499 if sels
["cr_in"] is _CRInSel
.BA_BB
:
500 sels
["cr_in"] = _CRIn2Sel
.BA
501 sels
["cr_in2"] = _CRIn2Sel
.BB
502 idxs
["cr_in2"] = idxs
["cr_in"]
503 for key
in ("cr_in", "cr_in2"):
504 regs
[key
] = _Reg(sels
[key
])
505 seltype
[key
] = _SelType
.SRC
512 "seltype": seltypes
[key
],
516 return _types
.MappingProxyType(records
)
518 extra_idx_in1
= property(lambda self
: self
.extras
["in1"]["idx"])
519 extra_idx_in2
= property(lambda self
: self
.extras
["in2"]["idx"])
520 extra_idx_in3
= property(lambda self
: self
.extras
["in3"]["idx"])
521 extra_idx_out
= property(lambda self
: self
.extras
["out"]["idx"])
522 extra_idx_out2
= property(lambda self
: self
.extras
["out2"]["idx"])
523 extra_idx_cr_in
= property(lambda self
: self
.extras
["cr_in"]["idx"])
524 extra_idx_cr_in2
= property(lambda self
: self
.extras
["cr_in2"]["idx"])
525 extra_idx_cr_out
= property(lambda self
: self
.extras
["cr_out"]["idx"])
530 for idx
in range(0, 4):
531 for entry
in self
.extra
[idx
]:
532 if entry
.seltype
is _SelType
.DST
:
533 if extra
is not None:
534 raise ValueError(self
.svp64
)
538 if _RegType(extra
.reg
) not in (_RegType
.CR_3BIT
, _RegType
.CR_5BIT
):
539 raise ValueError(self
.svp64
)
544 def extra_CR_3bit(self
):
545 return (_RegType(self
.extra_CR
.reg
) is _RegType
.CR_3BIT
)
549 def __init__(self
, value
=(0, 32)):
550 if isinstance(value
, str):
551 (start
, end
) = map(int, value
.split(":"))
554 if start
< 0 or end
< 0 or start
>= end
:
555 raise ValueError(value
)
560 return super().__init
__()
563 return (self
.__end
- self
.__start
+ 1)
566 return f
"[{self.__start}:{self.__end}]"
569 yield from range(self
.start
, (self
.end
+ 1))
571 def __reversed__(self
):
572 return tuple(reversed(tuple(self
)))
583 @_dataclasses.dataclass(eq
=True, frozen
=True)
585 class Mode(_enum
.Enum
):
586 INTEGER
= _enum
.auto()
587 PATTERN
= _enum
.auto()
590 def _missing_(cls
, value
):
591 if isinstance(value
, str):
592 return cls
[value
.upper()]
593 return super()._missing
_(value
)
596 def __new__(cls
, value
=None):
597 if isinstance(value
, str):
598 if value
.upper() == "NONE":
601 value
= int(value
, 0)
605 return super().__new
__(cls
, value
)
611 return (bin(self
) if self
else "None")
617 opcode
: IntegerOpcode
= None
618 priority
: Priority
= Priority
.NORMAL
620 def __lt__(self
, other
):
621 if not isinstance(other
, self
.__class
__):
622 return NotImplemented
623 return (self
.priority
< other
.priority
)
626 def CSV(cls
, record
):
627 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
628 if record
["opcode"] == "NONE":
629 typemap
["opcode"] = lambda _
: None
631 return dataclass(cls
, record
, typemap
=typemap
)
635 def __init__(self
, items
):
636 if isinstance(items
, dict):
637 items
= items
.items()
640 (name
, bitrange
) = item
641 return (name
, tuple(bitrange
.values()))
643 self
.__mapping
= dict(map(transform
, items
))
645 return super().__init
__()
648 return repr(self
.__mapping
)
651 yield from self
.__mapping
.items()
653 def __contains__(self
, key
):
654 return self
.__mapping
.__contains
__(key
)
656 def __getitem__(self
, key
):
657 return self
.__mapping
.get(key
, None)
672 def __init__(self
, insn
, operands
):
674 "b": {"target_addr": TargetAddrOperandLI
},
675 "ba": {"target_addr": TargetAddrOperandLI
},
676 "bl": {"target_addr": TargetAddrOperandLI
},
677 "bla": {"target_addr": TargetAddrOperandLI
},
678 "bc": {"target_addr": TargetAddrOperandBD
},
679 "bca": {"target_addr": TargetAddrOperandBD
},
680 "bcl": {"target_addr": TargetAddrOperandBD
},
681 "bcla": {"target_addr": TargetAddrOperandBD
},
682 "addpcis": {"D": DOperandDX
},
683 "fishmv": {"D": DOperandDX
},
684 "fmvis": {"D": DOperandDX
},
687 "SVi": NonZeroOperand
,
688 "SVd": NonZeroOperand
,
689 "SVxd": NonZeroOperand
,
690 "SVyd": NonZeroOperand
,
691 "SVzd": NonZeroOperand
,
693 "D": SignedImmediateOperand
,
697 "SIM": SignedOperand
,
698 "SVD": SignedOperand
,
699 "SVDS": SignedOperand
,
700 "RSp": GPRPairOperand
,
701 "RTp": GPRPairOperand
,
702 "FRAp": FPRPairOperand
,
703 "FRBp": FPRPairOperand
,
704 "FRSp": FPRPairOperand
,
705 "FRTp": FPRPairOperand
,
707 custom_immediates
= {
713 for operand
in operands
:
717 (name
, value
) = operand
.split("=")
718 mapping
[name
] = (StaticOperand
, {
724 if name
.endswith(")"):
725 name
= name
.replace("(", " ").replace(")", "")
726 (imm_name
, _
, name
) = name
.partition(" ")
730 if imm_name
is not None:
731 imm_cls
= custom_immediates
.get(imm_name
, ImmediateOperand
)
733 if insn
in custom_insns
and name
in custom_insns
[insn
]:
734 cls
= custom_insns
[insn
][name
]
735 elif name
in custom_fields
:
736 cls
= custom_fields
[name
]
737 elif name
in _Reg
.__members
__:
739 if reg
in self
.__class
__.__GPR
_PAIRS
:
741 elif reg
in self
.__class
__.__FPR
_PAIRS
:
744 regtype
= _RegType
[name
]
745 if regtype
is _RegType
.GPR
:
747 elif regtype
is _RegType
.FPR
:
749 elif regtype
is _RegType
.CR_3BIT
:
751 elif regtype
is _RegType
.CR_5BIT
:
754 if imm_name
is not None:
755 mapping
[imm_name
] = (imm_cls
, {"name": imm_name
})
756 mapping
[name
] = (cls
, {"name": name
})
760 for (name
, (cls
, kwargs
)) in mapping
.items():
761 kwargs
= dict(kwargs
)
762 kwargs
["name"] = name
763 if issubclass(cls
, StaticOperand
):
764 static
.append((cls
, kwargs
))
765 elif issubclass(cls
, DynamicOperand
):
766 dynamic
.append((cls
, kwargs
))
768 raise ValueError(name
)
770 self
.__mapping
= mapping
771 self
.__static
= tuple(static
)
772 self
.__dynamic
= tuple(dynamic
)
774 return super().__init
__()
777 for (_
, items
) in self
.__mapping
.items():
778 (cls
, kwargs
) = items
782 return self
.__mapping
.__repr
__()
784 def __contains__(self
, key
):
785 return self
.__mapping
.__contains
__(key
)
787 def __getitem__(self
, key
):
788 return self
.__mapping
.__getitem
__(key
)
796 return self
.__dynamic
799 class Arguments(tuple):
800 def __new__(cls
, record
, arguments
, operands
):
801 operands
= iter(tuple(operands
))
802 arguments
= iter(tuple(arguments
))
807 operand
= next(operands
)
808 except StopIteration:
812 argument
= next(arguments
)
813 except StopIteration:
814 raise ValueError("operands count mismatch")
816 if isinstance(operand
, ImmediateOperand
):
817 argument
= argument
.replace("(", " ").replace(")", "")
818 (imm_argument
, _
, argument
) = argument
.partition(" ")
820 (imm_operand
, operand
) = (operand
, next(operands
))
821 except StopIteration:
822 raise ValueError("operands count mismatch")
823 items
.append((imm_argument
, imm_operand
))
824 items
.append((argument
, operand
))
828 except StopIteration:
831 raise ValueError("operands count mismatch")
833 return super().__new
__(cls
, items
)
837 def __init__(self
, iterable
):
838 self
.__pcode
= tuple(iterable
)
839 return super().__init
__()
842 yield from self
.__pcode
845 return self
.__pcode
.__repr
__()
848 @_dataclasses.dataclass(eq
=True, frozen
=True)
849 class MarkdownRecord
:
854 @_dataclasses.dataclass(eq
=True, frozen
=True)
858 _In1Sel
, _In2Sel
, _In3Sel
, _CRInSel
, _CRIn2Sel
,
866 @_functools.total_ordering
867 @_dataclasses.dataclass(eq
=True, frozen
=True)
874 svp64
: SVP64Record
= None
876 def visit(self
, handler
, matcher
, depth
):
877 if matcher(node
=self
, depth
=depth
):
878 with
handler(node
=self
, depth
=depth
):
879 for (name
, fields
) in self
.extras
.items():
880 extra
= Extra(name
=name
, **fields
)
881 extra
.visit(depth
=(depth
+ 1),
882 handler
=handler
, matcher
=matcher
)
886 if self
.svp64
is not None:
887 return self
.svp64
.extras
889 return _types
.MappingProxyType({})
893 return self
.mdwn
.pcode
895 def __lt__(self
, other
):
896 if not isinstance(other
, Record
):
897 return NotImplemented
898 lhs
= (min(self
.opcodes
), self
.name
)
899 rhs
= (min(other
.opcodes
), other
.name
)
904 return (self
.static_operands
+ self
.dynamic_operands
)
907 def static_operands(self
):
909 operands
.append(POStaticOperand(record
=self
, value
=self
.PO
))
911 operands
.append(XOStaticOperand(
913 value
=ppc
.opcode
.value
,
914 span
=self
.section
.bitsel
,
916 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
917 operands
.append(cls(record
=self
, **kwargs
))
918 return tuple(operands
)
921 def dynamic_operands(self
):
923 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
924 operands
.append(cls(record
=self
, **kwargs
))
925 return tuple(operands
)
930 return int("".join(str(int(mapping
[bit
])) \
931 for bit
in sorted(mapping
)), 2)
933 def PO_XO(value
, mask
, opcode
, bits
):
936 for (src
, dst
) in enumerate(reversed(bits
)):
937 value
[dst
] = ((opcode
.value
& (1 << src
)) != 0)
938 mask
[dst
] = ((opcode
.mask
& (1 << src
)) != 0)
941 def PO(value
, mask
, opcode
, bits
):
942 return PO_XO(value
=value
, mask
=mask
, opcode
=opcode
, bits
=bits
)
944 def XO(value
, mask
, opcode
, bits
):
945 (value
, mask
) = PO_XO(value
=value
, mask
=mask
,
946 opcode
=opcode
, bits
=bits
)
947 for (op_cls
, op_kwargs
) in self
.mdwn
.operands
.static
:
948 operand
= op_cls(record
=self
, **op_kwargs
)
949 for (src
, dst
) in enumerate(reversed(operand
.span
)):
950 value
[dst
] = ((operand
.value
& (1 << src
)) != 0)
955 value
= {bit
:False for bit
in range(32)}
956 mask
= {bit
:False for bit
in range(32)}
957 if self
.section
.opcode
is not None:
958 (value
, mask
) = PO(value
=value
, mask
=mask
,
959 opcode
=self
.section
.opcode
, bits
=range(0, 6))
961 pairs
.append(XO(value
=value
, mask
=mask
,
962 opcode
=ppc
.opcode
, bits
=self
.section
.bitsel
))
965 for (value
, mask
) in pairs
:
966 value
= Opcode
.Value(binary(value
))
967 mask
= Opcode
.Mask(binary(mask
))
968 result
.append(Opcode(value
=value
, mask
=mask
))
974 opcode
= self
.section
.opcode
976 opcode
= self
.ppc
[0].opcode
977 if isinstance(opcode
, PatternOpcode
):
978 value
= int(opcode
.value
)
979 bits
= opcode
.value
.bit_length()
980 return int(_SelectableInt(value
=value
, bits
=bits
)[0:6])
982 return int(opcode
.value
)
986 return tuple(ppc
.opcode
for ppc
in self
.ppc
)
988 def match(self
, key
):
989 for opcode
in self
.opcodes
:
990 if opcode
.match(key
):
997 return self
.svp64
.mode
1017 if self
.svp64
is None:
1023 return self
.ppc
.cr_in
1027 return self
.ppc
.cr_in2
1031 return self
.ppc
.cr_out
1033 ptype
= property(lambda self
: self
.svp64
.ptype
)
1034 etype
= property(lambda self
: self
.svp64
.etype
)
1036 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
1037 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
1038 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
1039 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
1040 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
1041 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
1042 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
1043 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
1045 def __contains__(self
, key
):
1046 return self
.mdwn
.operands
.__contains
__(key
)
1048 def __getitem__(self
, key
):
1049 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
1050 return cls(record
=self
, **kwargs
)
1054 if "Rc" not in self
:
1056 return self
["Rc"].value
1060 def __init__(self
, record
, name
):
1061 self
.__record
= record
1065 yield ("record", self
.record
)
1066 yield ("name", self
.__name
)
1069 return f
"{self.__class__.__name__}({self.name})"
1077 return self
.__record
1081 return self
.record
.fields
[self
.name
]
1083 def assemble(self
, insn
):
1084 raise NotImplementedError()
1086 def disassemble(self
, insn
,
1087 style
=Style
.NORMAL
, indent
=""):
1088 raise NotImplementedError()
1091 class DynamicOperand(Operand
):
1092 def assemble(self
, insn
, value
):
1094 if isinstance(value
, str):
1095 value
= int(value
, 0)
1097 raise ValueError("signed operands not allowed")
1100 def disassemble(self
, insn
,
1101 style
=Style
.NORMAL
, indent
=""):
1105 if style
>= Style
.VERBOSE
:
1106 span
= map(str, span
)
1107 yield f
"{indent}{self.name}"
1108 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1109 yield f
"{indent}{indent}{', '.join(span)}"
1111 yield str(int(value
))
1114 class SignedOperand(DynamicOperand
):
1115 def assemble(self
, insn
, value
):
1116 if isinstance(value
, str):
1117 value
= int(value
, 0)
1118 return super().assemble(value
=value
, insn
=insn
)
1120 def assemble(self
, insn
, value
):
1122 if isinstance(value
, str):
1123 value
= int(value
, 0)
1126 def disassemble(self
, insn
,
1127 style
=Style
.NORMAL
, indent
=""):
1129 value
= insn
[span
].to_signed_int()
1130 sign
= "-" if (value
< 0) else ""
1133 if style
>= Style
.VERBOSE
:
1134 span
= map(str, span
)
1135 yield f
"{indent}{self.name}"
1136 yield f
"{indent}{indent}{sign}{value}"
1137 yield f
"{indent}{indent}{', '.join(span)}"
1139 yield f
"{sign}{value}"
1142 class StaticOperand(Operand
):
1143 def __init__(self
, record
, name
, value
):
1144 self
.__value
= value
1145 return super().__init
__(record
=record
, name
=name
)
1148 yield ("value", self
.__value
)
1149 yield from super().__iter
__()
1152 return f
"{self.__class__.__name__}({self.name}, value={self.value})"
1158 def assemble(self
, insn
):
1159 insn
[self
.span
] = self
.value
1161 def disassemble(self
, insn
,
1162 style
=Style
.NORMAL
, indent
=""):
1166 if style
>= Style
.VERBOSE
:
1167 span
= map(str, span
)
1168 yield f
"{indent}{self.name}"
1169 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1170 yield f
"{indent}{indent}{', '.join(span)}"
1172 yield str(int(value
))
1175 class SpanStaticOperand(StaticOperand
):
1176 def __init__(self
, record
, name
, value
, span
):
1177 self
.__span
= tuple(span
)
1178 return super().__init
__(record
=record
, name
=name
, value
=value
)
1181 yield ("span", self
.__span
)
1182 yield from super().__iter
__()
1189 class POStaticOperand(SpanStaticOperand
):
1190 def __init__(self
, record
, value
):
1191 return super().__init
__(record
=record
, name
="PO",
1192 value
=value
, span
=range(0, 6))
1195 for (key
, value
) in super().__iter
__():
1196 if key
not in {"name", "span"}:
1200 class XOStaticOperand(SpanStaticOperand
):
1201 def __init__(self
, record
, value
, span
):
1202 bits
= record
.section
.bitsel
1203 value
= _SelectableInt(value
=value
, bits
=len(bits
))
1204 span
= dict(zip(bits
, range(len(bits
))))
1205 span_rev
= {value
:key
for (key
, value
) in span
.items()}
1207 # This part is tricky: we cannot use record.operands,
1208 # as this code is called by record.static_operands method.
1209 for (cls
, kwargs
) in record
.mdwn
.operands
:
1210 operand
= cls(record
=record
, **kwargs
)
1211 for idx
in operand
.span
:
1212 rev
= span
.pop(idx
, None)
1214 span_rev
.pop(rev
, None)
1216 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1217 span
= tuple(span
.keys())
1219 return super().__init
__(record
=record
, name
="XO",
1220 value
=value
, span
=span
)
1223 for (key
, value
) in super().__iter
__():
1224 if key
not in {"name"}:
1228 class ImmediateOperand(DynamicOperand
):
1232 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1236 class NonZeroOperand(DynamicOperand
):
1237 def assemble(self
, insn
, value
):
1238 if isinstance(value
, str):
1239 value
= int(value
, 0)
1240 if not isinstance(value
, int):
1241 raise ValueError("non-integer operand")
1243 raise ValueError("non-zero operand")
1245 return super().assemble(value
=value
, insn
=insn
)
1247 def disassemble(self
, insn
,
1248 style
=Style
.NORMAL
, indent
=""):
1252 if style
>= Style
.VERBOSE
:
1253 span
= map(str, span
)
1254 yield f
"{indent}{self.name}"
1255 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1256 yield f
"{indent}{indent}{', '.join(span)}"
1258 yield str(int(value
) + 1)
1261 class ExtendableOperand(DynamicOperand
):
1262 def sv_spec_enter(self
, value
, span
):
1263 return (value
, span
)
1265 def sv_spec(self
, insn
):
1269 span
= tuple(map(str, span
))
1271 if isinstance(insn
, SVP64Instruction
):
1272 (origin_value
, origin_span
) = (value
, span
)
1273 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1275 for extra_idx
in self
.extra_idx
:
1276 if self
.record
.etype
is _SVEType
.EXTRA3
:
1277 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1278 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1279 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1281 raise ValueError(self
.record
.etype
)
1284 vector
= bool(spec
[0])
1285 spec_span
= spec
.__class
__
1286 if self
.record
.etype
is _SVEType
.EXTRA3
:
1287 spec_span
= tuple(map(str, spec_span
[1, 2]))
1289 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1290 spec_span
= tuple(map(str, spec_span
[1,]))
1291 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1294 spec_span
= (spec_span
+ ("{0}",))
1296 spec_span
= (("{0}",) + spec_span
)
1298 raise ValueError(self
.record
.etype
)
1300 vector_shift
= (2 + (5 - value
.bits
))
1301 scalar_shift
= value
.bits
1302 spec_shift
= (5 - value
.bits
)
1304 bits
= (len(span
) + len(spec_span
))
1305 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1306 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1308 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1309 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1311 value
= ((spec
<< scalar_shift
) | value
)
1312 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1314 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1315 origin_value
=origin_value
, origin_span
=origin_span
)
1317 return (vector
, value
, span
)
1319 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1320 return (value
, span
)
1323 def extra_idx(self
):
1324 for (key
, record
) in self
.record
.svp64
.extras
.items():
1325 if record
["reg"].alias
is self
.extra_reg
.alias
:
1329 def extra_reg(self
):
1330 return _Reg(self
.name
)
1332 def remap(self
, value
, vector
):
1333 raise NotImplementedError()
1335 def assemble(self
, value
, insn
, prefix
):
1338 if isinstance(value
, str):
1339 value
= value
.lower()
1340 if value
.startswith("%"):
1342 if value
.startswith("*"):
1343 if not isinstance(insn
, SVP64Instruction
):
1344 raise ValueError(value
)
1347 if value
.startswith(prefix
):
1348 if (self
.extra_reg
.or_zero
and (value
== f
"{prefix}0")):
1349 raise ValueError(value
)
1350 value
= value
[len(prefix
):]
1351 value
= int(value
, 0)
1353 if isinstance(insn
, SVP64Instruction
):
1354 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1356 for extra_idx
in self
.extra_idx
:
1357 if self
.record
.etype
is _SVEType
.EXTRA3
:
1358 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1359 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1360 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1362 raise ValueError(self
.record
.etype
)
1364 return super().assemble(value
=value
, insn
=insn
)
1366 def disassemble(self
, insn
,
1367 style
=Style
.NORMAL
, prefix
="", indent
=""):
1368 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1370 if (self
.extra_reg
.or_zero
and (value
== 0)):
1373 if style
>= Style
.VERBOSE
:
1374 mode
= "vector" if vector
else "scalar"
1375 yield f
"{indent}{self.name} ({mode})"
1376 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1377 yield f
"{indent}{indent}{', '.join(span)}"
1378 if isinstance(insn
, SVP64Instruction
):
1379 for extra_idx
in frozenset(self
.extra_idx
):
1380 if self
.record
.etype
is _SVEType
.NONE
:
1381 yield f
"{indent}{indent}extra[none]"
1383 etype
= repr(self
.record
.etype
).lower()
1384 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1386 vector
= "*" if vector
else ""
1387 yield f
"{vector}{prefix}{int(value)}"
1390 class SimpleRegisterOperand(ExtendableOperand
):
1391 def remap(self
, value
, vector
):
1393 extra
= (value
& 0b11)
1394 value
= (value
>> 2)
1396 extra
= (value
>> 5)
1397 value
= (value
& 0b11111)
1399 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1400 # (and shrink to a single bit if ok)
1401 if self
.record
.etype
is _SVEType
.EXTRA2
:
1403 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1404 assert (extra
& 0b01) == 0, \
1405 ("vector field %s cannot fit into EXTRA2" % value
)
1406 extra
= (0b10 |
(extra
>> 1))
1408 # range is r0-r63 in increments of 1
1409 assert (extra
>> 1) == 0, \
1410 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1412 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1414 # EXTRA3 vector bit needs marking
1417 raise ValueError(self
.record
.etype
)
1419 return (value
, extra
)
1422 class GPROperand(SimpleRegisterOperand
):
1423 def assemble(self
, insn
, value
):
1424 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1426 def disassemble(self
, insn
,
1427 style
=Style
.NORMAL
, indent
=""):
1428 prefix
= "" if (style
<= Style
.SHORT
) else "r"
1429 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1430 style
=style
, indent
=indent
)
1433 class GPRPairOperand(GPROperand
):
1437 class FPROperand(SimpleRegisterOperand
):
1438 def assemble(self
, insn
, value
):
1439 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1441 def disassemble(self
, insn
,
1442 style
=Style
.NORMAL
, indent
=""):
1443 prefix
= "" if (style
<= Style
.SHORT
) else "f"
1444 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1445 style
=style
, indent
=indent
)
1448 class FPRPairOperand(FPROperand
):
1452 class ConditionRegisterFieldOperand(ExtendableOperand
):
1453 def pattern(name_pattern
):
1454 (name
, pattern
) = name_pattern
1455 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1464 CR
= r
"(?:CR|cr)([0-9]+)"
1466 BIT
= rf
"({'|'.join(CONDS.keys())})"
1467 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1468 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1469 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1470 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1471 XCR
= fr
"{CR}\.{BIT}"
1472 PATTERNS
= tuple(map(pattern
, (
1477 ("BIT+CR", (LBIT
+ CR
)),
1478 ("CR+BIT", (CR
+ RBIT
)),
1479 ("BIT+CR*N", (LBIT
+ CRN
)),
1480 ("CR*N+BIT", (CRN
+ RBIT
)),
1481 ("BIT+N*CR", (LBIT
+ NCR
)),
1482 ("N*CR+BIT", (NCR
+ RBIT
)),
1485 def remap(self
, value
, vector
, regtype
):
1486 if regtype
is _RegType
.CR_5BIT
:
1487 subvalue
= (value
& 0b11)
1491 extra
= (value
& 0b1111)
1494 extra
= (value
>> 3)
1497 if self
.record
.etype
is _SVEType
.EXTRA2
:
1499 assert (extra
& 0b111) == 0, \
1500 "vector CR cannot fit into EXTRA2"
1501 extra
= (0b10 |
(extra
>> 3))
1503 assert (extra
>> 1) == 0, \
1504 "scalar CR cannot fit into EXTRA2"
1506 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1508 assert (extra
& 0b11) == 0, \
1509 "vector CR cannot fit into EXTRA3"
1510 extra
= (0b100 |
(extra
>> 2))
1512 assert (extra
>> 2) == 0, \
1513 "scalar CR cannot fit into EXTRA3"
1516 if regtype
is _RegType
.CR_5BIT
:
1517 value
= ((value
<< 2) | subvalue
)
1519 return (value
, extra
)
1521 def assemble(self
, insn
, value
):
1522 if isinstance(value
, str):
1525 if value
.startswith("*"):
1526 if not isinstance(insn
, SVP64Instruction
):
1527 raise ValueError(value
)
1531 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1532 match
= pattern
.match(value
)
1533 if match
is not None:
1534 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1535 values
= match
.groups()
1536 match
= dict(zip(keys
, values
))
1537 CR
= int(match
["CR"])
1541 N
= int(match
.get("N", "1"))
1542 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1543 value
= ((CR
* N
) + BIT
)
1550 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1552 def disassemble(self
, insn
,
1553 style
=Style
.NORMAL
, prefix
="", indent
=""):
1554 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1556 if style
>= Style
.VERBOSE
:
1557 mode
= "vector" if vector
else "scalar"
1558 yield f
"{indent}{self.name} ({mode})"
1559 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1560 yield f
"{indent}{indent}{', '.join(span)}"
1561 if isinstance(insn
, SVP64Instruction
):
1562 for extra_idx
in frozenset(self
.extra_idx
):
1563 if self
.record
.etype
is _SVEType
.NONE
:
1564 yield f
"{indent}{indent}extra[none]"
1566 etype
= repr(self
.record
.etype
).lower()
1567 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1569 vector
= "*" if vector
else ""
1570 CR
= int(value
>> 2)
1572 cond
= ("lt", "gt", "eq", "so")[CC
]
1573 if style
>= Style
.NORMAL
:
1575 if isinstance(insn
, SVP64Instruction
):
1576 yield f
"{vector}cr{CR}.{cond}"
1578 yield f
"4*cr{CR}+{cond}"
1582 yield f
"{vector}{prefix}{int(value)}"
1585 class CR3Operand(ConditionRegisterFieldOperand
):
1586 def remap(self
, value
, vector
):
1587 return super().remap(value
=value
, vector
=vector
,
1588 regtype
=_RegType
.CR_3BIT
)
1591 class CR5Operand(ConditionRegisterFieldOperand
):
1592 def remap(self
, value
, vector
):
1593 return super().remap(value
=value
, vector
=vector
,
1594 regtype
=_RegType
.CR_5BIT
)
1596 def sv_spec_enter(self
, value
, span
):
1597 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1598 return (value
, span
)
1600 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1601 value
= _selectconcat(value
, origin_value
[3:5])
1603 return (value
, span
)
1606 class EXTSOperand(SignedOperand
):
1607 field
: str # real name to report
1608 nz
: int = 0 # number of zeros
1609 fmt
: str = "d" # integer formatter
1611 def __init__(self
, record
, name
, field
, nz
=0, fmt
="d"):
1612 self
.__field
= field
1615 return super().__init
__(record
=record
, name
=name
)
1631 return self
.record
.fields
[self
.field
]
1633 def assemble(self
, insn
, value
):
1635 if isinstance(value
, str):
1636 value
= int(value
, 0)
1637 insn
[span
] = (value
>> self
.nz
)
1639 def disassemble(self
, insn
,
1640 style
=Style
.NORMAL
, indent
=""):
1642 value
= insn
[span
].to_signed_int()
1643 sign
= "-" if (value
< 0) else ""
1644 value
= (abs(value
) << self
.nz
)
1646 if style
>= Style
.VERBOSE
:
1647 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1648 zeros
= ("0" * self
.nz
)
1649 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1650 yield f
"{indent * 1}{hint}"
1651 yield f
"{indent * 2}{self.field}"
1652 yield f
"{indent * 3}{sign}{value:{self.fmt}}"
1653 yield f
"{indent * 3}{', '.join(span)}"
1655 yield f
"{sign}{value:{self.fmt}}"
1658 class TargetAddrOperand(EXTSOperand
):
1659 def __init__(self
, record
, name
, field
):
1660 return super().__init
__(record
=record
, name
=name
, field
=field
,
1664 class TargetAddrOperandLI(TargetAddrOperand
):
1665 def __init__(self
, record
, name
):
1666 return super().__init
__(record
=record
, name
=name
, field
="LI")
1669 class TargetAddrOperandBD(TargetAddrOperand
):
1670 def __init__(self
, record
, name
):
1671 return super().__init
__(record
=record
, name
=name
, field
="BD")
1674 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1675 def __init__(self
, record
, name
):
1676 return super().__init
__(record
=record
, name
=name
, field
="DS", nz
=2)
1679 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1680 def __init__(self
, record
, name
):
1681 return super().__init
__(record
=record
, name
=name
, field
="DQ", nz
=4)
1684 class DOperandDX(SignedOperand
):
1687 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1688 operands
= map(cls
, ("d0", "d1", "d2"))
1689 spans
= map(lambda operand
: operand
.span
, operands
)
1690 return sum(spans
, tuple())
1692 def disassemble(self
, insn
,
1693 style
=Style
.NORMAL
, indent
=""):
1695 value
= insn
[span
].to_signed_int()
1696 sign
= "-" if (value
< 0) else ""
1699 if style
>= Style
.VERBOSE
:
1706 for (subname
, subspan
) in mapping
.items():
1707 operand
= DynamicOperand(name
=subname
)
1709 span
= map(str, span
)
1710 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1711 yield f
"{indent}{indent}{indent}{sign}{value}"
1712 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1714 yield f
"{sign}{value}"
1717 class Instruction(_Mapping
):
1719 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1720 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1721 raise ValueError(bits
)
1723 if isinstance(value
, bytes
):
1724 if ((len(value
) * 8) != bits
):
1725 raise ValueError(f
"bit length mismatch")
1726 value
= int.from_bytes(value
, byteorder
=byteorder
)
1728 if isinstance(value
, int):
1729 value
= _SelectableInt(value
=value
, bits
=bits
)
1730 elif isinstance(value
, Instruction
):
1731 value
= value
.storage
1733 if not isinstance(value
, _SelectableInt
):
1734 raise ValueError(value
)
1737 if len(value
) != bits
:
1738 raise ValueError(value
)
1740 value
= _SelectableInt(value
=value
, bits
=bits
)
1742 return cls(storage
=value
)
1745 return hash(int(self
))
1747 def __getitem__(self
, key
):
1748 return self
.storage
.__getitem
__(key
)
1750 def __setitem__(self
, key
, value
):
1751 return self
.storage
.__setitem
__(key
, value
)
1753 def bytes(self
, byteorder
="little"):
1754 nr_bytes
= (len(self
.__class
__) // 8)
1755 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1758 def record(cls
, db
, entry
):
1761 raise KeyError(entry
)
1765 def operands(cls
, record
):
1766 yield from record
.operands
1769 def static_operands(cls
, record
):
1770 return filter(lambda operand
: isinstance(operand
, StaticOperand
),
1771 cls
.operands(record
=record
))
1774 def dynamic_operands(cls
, record
):
1775 return filter(lambda operand
: isinstance(operand
, DynamicOperand
),
1776 cls
.operands(record
=record
))
1778 def spec(self
, record
, prefix
):
1779 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1780 self
.spec_dynamic_operands(record
=record
)))
1782 static_operands
= []
1783 for (name
, value
) in self
.spec_static_operands(record
=record
):
1784 static_operands
.append(f
"{name}={value}")
1787 if dynamic_operands
:
1789 operands
+= ",".join(dynamic_operands
)
1792 operands
+= " ".join(static_operands
)
1794 return f
"{prefix}{record.name}{operands}"
1796 def spec_static_operands(self
, record
):
1797 for operand
in self
.static_operands(record
=record
):
1798 if not isinstance(operand
, (POStaticOperand
, XOStaticOperand
)):
1799 yield (operand
.name
, operand
.value
)
1801 def spec_dynamic_operands(self
, record
, style
=Style
.NORMAL
):
1805 for operand
in self
.dynamic_operands(record
=record
):
1807 value
= " ".join(operand
.disassemble(insn
=self
,
1808 style
=min(style
, Style
.NORMAL
)))
1810 name
= f
"{imm_name}({name})"
1811 value
= f
"{imm_value}({value})"
1813 if isinstance(operand
, ImmediateOperand
):
1821 def assemble(cls
, record
, arguments
=None):
1822 if arguments
is None:
1825 insn
= cls
.integer(value
=0)
1827 for operand
in cls
.static_operands(record
=record
):
1828 operand
.assemble(insn
=insn
)
1830 arguments
= Arguments(record
=record
,
1831 arguments
=arguments
, operands
=cls
.dynamic_operands(record
=record
))
1832 for (value
, operand
) in arguments
:
1833 operand
.assemble(insn
=insn
, value
=value
)
1837 def disassemble(self
, record
,
1839 style
=Style
.NORMAL
):
1840 raise NotImplementedError()
1843 class WordInstruction(Instruction
):
1844 _
: _Field
= range(0, 32)
1845 PO
: _Field
= range(0, 6)
1848 def integer(cls
, value
, byteorder
="little"):
1849 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1854 for idx
in range(32):
1855 bit
= int(self
[idx
])
1857 return "".join(map(str, bits
))
1859 def disassemble(self
, record
,
1861 style
=Style
.NORMAL
):
1862 if style
<= Style
.SHORT
:
1865 blob
= self
.bytes(byteorder
=byteorder
)
1866 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1870 yield f
"{blob}.long 0x{int(self):08x}"
1873 # awful temporary hack: workaround for ld-update
1874 # https://bugs.libre-soc.org/show_bug.cgi?id=1056#c2
1875 # XXX TODO must check that *EXTENDED* RA != extended-RT
1876 if (record
.svp64
is not None and
1877 record
.mode
== _SVMode
.LDST_IMM
and
1878 'u' in record
.name
):
1879 yield f
"{blob}.long 0x{int(self):08x}"
1883 if style
is Style
.LEGACY
:
1885 for operand
in self
.dynamic_operands(record
=record
):
1886 if isinstance(operand
, (GPRPairOperand
, FPRPairOperand
)):
1889 if style
is Style
.LEGACY
and (paired
or record
.ppc
.unofficial
):
1890 yield f
"{blob}.long 0x{int(self):08x}"
1892 operands
= tuple(map(_operator
.itemgetter(1),
1893 self
.spec_dynamic_operands(record
=record
, style
=style
)))
1895 operands
= ",".join(operands
)
1896 yield f
"{blob}{record.name} {operands}"
1898 yield f
"{blob}{record.name}"
1900 if style
>= Style
.VERBOSE
:
1902 binary
= self
.binary
1903 spec
= self
.spec(record
=record
, prefix
="")
1904 yield f
"{indent}spec"
1905 yield f
"{indent}{indent}{spec}"
1906 yield f
"{indent}pcode"
1907 for stmt
in record
.mdwn
.pcode
:
1908 yield f
"{indent}{indent}{stmt}"
1909 yield f
"{indent}binary"
1910 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1911 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1912 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1913 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1914 yield f
"{indent}opcodes"
1915 for opcode
in record
.opcodes
:
1916 yield f
"{indent}{indent}{opcode!r}"
1917 for operand
in self
.operands(record
=record
):
1918 yield from operand
.disassemble(insn
=self
,
1919 style
=style
, indent
=indent
)
1923 class PrefixedInstruction(Instruction
):
1924 class Prefix(WordInstruction
.remap(range(0, 32))):
1927 class Suffix(WordInstruction
.remap(range(32, 64))):
1930 _
: _Field
= range(64)
1936 def integer(cls
, value
, byteorder
="little"):
1937 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
1940 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
1941 def transform(value
):
1942 return WordInstruction
.integer(value
=value
,
1943 byteorder
=byteorder
)[0:32]
1945 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
1946 value
= _selectconcat(prefix
, suffix
)
1948 return super().integer(bits
=64, value
=value
)
1951 class Mode(_Mapping
):
1952 _
: _Field
= range(0, 5)
1953 sel
: _Field
= (0, 1)
1956 class ExtraRM(_Mapping
):
1957 _
: _Field
= range(0, 9)
1960 class Extra2RM(ExtraRM
):
1961 idx0
: _Field
= range(0, 2)
1962 idx1
: _Field
= range(2, 4)
1963 idx2
: _Field
= range(4, 6)
1964 idx3
: _Field
= range(6, 8)
1966 def __getitem__(self
, key
):
1972 _SVExtra
.Idx0
: self
.idx0
,
1973 _SVExtra
.Idx1
: self
.idx1
,
1974 _SVExtra
.Idx2
: self
.idx2
,
1975 _SVExtra
.Idx3
: self
.idx3
,
1978 def __setitem__(self
, key
, value
):
1979 self
[key
].assign(value
)
1982 class Extra3RM(ExtraRM
):
1983 idx0
: _Field
= range(0, 3)
1984 idx1
: _Field
= range(3, 6)
1985 idx2
: _Field
= range(6, 9)
1987 def __getitem__(self
, key
):
1992 _SVExtra
.Idx0
: self
.idx0
,
1993 _SVExtra
.Idx1
: self
.idx1
,
1994 _SVExtra
.Idx2
: self
.idx2
,
1997 def __setitem__(self
, key
, value
):
1998 self
[key
].assign(value
)
2001 class BaseRM(_Mapping
):
2002 _
: _Field
= range(24)
2003 mmode
: _Field
= (0,)
2004 mask
: _Field
= range(1, 4)
2005 elwidth
: _Field
= range(4, 6)
2006 ewsrc
: _Field
= range(6, 8)
2007 subvl
: _Field
= range(8, 10)
2008 mode
: Mode
.remap(range(19, 24))
2009 smask_extra322
: _Field
= (6,7,18,) # LDST_IDX is EXTRA332
2010 smask
: _Field
= range(16, 19) # everything else use this
2011 extra
: ExtraRM
.remap(range(10, 19))
2012 extra2
: Extra2RM
.remap(range(10, 19))
2013 extra3
: Extra3RM
.remap(range(10, 19))
2014 # XXX extra332 = (extra3[0], extra3[1], extra2[3])
2016 def specifiers(self
, record
):
2017 subvl
= int(self
.subvl
)
2025 def disassemble(self
, style
=Style
.NORMAL
):
2026 if style
>= Style
.VERBOSE
:
2028 for (name
, span
) in self
.traverse(path
="RM"):
2029 value
= self
.storage
[span
]
2031 yield f
"{indent}{int(value):0{value.bits}b}"
2032 yield f
"{indent}{', '.join(map(str, span))}"
2035 class FFRc1BaseRM(BaseRM
):
2036 def specifiers(self
, record
, mode
):
2037 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
2038 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
2039 mask
= int(_selectconcat(CR
, inv
))
2040 predicate
= PredicateBaseRM
.predicate(True, mask
)
2041 yield f
"{mode}={predicate}"
2043 yield from super().specifiers(record
=record
)
2046 class FFRc0BaseRM(BaseRM
):
2047 def specifiers(self
, record
, mode
):
2049 inv
= "~" if self
.inv
else ""
2050 yield f
"{mode}={inv}RC1"
2052 yield from super().specifiers(record
=record
)
2055 class SatBaseRM(BaseRM
):
2056 def specifiers(self
, record
):
2062 yield from super().specifiers(record
=record
)
2065 class ZZBaseRM(BaseRM
):
2066 def specifiers(self
, record
):
2070 yield from super().specifiers(record
=record
)
2073 class ZZCombinedBaseRM(BaseRM
):
2074 def specifiers(self
, record
):
2075 if self
.sz
and self
.dz
:
2082 yield from super().specifiers(record
=record
)
2085 class DZBaseRM(BaseRM
):
2086 def specifiers(self
, record
):
2090 yield from super().specifiers(record
=record
)
2093 class SZBaseRM(BaseRM
):
2094 def specifiers(self
, record
):
2098 yield from super().specifiers(record
=record
)
2101 class MRBaseRM(BaseRM
):
2102 def specifiers(self
, record
):
2108 yield from super().specifiers(record
=record
)
2111 class ElsBaseRM(BaseRM
):
2112 def specifiers(self
, record
):
2116 yield from super().specifiers(record
=record
)
2119 class WidthBaseRM(BaseRM
):
2121 def width(FP
, width
):
2130 width
= ("fp" + width
)
2133 def specifiers(self
, record
):
2134 # elwidths: use "w=" if same otherwise dw/sw
2135 # FIXME this should consider FP instructions
2137 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
2138 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2139 if record
.svp64
.mode
is _SVMode
.CROP
:
2143 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2152 yield from super().specifiers(record
=record
)
2155 class PredicateBaseRM(BaseRM
):
2157 def predicate(CR
, mask
):
2160 (False, 0b001): "1<<r3",
2161 (False, 0b010): "r3",
2162 (False, 0b011): "~r3",
2163 (False, 0b100): "r10",
2164 (False, 0b101): "~r10",
2165 (False, 0b110): "r30",
2166 (False, 0b111): "~r30",
2168 (True, 0b000): "lt",
2169 (True, 0b001): "ge",
2170 (True, 0b010): "gt",
2171 (True, 0b011): "le",
2172 (True, 0b100): "eq",
2173 (True, 0b101): "ne",
2174 (True, 0b110): "so",
2175 (True, 0b111): "ns",
2178 def specifiers(self
, record
):
2179 # predication - single and twin
2180 # use "m=" if same otherwise sm/dm
2181 CR
= (int(self
.mmode
) == 1)
2182 mask
= int(self
.mask
)
2183 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
2184 if record
.svp64
.ptype
is _SVPType
.P2
:
2185 # LDST_IDX smask moving to extra322 but not straight away (False)
2186 if False and record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2187 smask
= int(self
.smask_extra332
)
2189 smask
= int(self
.smask
)
2190 sm
= PredicateBaseRM
.predicate(CR
, smask
)
2199 yield from super().specifiers(record
=record
)
2202 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
2206 class SEABaseRM(BaseRM
):
2207 def specifiers(self
, record
):
2211 yield from super().specifiers(record
=record
)
2214 class VLiBaseRM(BaseRM
):
2215 def specifiers(self
, record
):
2219 yield from super().specifiers(record
=record
)
2222 class NormalBaseRM(PredicateWidthBaseRM
):
2225 https://libre-soc.org/openpower/sv/normal/
2230 class NormalSimpleRM(ZZCombinedBaseRM
, NormalBaseRM
):
2231 """normal: simple mode"""
2235 def specifiers(self
, record
):
2236 yield from super().specifiers(record
=record
)
2239 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
2240 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
2244 class NormalFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, NormalBaseRM
):
2245 """normal: Rc=1: ffirst CR sel"""
2248 CR
: BaseRM
.mode
[3, 4]
2250 def specifiers(self
, record
):
2251 yield from super().specifiers(record
=record
, mode
="ff")
2254 class NormalFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
2255 """normal: Rc=0: ffirst z/nonz"""
2260 def specifiers(self
, record
):
2261 yield from super().specifiers(record
=record
, mode
="ff")
2264 class NormalSatRM(SatBaseRM
, ZZCombinedBaseRM
, NormalBaseRM
):
2265 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2271 class NormalRM(NormalBaseRM
):
2272 simple
: NormalSimpleRM
2274 ffrc1
: NormalFFRc1RM
2275 ffrc0
: NormalFFRc0RM
2279 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2281 LD/ST Immediate mode
2282 https://libre-soc.org/openpower/sv/ldst/
2287 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2288 """ld/st immediate: simple mode"""
2289 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2290 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2296 def specifiers(self
, record
):
2302 yield from super().specifiers(record
=record
)
2305 class LDSTFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2306 """ld/st immediate&indexed: Rc=1: ffirst CR sel"""
2309 CR
: BaseRM
.mode
[3, 4]
2311 def specifiers(self
, record
):
2312 yield from super().specifiers(record
=record
, mode
="ff")
2315 class LDSTFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2316 """ld/st immediate&indexed: Rc=0: ffirst z/nonz"""
2321 def specifiers(self
, record
):
2322 yield from super().specifiers(record
=record
, mode
="ff")
2325 class LDSTImmRM(LDSTImmBaseRM
):
2326 simple
: LDSTImmSimpleRM
2331 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2334 https://libre-soc.org/openpower/sv/ldst/
2339 class LDSTIdxSimpleRM(SEABaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2340 """ld/st index: simple mode (includes element-strided and Signed-EA)"""
2341 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2348 def specifiers(self
, record
):
2354 yield from super().specifiers(record
=record
)
2357 class LDSTIdxRM(LDSTIdxBaseRM
):
2358 simple
: LDSTIdxSimpleRM
2364 class CROpBaseRM(BaseRM
):
2367 https://libre-soc.org/openpower/sv/cr_ops/
2372 class CROpSimpleRM(PredicateBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2373 """crop: simple mode"""
2378 def specifiers(self
, record
):
2380 yield "rg" # simple CR Mode reports /rg
2382 yield from super().specifiers(record
=record
)
2385 class CROpMRRM(MRBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2386 """crop: scalar reduce mode (mapreduce)"""
2392 class CROpFF5RM(FFRc0BaseRM
, PredicateBaseRM
, VLiBaseRM
, DZBaseRM
,
2393 SZBaseRM
, CROpBaseRM
):
2394 """crop: ffirst 5-bit mode"""
2401 def specifiers(self
, record
):
2402 yield from super().specifiers(record
=record
, mode
="ff")
2405 # FIXME: almost everything in this class contradicts the specs (it doesn't)
2406 # The modes however are swapped: 5-bit is 3-bit, 3-bit is 5-bit
2407 class CROpFF3RM(FFRc1BaseRM
, PredicateBaseRM
, VLiBaseRM
, ZZBaseRM
, CROpBaseRM
):
2408 """cr_op: ffirst 3-bit mode"""
2414 def specifiers(self
, record
):
2415 yield from super().specifiers(record
=record
, mode
="ff")
2418 class CROpRM(CROpBaseRM
):
2419 simple
: CROpSimpleRM
2425 # ********************
2427 # https://libre-soc.org/openpower/sv/branches/
2428 class BranchBaseRM(BaseRM
):
2438 def specifiers(self
, record
):
2450 raise ValueError(self
.sz
)
2462 # Branch modes lack source mask.
2463 # Therefore a custom code is needed.
2464 CR
= (int(self
.mmode
) == 1)
2465 mask
= int(self
.mask
)
2466 m
= PredicateBaseRM
.predicate(CR
, mask
)
2470 yield from super().specifiers(record
=record
)
2473 class BranchSimpleRM(BranchBaseRM
):
2474 """branch: simple mode"""
2478 class BranchVLSRM(BranchBaseRM
):
2479 """branch: VLSET mode"""
2483 def specifiers(self
, record
):
2489 }[int(self
.VSb
), int(self
.VLi
)]
2491 yield from super().specifiers(record
=record
)
2494 class BranchCTRRM(BranchBaseRM
):
2495 """branch: CTR-test mode"""
2498 def specifiers(self
, record
):
2504 yield from super().specifiers(record
=record
)
2507 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2508 """branch: CTR-test+VLSET mode"""
2512 class BranchRM(BranchBaseRM
):
2513 simple
: BranchSimpleRM
2516 ctrvls
: BranchCTRVLSRM
2527 @_dataclasses.dataclass(eq
=True, frozen
=True)
2532 def match(cls
, desc
, record
):
2533 raise NotImplementedError()
2535 def validate(self
, others
):
2538 def assemble(self
, insn
):
2539 raise NotImplementedError()
2542 @_dataclasses.dataclass(eq
=True, frozen
=True)
2543 class SpecifierWidth(Specifier
):
2547 def match(cls
, desc
, record
, etalon
):
2548 (mode
, _
, value
) = desc
.partition("=")
2550 value
= value
.strip()
2553 width
= _SVP64Width(value
)
2555 return cls(record
=record
, width
=width
)
2558 @_dataclasses.dataclass(eq
=True, frozen
=True)
2559 class SpecifierW(SpecifierWidth
):
2561 def match(cls
, desc
, record
):
2562 return super().match(desc
=desc
, record
=record
, etalon
="w")
2564 def assemble(self
, insn
):
2565 selector
= insn
.select(record
=self
.record
)
2566 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2567 selector
.ewsrc
= self
.width
.value
2568 selector
.elwidth
= self
.width
.value
2571 @_dataclasses.dataclass(eq
=True, frozen
=True)
2572 class SpecifierSW(SpecifierWidth
):
2574 def match(cls
, desc
, record
):
2575 if record
.svp64
.mode
is _SVMode
.CROP
:
2577 return super().match(desc
=desc
, record
=record
, etalon
="sw")
2579 def assemble(self
, insn
):
2580 selector
= insn
.select(record
=self
.record
)
2581 selector
.ewsrc
= self
.width
.value
2584 @_dataclasses.dataclass(eq
=True, frozen
=True)
2585 class SpecifierDW(SpecifierWidth
):
2587 def match(cls
, desc
, record
):
2588 return super().match(desc
=desc
, record
=record
, etalon
="dw")
2590 def assemble(self
, insn
):
2591 selector
= insn
.select(record
=self
.record
)
2592 selector
.elwidth
= self
.width
.value
2595 @_dataclasses.dataclass(eq
=True, frozen
=True)
2596 class SpecifierSubVL(Specifier
):
2600 def match(cls
, desc
, record
):
2602 value
= _SVP64SubVL(desc
)
2606 return cls(record
=record
, value
=value
)
2608 def assemble(self
, insn
):
2609 selector
= insn
.select(record
=self
.record
)
2610 selector
.subvl
= int(self
.value
.value
)
2613 @_dataclasses.dataclass(eq
=True, frozen
=True)
2614 class SpecifierPredicate(Specifier
):
2619 def match(cls
, desc
, record
, mode_match
, pred_match
):
2620 (mode
, _
, pred
) = desc
.partition("=")
2623 if not mode_match(mode
):
2626 pred
= _SVP64Pred(pred
.strip())
2627 if not pred_match(pred
):
2628 raise ValueError(pred
)
2630 return cls(record
=record
, mode
=mode
, pred
=pred
)
2633 @_dataclasses.dataclass(eq
=True, frozen
=True)
2634 class SpecifierFF(SpecifierPredicate
):
2636 def match(cls
, desc
, record
):
2637 return super().match(desc
=desc
, record
=record
,
2638 mode_match
=lambda mode_arg
: mode_arg
== "ff",
2639 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2644 def assemble(self
, insn
):
2645 selector
= insn
.select(record
=self
.record
)
2646 if selector
.mode
.sel
!= 0:
2647 raise ValueError("cannot override mode")
2648 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2649 selector
.mode
.sel
= 0b01
2650 # HACK: please finally provide correct logic for CRs.
2651 if self
.pred
in (_SVP64Pred
.RC1
, _SVP64Pred
.RC1_N
):
2652 selector
.mode
[2] = (self
.pred
is _SVP64Pred
.RC1_N
)
2654 selector
.mode
[2] = self
.pred
.inv
2655 selector
.mode
[3, 4] = self
.pred
.state
2657 selector
.mode
.sel
= 0b01 if self
.mode
== "ff" else 0b11
2658 selector
.inv
= self
.pred
.inv
2660 selector
.CR
= self
.pred
.state
2662 selector
.RC1
= self
.pred
.state
2665 @_dataclasses.dataclass(eq
=True, frozen
=True)
2666 class SpecifierMask(SpecifierPredicate
):
2668 def match(cls
, desc
, record
, mode
):
2669 return super().match(desc
=desc
, record
=record
,
2670 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2671 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2676 def assemble(self
, insn
):
2677 raise NotImplementedError()
2680 @_dataclasses.dataclass(eq
=True, frozen
=True)
2681 class SpecifierM(SpecifierMask
):
2683 def match(cls
, desc
, record
):
2684 return super().match(desc
=desc
, record
=record
, mode
="m")
2686 def validate(self
, others
):
2688 if isinstance(spec
, SpecifierSM
):
2689 raise ValueError("source-mask and predicate mask conflict")
2690 elif isinstance(spec
, SpecifierDM
):
2691 raise ValueError("dest-mask and predicate mask conflict")
2693 def assemble(self
, insn
):
2694 selector
= insn
.select(record
=self
.record
)
2695 selector
.mask
= int(self
.pred
)
2696 if ((self
.record
.ptype
is _SVPType
.P2
) and
2697 (self
.record
.svp64
.mode
is not _SVMode
.BRANCH
)):
2698 selector
.smask
= int(self
.pred
)
2699 # LDST_IDX smask moving to extra322 but not straight away (False)
2700 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2701 selector
.smask_extra332
= int(self
.pred
)
2703 selector
.smask
= int(self
.pred
)
2705 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2708 @_dataclasses.dataclass(eq
=True, frozen
=True)
2709 class SpecifierSM(SpecifierMask
):
2711 def match(cls
, desc
, record
):
2712 return super().match(desc
=desc
, record
=record
, mode
="sm")
2714 def validate(self
, others
):
2715 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2716 raise ValueError("source-mask on non-twin predicate")
2718 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2721 if isinstance(spec
, SpecifierDM
):
2725 raise ValueError("missing dest-mask in CR twin predication")
2726 if self
.pred
.mode
!= twin
.pred
.mode
:
2727 raise ValueError(f
"predicate masks mismatch: "
2728 f
"{self.pred!r} vs {twin.pred!r}")
2730 def assemble(self
, insn
):
2731 selector
= insn
.select(record
=self
.record
)
2732 # LDST_IDX smask moving to extra322 but not straight away (False)
2733 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2734 selector
.smask_extra332
= int(self
.pred
)
2736 selector
.smask
= int(self
.pred
)
2737 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2740 @_dataclasses.dataclass(eq
=True, frozen
=True)
2741 class SpecifierDM(SpecifierMask
):
2743 def match(cls
, desc
, record
):
2744 return super().match(desc
=desc
, record
=record
, mode
="dm")
2746 def validate(self
, others
):
2747 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2748 raise ValueError("dest-mask on non-twin predicate")
2750 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2753 if isinstance(spec
, SpecifierSM
):
2757 raise ValueError("missing source-mask in CR twin predication")
2758 if self
.pred
.mode
!= twin
.pred
.mode
:
2759 raise ValueError(f
"predicate masks mismatch: "
2760 f
"{self.pred!r} vs {twin.pred!r}")
2762 def assemble(self
, insn
):
2763 selector
= insn
.select(record
=self
.record
)
2764 selector
.mask
= int(self
.pred
)
2765 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2768 @_dataclasses.dataclass(eq
=True, frozen
=True)
2769 class SpecifierZZ(Specifier
):
2771 def match(cls
, desc
, record
):
2775 return cls(record
=record
)
2777 def validate(self
, others
):
2779 # Since zz takes precedence (overrides) sz and dz,
2780 # treat them as mutually exclusive.
2781 if isinstance(spec
, (SpecifierSZ
, SpecifierDZ
)):
2782 raise ValueError("mutually exclusive predicate masks")
2784 def assemble(self
, insn
):
2785 selector
= insn
.select(record
=self
.record
)
2786 if hasattr(selector
, "zz"): # this should be done in a different way
2793 @_dataclasses.dataclass(eq
=True, frozen
=True)
2794 class SpecifierXZ(Specifier
):
2796 hint
: str = _dataclasses
.field(repr=False)
2799 def match(cls
, desc
, record
, etalon
, hint
):
2803 return cls(desc
=desc
, record
=record
, hint
=hint
)
2805 def validate(self
, others
):
2806 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2807 raise ValueError(f
"{self.hint} on non-twin predicate")
2809 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2812 if isinstance(spec
, SpecifierXZ
):
2816 raise ValueError(f
"missing {self.hint} in CR twin predication")
2817 if self
.pred
!= twin
.pred
:
2818 raise ValueError(f
"predicate masks mismatch: "
2819 f
"{self.pred!r} vs {twin.pred!r}")
2821 def assemble(self
, insn
):
2822 selector
= insn
.select(record
=self
.record
)
2823 setattr(selector
, self
.desc
, 1)
2826 @_dataclasses.dataclass(eq
=True, frozen
=True)
2827 class SpecifierSZ(SpecifierXZ
):
2829 def match(cls
, desc
, record
):
2830 return super().match(desc
=desc
, record
=record
,
2831 etalon
="sz", hint
="source-mask")
2833 def validate(self
, others
):
2835 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2836 if isinstance(spec
, SpecifierFF
):
2837 raise ValueError("source-zero not allowed in ff mode")
2840 @_dataclasses.dataclass(eq
=True, frozen
=True)
2841 class SpecifierDZ(SpecifierXZ
):
2843 def match(cls
, desc
, record
):
2844 return super().match(desc
=desc
, record
=record
,
2845 etalon
="dz", hint
="dest-mask")
2847 def validate(self
, others
):
2849 if ((self
.record
.svp64
.mode
is not _SVMode
.CROP
) and
2850 isinstance(spec
, SpecifierFF
) and
2851 (spec
.pred
.mode
is _SVP64PredMode
.RC1
)):
2852 raise ValueError(f
"dest-zero not allowed in ff mode BO")
2855 @_dataclasses.dataclass(eq
=True, frozen
=True)
2856 class SpecifierEls(Specifier
):
2858 def match(cls
, desc
, record
):
2862 if record
.svp64
.mode
not in (_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
):
2863 raise ValueError("els is only valid in ld/st modes, not "
2864 "%s" % str(self
.record
.svp64
.mode
))
2866 return cls(record
=record
)
2868 def assemble(self
, insn
):
2869 if self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
: # stride mode
2870 insn
.prefix
.rm
.mode
[1] = 0
2872 selector
= insn
.select(record
=self
.record
)
2877 @_dataclasses.dataclass(eq
=True, frozen
=True)
2878 class SpecifierSEA(Specifier
):
2880 def match(cls
, desc
, record
):
2884 return cls(record
=record
)
2886 def validate(self
, others
):
2887 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
:
2888 raise ValueError("sea is only valid in ld/st modes, not "
2889 "%s" % str(self
.record
.svp64
.mode
))
2892 if isinstance(spec
, SpecifierFF
):
2893 raise ValueError(f
"sea cannot be used in ff mode")
2895 def assemble(self
, insn
):
2896 selector
= insn
.select(record
=self
.record
)
2897 if selector
.mode
.sel
not in (0b10, 0b00):
2898 raise ValueError("sea is only valid for normal and els modes, "
2899 "not %d" % int(selector
.mode
.sel
))
2903 @_dataclasses.dataclass(eq
=True, frozen
=True)
2904 class SpecifierSat(Specifier
):
2909 def match(cls
, desc
, record
, etalon
, sign
):
2913 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.LDST_IMM
,
2915 raise ValueError("only normal, ld/st imm and "
2916 "ld/st idx modes supported")
2918 return cls(record
=record
, desc
=desc
, sign
=sign
)
2920 def assemble(self
, insn
):
2921 selector
= insn
.select(record
=self
.record
)
2922 selector
.mode
[0] = 0b1
2923 selector
.mode
[1] = 0b0
2924 selector
.N
= int(self
.sign
)
2927 @_dataclasses.dataclass(eq
=True, frozen
=True)
2928 class SpecifierSatS(SpecifierSat
):
2930 def match(cls
, desc
, record
):
2931 return super().match(desc
=desc
, record
=record
,
2932 etalon
="sats", sign
=True)
2935 @_dataclasses.dataclass(eq
=True, frozen
=True)
2936 class SpecifierSatU(SpecifierSat
):
2938 def match(cls
, desc
, record
):
2939 return super().match(desc
=desc
, record
=record
,
2940 etalon
="satu", sign
=False)
2943 @_dataclasses.dataclass(eq
=True, frozen
=True)
2944 class SpecifierMapReduce(Specifier
):
2948 def match(cls
, record
, RG
):
2949 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2950 raise ValueError("only normal and crop modes supported")
2952 return cls(record
=record
, RG
=RG
)
2954 def assemble(self
, insn
):
2955 selector
= insn
.select(record
=self
.record
)
2956 if self
.record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2957 raise ValueError("only normal and crop modes supported")
2958 selector
.mode
[0] = 0
2959 selector
.mode
[1] = 0
2960 selector
.mode
[2] = 1
2961 selector
.RG
= self
.RG
2964 @_dataclasses.dataclass(eq
=True, frozen
=True)
2965 class SpecifierMR(SpecifierMapReduce
):
2967 def match(cls
, desc
, record
):
2971 return super().match(record
=record
, RG
=False)
2974 @_dataclasses.dataclass(eq
=True, frozen
=True)
2975 class SpecifierMRR(SpecifierMapReduce
):
2977 def match(cls
, desc
, record
):
2981 return super().match(record
=record
, RG
=True)
2984 @_dataclasses.dataclass(eq
=True, frozen
=True)
2985 class SpecifierBranch(Specifier
):
2987 def match(cls
, desc
, record
, etalon
):
2991 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
2992 raise ValueError("only branch modes supported")
2994 return cls(record
=record
)
2997 @_dataclasses.dataclass(eq
=True, frozen
=True)
2998 class SpecifierAll(SpecifierBranch
):
3000 def match(cls
, desc
, record
):
3001 return super().match(desc
=desc
, record
=record
, etalon
="all")
3003 def assemble(self
, insn
):
3004 selector
= insn
.select(record
=self
.record
)
3008 @_dataclasses.dataclass(eq
=True, frozen
=True)
3009 class SpecifierSNZ(Specifier
):
3011 def match(cls
, desc
, record
):
3015 if record
.svp64
.mode
not in (_SVMode
.BRANCH
, _SVMode
.CROP
):
3016 raise ValueError("only branch and crop modes supported")
3018 return cls(record
=record
)
3020 def assemble(self
, insn
):
3021 selector
= insn
.select(record
=self
.record
)
3022 if self
.record
.svp64
.mode
in (_SVMode
.CROP
, _SVMode
.BRANCH
):
3024 if self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3027 raise ValueError("only branch and crop modes supported")
3030 @_dataclasses.dataclass(eq
=True, frozen
=True)
3031 class SpecifierSL(SpecifierBranch
):
3033 def match(cls
, desc
, record
):
3034 return super().match(desc
=desc
, record
=record
, etalon
="sl")
3036 def assemble(self
, insn
):
3037 selector
= insn
.select(record
=self
.record
)
3041 @_dataclasses.dataclass(eq
=True, frozen
=True)
3042 class SpecifierSLu(SpecifierBranch
):
3044 def match(cls
, desc
, record
):
3045 return super().match(desc
=desc
, record
=record
, etalon
="slu")
3047 def assemble(self
, insn
):
3048 selector
= insn
.select(record
=self
.record
)
3052 @_dataclasses.dataclass(eq
=True, frozen
=True)
3053 class SpecifierLRu(SpecifierBranch
):
3055 def match(cls
, desc
, record
):
3056 return super().match(desc
=desc
, record
=record
, etalon
="lru")
3058 def assemble(self
, insn
):
3059 selector
= insn
.select(record
=self
.record
)
3063 @_dataclasses.dataclass(eq
=True, frozen
=True)
3064 class SpecifierVSXX(SpecifierBranch
):
3069 def match(cls
, desc
, record
, etalon
, VSb
, VLi
):
3073 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3074 raise ValueError("only branch modes supported")
3076 return cls(record
=record
, VSb
=VSb
, VLi
=VLi
)
3078 def assemble(self
, insn
):
3079 selector
= insn
.select(record
=self
.record
)
3081 selector
.VSb
= int(self
.VSb
)
3082 selector
.VLi
= int(self
.VLi
)
3085 @_dataclasses.dataclass(eq
=True, frozen
=True)
3086 class SpecifierVS(SpecifierVSXX
):
3088 def match(cls
, desc
, record
):
3089 return super().match(desc
=desc
, record
=record
,
3090 etalon
="vs", VSb
=False, VLi
=False)
3093 @_dataclasses.dataclass(eq
=True, frozen
=True)
3094 class SpecifierVSi(SpecifierVSXX
):
3096 def match(cls
, desc
, record
):
3097 return super().match(desc
=desc
, record
=record
,
3098 etalon
="vsi", VSb
=False, VLi
=True)
3101 @_dataclasses.dataclass(eq
=True, frozen
=True)
3102 class SpecifierVSb(SpecifierVSXX
):
3104 def match(cls
, desc
, record
):
3105 return super().match(desc
=desc
, record
=record
,
3106 etalon
="vsb", VSb
=True, VLi
=False)
3109 @_dataclasses.dataclass(eq
=True, frozen
=True)
3110 class SpecifierVSbi(SpecifierVSXX
):
3112 def match(cls
, desc
, record
):
3113 return super().match(desc
=desc
, record
=record
,
3114 etalon
="vsbi", VSb
=True, VLi
=True)
3117 @_dataclasses.dataclass(eq
=True, frozen
=True)
3118 class SpecifierCTX(Specifier
):
3122 def match(cls
, desc
, record
, etalon
, CTi
):
3126 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3127 raise ValueError("only branch modes supported")
3129 return cls(record
=record
, CTi
=CTi
)
3131 def assemble(self
, insn
):
3132 selector
= insn
.select(record
=self
.record
)
3134 selector
.CTi
= int(self
.CTi
)
3137 @_dataclasses.dataclass(eq
=True, frozen
=True)
3138 class SpecifierCTR(SpecifierCTX
):
3140 def match(cls
, desc
, record
):
3141 return super().match(desc
=desc
, record
=record
,
3142 etalon
="ctr", CTi
=False)
3145 @_dataclasses.dataclass(eq
=True, frozen
=True)
3146 class SpecifierCTi(SpecifierCTX
):
3148 def match(cls
, desc
, record
):
3149 return super().match(desc
=desc
, record
=record
,
3150 etalon
="cti", CTi
=True)
3153 @_dataclasses.dataclass(eq
=True, frozen
=True)
3154 class SpecifierPI(Specifier
):
3156 def match(cls
, desc
, record
):
3160 if record
.svp64
.mode
not in [_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
]:
3161 raise ValueError("only ld/st imm/idx mode supported")
3163 return cls(record
=record
)
3165 def assemble(self
, insn
):
3166 selector
= insn
.select(record
=self
.record
)
3167 selector
.mode
[2] = 0b1
3171 @_dataclasses.dataclass(eq
=True, frozen
=True)
3172 class SpecifierLF(Specifier
):
3174 def match(cls
, desc
, record
):
3178 if record
.svp64
.mode
is not _SVMode
.LDST_IMM
:
3179 raise ValueError("only ld/st imm mode supported")
3181 return cls(record
=record
)
3183 def assemble(self
, insn
):
3184 selector
= insn
.select(record
=self
.record
)
3185 selector
.mode
[1] = 0
3189 @_dataclasses.dataclass(eq
=True, frozen
=True)
3190 class SpecifierVLi(Specifier
):
3192 def match(cls
, desc
, record
):
3196 return cls(record
=record
)
3198 def validate(self
, others
):
3200 if isinstance(spec
, SpecifierFF
):
3203 raise ValueError("VLi only allowed in failfirst")
3205 def assemble(self
, insn
):
3206 selector
= insn
.select(record
=self
.record
)
3207 selector
.mode
[1] = 1
3211 class Specifiers(tuple):
3246 def __new__(cls
, items
, record
):
3247 def transform(item
):
3248 for spec_cls
in cls
.SPECS
:
3249 spec
= spec_cls
.match(item
, record
=record
)
3250 if spec
is not None:
3252 raise ValueError(item
)
3254 # TODO: remove this hack
3255 items
= dict.fromkeys(items
)
3259 items
= tuple(items
)
3261 specs
= tuple(map(transform
, items
))
3262 for (index
, spec
) in enumerate(specs
):
3263 head
= specs
[:index
]
3264 tail
= specs
[index
+ 1:]
3265 spec
.validate(others
=(head
+ tail
))
3267 return super().__new
__(cls
, specs
)
3270 class SVP64OperandMeta(type):
3271 class SVP64NonZeroOperand(NonZeroOperand
):
3272 def assemble(self
, insn
, value
):
3273 if isinstance(value
, str):
3274 value
= int(value
, 0)
3275 if not isinstance(value
, int):
3276 raise ValueError("non-integer operand")
3278 # FIXME: this is really weird
3279 if self
.record
.name
in ("svstep", "svstep."):
3280 value
+= 1 # compensation
3282 return super().assemble(value
=value
, insn
=insn
)
3284 class SVP64XOStaticOperand(SpanStaticOperand
):
3285 def __init__(self
, record
, value
, span
):
3286 return super().__init
__(record
=record
, name
="XO",
3287 value
=value
, span
=span
)
3290 NonZeroOperand
: SVP64NonZeroOperand
,
3291 XOStaticOperand
: SVP64XOStaticOperand
,
3294 def __new__(metacls
, name
, bases
, ns
):
3296 for (index
, base_cls
) in enumerate(bases
):
3297 bases
[index
] = metacls
.__TRANSFORM
.get(base_cls
, base_cls
)
3299 bases
= tuple(bases
)
3301 return super().__new
__(metacls
, name
, bases
, ns
)
3304 class SVP64Operand(Operand
, metaclass
=SVP64OperandMeta
):
3307 return tuple(map(lambda bit
: (bit
+ 32), super().span
))
3311 def __init__(self
, insn
, record
):
3313 self
.__record
= record
3314 return super().__init
__()
3317 return self
.rm
.__doc
__
3320 return repr(self
.rm
)
3328 return self
.__record
3332 rm
= getattr(self
.insn
.prefix
.rm
, self
.record
.svp64
.mode
.name
.lower())
3334 # The idea behind these tables is that they are now literally
3335 # in identical format to insndb.csv and minor_xx.csv and can
3336 # be done precisely as that. The only thing to watch out for
3337 # is the insertion of Rc=1 as a "mask/value" bit and likewise
3338 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
3341 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
3342 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3343 # mode Rc mask Rc member
3345 (0b000000, 0b111000, "simple"), # simple (no Rc)
3346 (0b001000, 0b111100, "mr"), # mapreduce (no Rc)
3347 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3348 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3349 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3350 (0b001100, 0b111100, "rsvd"), # reserved
3352 mode
= int(self
.insn
.prefix
.rm
.normal
.mode
)
3353 search
= ((mode
<< 1) | self
.record
.Rc
)
3355 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
3356 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3357 # mode Rc mask Rc member
3358 # ironically/coincidentally this table is identical to NORMAL
3359 # mode except reserved in place of mr
3361 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3362 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3363 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3365 search
= ((int(self
.insn
.prefix
.rm
.ldst_imm
.mode
) << 1) |
3368 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
3369 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3370 # mode Rc mask Rc member
3372 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3373 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3374 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3376 search
= ((int(self
.insn
.prefix
.rm
.ldst_idx
.mode
) << 1) |
3379 elif self
.record
.svp64
.mode
is _SVMode
.CROP
:
3380 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
3381 # mode 3b mask 3b member
3383 (0b000000, 0b111000, "simple"), # simple
3384 (0b001000, 0b111000, "mr"), # mapreduce
3385 (0b010001, 0b010001, "ff3"), # ffirst, 3-bit CR
3386 (0b010000, 0b010000, "ff5"), # ffirst, 5-bit CR
3388 search
= ((int(self
.insn
.prefix
.rm
.crop
.mode
) << 1) |
3389 int(self
.record
.svp64
.extra_CR_3bit
))
3391 elif self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3395 (0b00, 0b11, "simple"), # simple
3396 (0b01, 0b11, "vls"), # VLset
3397 (0b10, 0b11, "ctr"), # CTR mode
3398 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
3400 # slightly weird: doesn't have a 5-bit "mode" field like others
3401 search
= int(self
.insn
.prefix
.rm
.branch
.mode
.sel
)
3404 if table
is not None:
3405 for (value
, mask
, field
) in table
:
3406 if field
.startswith("rsvd"):
3408 if ((value
& mask
) == (search
& mask
)):
3409 return getattr(rm
, field
)
3413 def __getattr__(self
, key
):
3414 if key
.startswith(f
"_{self.__class__.__name__}__"):
3415 return super().__getattribute
__(key
)
3417 return getattr(self
.rm
, key
)
3419 def __setattr__(self
, key
, value
):
3420 if key
.startswith(f
"_{self.__class__.__name__}__"):
3421 return super().__setattr
__(key
, value
)
3424 if not hasattr(rm
, key
):
3425 raise AttributeError(key
)
3427 return setattr(rm
, key
, value
)
3430 class SVP64Instruction(PrefixedInstruction
):
3431 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
3432 class Prefix(PrefixedInstruction
.Prefix
):
3434 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
3438 def select(self
, record
):
3439 return RMSelector(insn
=self
, record
=record
)
3444 for idx
in range(64):
3445 bit
= int(self
[idx
])
3447 return "".join(map(str, bits
))
3450 def assemble(cls
, record
, arguments
=None, specifiers
=None):
3451 insn
= super().assemble(record
=record
, arguments
=arguments
)
3453 specifiers
= Specifiers(items
=specifiers
, record
=record
)
3454 for specifier
in specifiers
:
3455 specifier
.assemble(insn
=insn
)
3457 insn
.prefix
.PO
= 0x1
3458 insn
.prefix
.id = 0x3
3462 def disassemble(self
, record
,
3464 style
=Style
.NORMAL
):
3466 if style
<= Style
.SHORT
:
3469 blob
= insn
.bytes(byteorder
=byteorder
)
3470 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
3473 blob_prefix
= blob(self
.prefix
)
3474 blob_suffix
= blob(self
.suffix
)
3476 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3477 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
3480 assert record
.svp64
is not None
3482 name
= f
"sv.{record.name}"
3484 rm
= self
.select(record
=record
)
3486 # convert specifiers to /x/y/z (sorted lexicographically)
3487 specifiers
= sorted(rm
.specifiers(record
=record
))
3488 if specifiers
: # if any add one extra to get the extra "/"
3489 specifiers
= ([""] + specifiers
)
3490 specifiers
= "/".join(specifiers
)
3492 # convert operands to " ,x,y,z"
3493 operands
= tuple(map(_operator
.itemgetter(1),
3494 self
.spec_dynamic_operands(record
=record
, style
=style
)))
3495 operands
= ",".join(operands
)
3496 if len(operands
) > 0: # if any separate with a space
3497 operands
= (" " + operands
)
3499 if style
<= Style
.LEGACY
:
3500 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3501 suffix
= WordInstruction
.integer(value
=int(self
.suffix
))
3502 yield from suffix
.disassemble(record
=record
,
3503 byteorder
=byteorder
, style
=style
)
3505 yield f
"{blob_prefix}{name}{specifiers}{operands}"
3507 yield f
"{blob_suffix}"
3509 if style
>= Style
.VERBOSE
:
3511 binary
= self
.binary
3512 spec
= self
.spec(record
=record
, prefix
="sv.")
3514 yield f
"{indent}spec"
3515 yield f
"{indent}{indent}{spec}"
3516 yield f
"{indent}pcode"
3517 for stmt
in record
.mdwn
.pcode
:
3518 yield f
"{indent}{indent}{stmt}"
3519 yield f
"{indent}binary"
3520 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
3521 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
3522 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
3523 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
3524 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
3525 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
3526 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
3527 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
3528 yield f
"{indent}opcodes"
3529 for opcode
in record
.opcodes
:
3530 yield f
"{indent}{indent}{opcode!r}"
3531 for operand
in self
.operands(record
=record
):
3532 yield from operand
.disassemble(insn
=self
,
3533 style
=style
, indent
=indent
)
3535 yield f
"{indent}{indent}{str(rm)}"
3536 for line
in rm
.disassemble(style
=style
):
3537 yield f
"{indent}{indent}{line}"
3541 def operands(cls
, record
):
3542 for operand
in super().operands(record
=record
):
3543 parent
= operand
.__class
__
3544 name
= f
"SVP64{parent.__name__}"
3545 bases
= (SVP64Operand
, parent
)
3546 child
= type(name
, bases
, {})
3547 yield child(**dict(operand
))
3550 def parse(stream
, factory
):
3552 return ("TODO" not in frozenset(entry
.values()))
3554 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
3555 entries
= _csv
.DictReader(lines
)
3556 entries
= filter(match
, entries
)
3557 return tuple(map(factory
, entries
))
3560 class MarkdownDatabase
:
3563 for (name
, desc
) in _ISA():
3566 (dynamic
, *static
) = desc
.regs
3567 operands
.extend(dynamic
)
3568 operands
.extend(static
)
3569 pcode
= PCode(iterable
=filter(str.strip
, desc
.pcode
))
3570 operands
= Operands(insn
=name
, operands
=operands
)
3571 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
3573 self
.__db
= dict(sorted(db
.items()))
3575 return super().__init
__()
3578 yield from self
.__db
.items()
3580 def __contains__(self
, key
):
3581 return self
.__db
.__contains
__(key
)
3583 def __getitem__(self
, key
):
3584 return self
.__db
.__getitem
__(key
)
3587 class FieldsDatabase
:
3590 df
= _DecodeFields()
3592 for (form
, fields
) in df
.instrs
.items():
3593 if form
in {"DQE", "TX"}:
3597 db
[_Form
[form
]] = Fields(fields
)
3601 return super().__init
__()
3603 def __getitem__(self
, key
):
3604 return self
.__db
.__getitem
__(key
)
3608 def __init__(self
, root
, mdwndb
):
3609 # The code below groups the instructions by name:section.
3610 # There can be multiple names for the same instruction.
3611 # The point is to capture different opcodes for the same instruction.
3613 records
= _collections
.defaultdict(set)
3614 path
= (root
/ "insndb.csv")
3615 with
open(path
, "r", encoding
="UTF-8") as stream
:
3616 for section
in sorted(parse(stream
, Section
.CSV
)):
3617 path
= (root
/ section
.path
)
3619 section
.Mode
.INTEGER
: IntegerOpcode
,
3620 section
.Mode
.PATTERN
: PatternOpcode
,
3622 factory
= _functools
.partial(
3623 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
3624 with
open(path
, "r", encoding
="UTF-8") as stream
:
3625 for insn
in parse(stream
, factory
):
3626 for name
in insn
.names
:
3627 records
[name
].add(insn
)
3628 sections
[name
] = section
3630 items
= sorted(records
.items())
3632 for (name
, multirecord
) in items
:
3633 records
[name
] = PPCMultiRecord(sorted(multirecord
))
3635 def exact_match(name
):
3636 record
= records
.get(name
)
3642 if not name
.endswith("l"):
3644 alias
= exact_match(name
[:-1])
3647 record
= records
[alias
]
3648 if "lk" not in record
.flags
:
3649 raise ValueError(record
)
3653 if not name
.endswith("a"):
3655 alias
= LK_match(name
[:-1])
3658 record
= records
[alias
]
3659 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
3660 raise ValueError(record
)
3661 if "AA" not in mdwndb
[name
].operands
:
3662 raise ValueError(record
)
3666 if not name
.endswith("."):
3668 alias
= exact_match(name
[:-1])
3671 record
= records
[alias
]
3672 if record
.Rc
is _RCOE
.NONE
:
3673 raise ValueError(record
)
3677 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
3678 for (name
, _
) in mdwndb
:
3679 if name
.startswith("sv."):
3682 for match
in matches
:
3684 if alias
is not None:
3688 section
= sections
[alias
]
3689 record
= records
[alias
]
3690 db
[name
] = (section
, record
)
3692 self
.__db
= dict(sorted(db
.items()))
3694 return super().__init
__()
3696 @_functools.lru_cache(maxsize
=512, typed
=False)
3697 def __getitem__(self
, key
):
3698 return self
.__db
.get(key
, (None, None))
3701 class SVP64Database
:
3702 def __init__(self
, root
, ppcdb
):
3704 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
3705 for (prefix
, _
, names
) in _os
.walk(root
):
3706 prefix
= _pathlib
.Path(prefix
)
3707 for name
in filter(lambda name
: pattern
.match(name
), names
):
3708 path
= (prefix
/ _pathlib
.Path(name
))
3709 with
open(path
, "r", encoding
="UTF-8") as stream
:
3710 db
.update(parse(stream
, SVP64Record
.CSV
))
3711 db
= {record
.name
:record
for record
in db
}
3713 self
.__db
= dict(sorted(db
.items()))
3714 self
.__ppcdb
= ppcdb
3716 return super().__init
__()
3718 def __getitem__(self
, key
):
3719 (_
, record
) = self
.__ppcdb
[key
]
3723 for name
in record
.names
:
3724 record
= self
.__db
.get(name
, None)
3725 if record
is not None:
3731 class Database(Node
):
3732 def __init__(self
, root
):
3733 root
= _pathlib
.Path(root
)
3734 mdwndb
= MarkdownDatabase()
3735 fieldsdb
= FieldsDatabase()
3736 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
3737 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
3741 opcodes
= _collections
.defaultdict(
3742 lambda: _collections
.defaultdict(set))
3744 for (name
, mdwn
) in mdwndb
:
3745 if name
.startswith("sv."):
3747 (section
, ppc
) = ppcdb
[name
]
3750 svp64
= svp64db
[name
]
3751 fields
= fieldsdb
[ppc
.form
]
3752 record
= Record(name
=name
,
3753 section
=section
, ppc
=ppc
, svp64
=svp64
,
3754 mdwn
=mdwn
, fields
=fields
)
3756 names
[record
.name
] = record
3757 opcodes
[section
][record
.PO
].add(record
)
3759 self
.__db
= sorted(db
)
3760 self
.__names
= dict(sorted(names
.items()))
3761 self
.__opcodes
= dict(sorted(opcodes
.items()))
3763 return super().__init
__()
3765 def visit(self
, handler
, matcher
, depth
):
3766 if matcher(node
=self
, depth
=depth
):
3767 with
handler(node
=self
, depth
=depth
):
3769 record
.visit(depth
=(depth
+ 1),
3770 handler
=handler
, matcher
=matcher
)
3774 for record
in self
.__db
:
3778 return repr(self
.__db
)
3781 yield from self
.__db
3783 @_functools.lru_cache(maxsize
=None)
3784 def __contains__(self
, key
):
3785 return self
.__getitem
__(key
) is not None
3787 @_functools.lru_cache(maxsize
=None)
3788 def __getitem__(self
, key
):
3789 if isinstance(key
, SVP64Instruction
):
3792 if isinstance(key
, Instruction
):
3795 sections
= sorted(self
.__opcodes
)
3796 for section
in sections
:
3797 group
= self
.__opcodes
[section
]
3798 for record
in group
[PO
]:
3799 if record
.match(key
=key
):
3804 elif isinstance(key
, str):
3805 return self
.__names
.get(key
)
3807 raise ValueError("instruction or name expected")