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 __call__(self
, node
):
61 method
= node
.__class
__.__name
__
62 method
= getattr(self
, method
, self
.Node
)
63 return method(node
=node
)
65 @_contextlib.contextmanager
67 for subnode
in node
.subnodes
:
80 nodes
= _collections
.deque([root
])
82 node
= nodes
.popleft()
83 nodes
.extend(node
.subnodes
)
87 @_functools.total_ordering
88 class Style(_enum
.Enum
):
92 VERBOSE
= _enum
.auto()
94 def __lt__(self
, other
):
95 if not isinstance(other
, self
.__class
__):
97 return (self
.value
< other
.value
)
100 @_functools.total_ordering
101 class Priority(_enum
.Enum
):
107 def _missing_(cls
, value
):
108 if isinstance(value
, str):
109 value
= value
.upper()
113 return super()._missing
_(value
)
115 def __lt__(self
, other
):
116 if not isinstance(other
, self
.__class
__):
117 return NotImplemented
119 # NOTE: the order is inversed, LOW < NORMAL < HIGH
120 return (self
.value
> other
.value
)
123 def dataclass(cls
, record
, keymap
=None, typemap
=None):
127 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
129 def transform(key_value
):
130 (key
, value
) = key_value
131 key
= keymap
.get(key
, key
)
132 hook
= typemap
.get(key
, lambda value
: value
)
133 if hook
is bool and value
in ("", "0"):
139 record
= dict(map(transform
, record
.items()))
140 for key
in frozenset(record
.keys()):
141 if record
[key
] == "":
147 @_functools.total_ordering
148 @_dataclasses.dataclass(eq
=True, frozen
=True)
151 def __new__(cls
, value
):
152 if isinstance(value
, str):
153 value
= int(value
, 0)
154 if not isinstance(value
, int):
155 raise ValueError(value
)
157 if value
.bit_length() > 64:
158 raise ValueError(value
)
160 return super().__new
__(cls
, value
)
163 return self
.__repr
__()
166 return f
"{self:0{self.bit_length()}b}"
168 def bit_length(self
):
169 if super().bit_length() > 32:
173 class Value(Integer
):
182 def __lt__(self
, other
):
183 if not isinstance(other
, Opcode
):
184 return NotImplemented
185 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
188 return (self
.value
& self
.mask
)
191 return int(self
).__index
__()
194 def pattern(value
, mask
, bit_length
):
195 for bit
in range(bit_length
):
196 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
198 elif (value
& (1 << (bit_length
- bit
- 1))):
203 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
205 def match(self
, key
):
206 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
209 @_functools.total_ordering
210 @_dataclasses.dataclass(eq
=True, frozen
=True)
211 class IntegerOpcode(Opcode
):
212 def __init__(self
, value
):
213 if value
.startswith("0b"):
214 mask
= int(("1" * len(value
[2:])), 2)
218 value
= Opcode
.Value(value
)
219 mask
= Opcode
.Mask(mask
)
221 return super().__init
__(value
=value
, mask
=mask
)
224 @_functools.total_ordering
225 @_dataclasses.dataclass(eq
=True, frozen
=True)
226 class PatternOpcode(Opcode
):
227 def __init__(self
, pattern
):
228 if not isinstance(pattern
, str):
229 raise ValueError(pattern
)
231 (value
, mask
) = (0, 0)
232 for symbol
in pattern
:
233 if symbol
not in {"0", "1", "-"}:
234 raise ValueError(pattern
)
235 value |
= (symbol
== "1")
236 mask |
= (symbol
!= "-")
242 value
= Opcode
.Value(value
)
243 mask
= Opcode
.Mask(mask
)
245 return super().__init
__(value
=value
, mask
=mask
)
248 @_dataclasses.dataclass(eq
=True, frozen
=True)
250 class FlagsMeta(type):
265 class Flags(tuple, metaclass
=FlagsMeta
):
266 def __new__(cls
, flags
=frozenset()):
267 flags
= frozenset(flags
)
268 diff
= (flags
- frozenset(cls
))
270 raise ValueError(flags
)
271 return super().__new
__(cls
, sorted(flags
))
275 flags
: Flags
= Flags()
277 function
: _Function
= _Function
.NONE
278 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
279 in1
: _In1Sel
= _In1Sel
.NONE
280 in2
: _In2Sel
= _In2Sel
.NONE
281 in3
: _In3Sel
= _In3Sel
.NONE
282 out
: _OutSel
= _OutSel
.NONE
283 cr_in
: _CRInSel
= _CRInSel
.NONE
284 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
285 cr_out
: _CROutSel
= _CROutSel
.NONE
286 cry_in
: _CryIn
= _CryIn
.ZERO
287 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
288 upd
: _LDSTMode
= _LDSTMode
.NONE
289 Rc
: _RCOE
= _RCOE
.NONE
290 form
: _Form
= _Form
.NONE
292 unofficial
: bool = False
296 "internal op": "intop",
300 "ldst len": "ldst_len",
302 "CONDITIONS": "conditions",
305 def __lt__(self
, other
):
306 if not isinstance(other
, self
.__class
__):
307 return NotImplemented
308 lhs
= (self
.opcode
, self
.comment
)
309 rhs
= (other
.opcode
, other
.comment
)
313 def CSV(cls
, record
, opcode_cls
):
314 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
315 typemap
["opcode"] = opcode_cls
317 if record
["CR in"] == "BA_BB":
318 record
["cr_in"] = "BA"
319 record
["cr_in2"] = "BB"
323 for flag
in frozenset(PPCRecord
.Flags
):
324 if bool(record
.pop(flag
, "")):
326 record
["flags"] = PPCRecord
.Flags(flags
)
328 return dataclass(cls
, record
,
329 keymap
=PPCRecord
.__KEYMAP
,
334 return frozenset(self
.comment
.split("=")[-1].split("/"))
337 class PPCMultiRecord(tuple):
338 def __getattr__(self
, attr
):
341 raise AttributeError(attr
)
342 return getattr(self
[0], attr
)
345 @_dataclasses.dataclass(eq
=True, frozen
=True)
347 class ExtraMap(tuple):
349 @_dataclasses.dataclass(eq
=True, frozen
=True)
351 seltype
: _SelType
= _SelType
.NONE
352 reg
: _Reg
= _Reg
.NONE
355 return f
"{self.seltype.value}:{self.reg.name}"
357 def __new__(cls
, value
="0"):
358 if isinstance(value
, str):
359 def transform(value
):
360 (seltype
, reg
) = value
.split(":")
361 seltype
= _SelType(seltype
)
363 return cls
.Entry(seltype
=seltype
, reg
=reg
)
368 value
= map(transform
, value
.split(";"))
370 return super().__new
__(cls
, value
)
373 return repr(list(self
))
375 def __new__(cls
, value
=tuple()):
379 return super().__new
__(cls
, map(cls
.Extra
, value
))
382 return repr({index
:self
[index
] for index
in range(0, 4)})
385 ptype
: _SVPType
= _SVPType
.NONE
386 etype
: _SVEType
= _SVEType
.NONE
387 msrc
: _SVMaskSrc
= _SVMaskSrc
.NO
# MASK_SRC is active
388 in1
: _In1Sel
= _In1Sel
.NONE
389 in2
: _In2Sel
= _In2Sel
.NONE
390 in3
: _In3Sel
= _In3Sel
.NONE
391 out
: _OutSel
= _OutSel
.NONE
392 out2
: _OutSel
= _OutSel
.NONE
393 cr_in
: _CRInSel
= _CRInSel
.NONE
394 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
395 cr_out
: _CROutSel
= _CROutSel
.NONE
396 extra
: ExtraMap
= ExtraMap()
398 mode
: _SVMode
= _SVMode
.NORMAL
402 "CONDITIONS": "conditions",
411 def CSV(cls
, record
):
412 record
["insn"] = record
["insn"].split("=")[-1]
414 for key
in frozenset({
415 "in1", "in2", "in3", "CR in",
416 "out", "out2", "CR out",
422 if record
["CR in"] == "BA_BB":
423 record
["cr_in"] = "BA"
424 record
["cr_in2"] = "BB"
428 for idx
in range(0, 4):
429 extra
.append(record
.pop(f
"{idx}"))
431 record
["extra"] = cls
.ExtraMap(extra
)
433 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
438 "in1", "in2", "in3", "cr_in", "cr_in2",
439 "out", "out2", "cr_out",
454 for index
in range(0, 4):
455 for entry
in self
.extra
[index
]:
456 extras
[entry
.seltype
][entry
.reg
] = idxmap
[index
]
458 for (seltype
, regs
) in extras
.items():
459 idx
= regs
.get(reg
, _SVExtra
.NONE
)
460 if idx
is not _SVExtra
.NONE
:
461 yield (reg
, seltype
, idx
)
468 # has the word "in", it is a SelType.SRC "out" -> DST
469 # in1/2/3 and CR in are SRC, and must match only against "s:NN"
470 # out/out1 and CR out are DST, and must match only against "d:NN"
471 keytype
= _SelType
.SRC
if ("in" in key
) else _SelType
.DST
472 sel
= sels
[key
] = getattr(self
, key
)
473 reg
= regs
[key
] = _Reg(sel
)
474 seltypes
[key
] = _SelType
.NONE
475 idxs
[key
] = _SVExtra
.NONE
476 for (reg
, seltype
, idx
) in extra(reg
.alias
):
477 if keytype
!= seltype
: # only check SRC-to-SRC and DST-to-DST
479 if idx
!= idxs
[key
] and idxs
[key
] is not _SVExtra
.NONE
:
480 raise ValueError(idx
)
483 seltypes
[key
] = seltype
485 if sels
["cr_in"] is _CRInSel
.BA_BB
:
486 sels
["cr_in"] = _CRIn2Sel
.BA
487 sels
["cr_in2"] = _CRIn2Sel
.BB
488 idxs
["cr_in2"] = idxs
["cr_in"]
489 for key
in ("cr_in", "cr_in2"):
490 regs
[key
] = _Reg(sels
[key
])
491 seltype
[key
] = _SelType
.SRC
498 "seltype": seltypes
[key
],
502 return _types
.MappingProxyType(records
)
504 extra_idx_in1
= property(lambda self
: self
.extras
["in1"]["idx"])
505 extra_idx_in2
= property(lambda self
: self
.extras
["in2"]["idx"])
506 extra_idx_in3
= property(lambda self
: self
.extras
["in3"]["idx"])
507 extra_idx_out
= property(lambda self
: self
.extras
["out"]["idx"])
508 extra_idx_out2
= property(lambda self
: self
.extras
["out2"]["idx"])
509 extra_idx_cr_in
= property(lambda self
: self
.extras
["cr_in"]["idx"])
510 extra_idx_cr_in2
= property(lambda self
: self
.extras
["cr_in2"]["idx"])
511 extra_idx_cr_out
= property(lambda self
: self
.extras
["cr_out"]["idx"])
516 for idx
in range(0, 4):
517 for entry
in self
.extra
[idx
]:
518 if entry
.seltype
is _SelType
.DST
:
519 if extra
is not None:
520 raise ValueError(self
.svp64
)
524 if _RegType(extra
.reg
) not in (_RegType
.CR_3BIT
, _RegType
.CR_5BIT
):
525 raise ValueError(self
.svp64
)
530 def extra_CR_3bit(self
):
531 return (_RegType(self
.extra_CR
.reg
) is _RegType
.CR_3BIT
)
535 def __init__(self
, value
=(0, 32)):
536 if isinstance(value
, str):
537 (start
, end
) = map(int, value
.split(":"))
540 if start
< 0 or end
< 0 or start
>= end
:
541 raise ValueError(value
)
546 return super().__init
__()
549 return (self
.__end
- self
.__start
+ 1)
552 return f
"[{self.__start}:{self.__end}]"
555 yield from range(self
.start
, (self
.end
+ 1))
557 def __reversed__(self
):
558 return tuple(reversed(tuple(self
)))
569 @_dataclasses.dataclass(eq
=True, frozen
=True)
571 class Mode(_enum
.Enum
):
572 INTEGER
= _enum
.auto()
573 PATTERN
= _enum
.auto()
576 def _missing_(cls
, value
):
577 if isinstance(value
, str):
578 return cls
[value
.upper()]
579 return super()._missing
_(value
)
582 def __new__(cls
, value
=None):
583 if isinstance(value
, str):
584 if value
.upper() == "NONE":
587 value
= int(value
, 0)
591 return super().__new
__(cls
, value
)
597 return (bin(self
) if self
else "None")
603 opcode
: IntegerOpcode
= None
604 priority
: Priority
= Priority
.NORMAL
606 def __lt__(self
, other
):
607 if not isinstance(other
, self
.__class
__):
608 return NotImplemented
609 return (self
.priority
< other
.priority
)
612 def CSV(cls
, record
):
613 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
614 if record
["opcode"] == "NONE":
615 typemap
["opcode"] = lambda _
: None
617 return dataclass(cls
, record
, typemap
=typemap
)
621 def __init__(self
, items
):
622 if isinstance(items
, dict):
623 items
= items
.items()
626 (name
, bitrange
) = item
627 return (name
, tuple(bitrange
.values()))
629 self
.__mapping
= dict(map(transform
, items
))
631 return super().__init
__()
634 return repr(self
.__mapping
)
637 yield from self
.__mapping
.items()
639 def __contains__(self
, key
):
640 return self
.__mapping
.__contains
__(key
)
642 def __getitem__(self
, key
):
643 return self
.__mapping
.get(key
, None)
658 def __init__(self
, insn
, operands
):
660 "b": {"target_addr": TargetAddrOperandLI
},
661 "ba": {"target_addr": TargetAddrOperandLI
},
662 "bl": {"target_addr": TargetAddrOperandLI
},
663 "bla": {"target_addr": TargetAddrOperandLI
},
664 "bc": {"target_addr": TargetAddrOperandBD
},
665 "bca": {"target_addr": TargetAddrOperandBD
},
666 "bcl": {"target_addr": TargetAddrOperandBD
},
667 "bcla": {"target_addr": TargetAddrOperandBD
},
668 "addpcis": {"D": DOperandDX
},
669 "fishmv": {"D": DOperandDX
},
670 "fmvis": {"D": DOperandDX
},
673 "SVi": NonZeroOperand
,
674 "SVd": NonZeroOperand
,
675 "SVxd": NonZeroOperand
,
676 "SVyd": NonZeroOperand
,
677 "SVzd": NonZeroOperand
,
679 "D": SignedImmediateOperand
,
683 "SIM": SignedOperand
,
684 "SVD": SignedOperand
,
685 "SVDS": SignedOperand
,
686 "RSp": GPRPairOperand
,
687 "RTp": GPRPairOperand
,
688 "FRAp": FPRPairOperand
,
689 "FRBp": FPRPairOperand
,
690 "FRSp": FPRPairOperand
,
691 "FRTp": FPRPairOperand
,
693 custom_immediates
= {
699 for operand
in operands
:
703 (name
, value
) = operand
.split("=")
704 mapping
[name
] = (StaticOperand
, {
710 if name
.endswith(")"):
711 name
= name
.replace("(", " ").replace(")", "")
712 (imm_name
, _
, name
) = name
.partition(" ")
716 if imm_name
is not None:
717 imm_cls
= custom_immediates
.get(imm_name
, ImmediateOperand
)
719 if insn
in custom_insns
and name
in custom_insns
[insn
]:
720 cls
= custom_insns
[insn
][name
]
721 elif name
in custom_fields
:
722 cls
= custom_fields
[name
]
723 elif name
in _Reg
.__members
__:
725 if reg
in self
.__class
__.__GPR
_PAIRS
:
727 elif reg
in self
.__class
__.__FPR
_PAIRS
:
730 regtype
= _RegType
[name
]
731 if regtype
is _RegType
.GPR
:
733 elif regtype
is _RegType
.FPR
:
735 elif regtype
is _RegType
.CR_3BIT
:
737 elif regtype
is _RegType
.CR_5BIT
:
740 if imm_name
is not None:
741 mapping
[imm_name
] = (imm_cls
, {"name": imm_name
})
742 mapping
[name
] = (cls
, {"name": name
})
746 for (name
, (cls
, kwargs
)) in mapping
.items():
747 kwargs
= dict(kwargs
)
748 kwargs
["name"] = name
749 if issubclass(cls
, StaticOperand
):
750 static
.append((cls
, kwargs
))
751 elif issubclass(cls
, DynamicOperand
):
752 dynamic
.append((cls
, kwargs
))
754 raise ValueError(name
)
756 self
.__mapping
= mapping
757 self
.__static
= tuple(static
)
758 self
.__dynamic
= tuple(dynamic
)
760 return super().__init
__()
763 for (_
, items
) in self
.__mapping
.items():
764 (cls
, kwargs
) = items
768 return self
.__mapping
.__repr
__()
770 def __contains__(self
, key
):
771 return self
.__mapping
.__contains
__(key
)
773 def __getitem__(self
, key
):
774 return self
.__mapping
.__getitem
__(key
)
782 return self
.__dynamic
785 class Arguments(tuple):
786 def __new__(cls
, record
, arguments
, operands
):
787 operands
= iter(tuple(operands
))
788 arguments
= iter(tuple(arguments
))
793 operand
= next(operands
)
794 except StopIteration:
798 argument
= next(arguments
)
799 except StopIteration:
800 raise ValueError("operands count mismatch")
802 if isinstance(operand
, ImmediateOperand
):
803 argument
= argument
.replace("(", " ").replace(")", "")
804 (imm_argument
, _
, argument
) = argument
.partition(" ")
806 (imm_operand
, operand
) = (operand
, next(operands
))
807 except StopIteration:
808 raise ValueError("operands count mismatch")
809 items
.append((imm_argument
, imm_operand
))
810 items
.append((argument
, operand
))
814 except StopIteration:
817 raise ValueError("operands count mismatch")
819 return super().__new
__(cls
, items
)
823 def __init__(self
, iterable
):
824 self
.__pcode
= tuple(iterable
)
825 return super().__init
__()
828 yield from self
.__pcode
831 return self
.__pcode
.__repr
__()
834 @_dataclasses.dataclass(eq
=True, frozen
=True)
835 class MarkdownRecord
:
840 @_dataclasses.dataclass(eq
=True, frozen
=True)
844 _In1Sel
, _In2Sel
, _In3Sel
, _CRInSel
, _CRIn2Sel
,
852 @_functools.total_ordering
853 @_dataclasses.dataclass(eq
=True, frozen
=True)
860 svp64
: SVP64Record
= None
864 for (name
, fields
) in self
.extras
.items():
865 yield Extra(name
=name
, **fields
)
869 if self
.svp64
is not None:
870 return self
.svp64
.extras
872 return _types
.MappingProxyType({})
876 return self
.mdwn
.pcode
878 def __lt__(self
, other
):
879 if not isinstance(other
, Record
):
880 return NotImplemented
881 lhs
= (min(self
.opcodes
), self
.name
)
882 rhs
= (min(other
.opcodes
), other
.name
)
887 return (self
.static_operands
+ self
.dynamic_operands
)
890 def static_operands(self
):
892 operands
.append(POStaticOperand(record
=self
, value
=self
.PO
))
894 operands
.append(XOStaticOperand(
896 value
=ppc
.opcode
.value
,
897 span
=self
.section
.bitsel
,
899 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
900 operands
.append(cls(record
=self
, **kwargs
))
901 return tuple(operands
)
904 def dynamic_operands(self
):
906 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
907 operands
.append(cls(record
=self
, **kwargs
))
908 return tuple(operands
)
913 return int("".join(str(int(mapping
[bit
])) \
914 for bit
in sorted(mapping
)), 2)
916 def PO_XO(value
, mask
, opcode
, bits
):
919 for (src
, dst
) in enumerate(reversed(bits
)):
920 value
[dst
] = ((opcode
.value
& (1 << src
)) != 0)
921 mask
[dst
] = ((opcode
.mask
& (1 << src
)) != 0)
924 def PO(value
, mask
, opcode
, bits
):
925 return PO_XO(value
=value
, mask
=mask
, opcode
=opcode
, bits
=bits
)
927 def XO(value
, mask
, opcode
, bits
):
928 (value
, mask
) = PO_XO(value
=value
, mask
=mask
,
929 opcode
=opcode
, bits
=bits
)
930 for (op_cls
, op_kwargs
) in self
.mdwn
.operands
.static
:
931 operand
= op_cls(record
=self
, **op_kwargs
)
932 for (src
, dst
) in enumerate(reversed(operand
.span
)):
933 value
[dst
] = ((operand
.value
& (1 << src
)) != 0)
938 value
= {bit
:False for bit
in range(32)}
939 mask
= {bit
:False for bit
in range(32)}
940 if self
.section
.opcode
is not None:
941 (value
, mask
) = PO(value
=value
, mask
=mask
,
942 opcode
=self
.section
.opcode
, bits
=range(0, 6))
944 pairs
.append(XO(value
=value
, mask
=mask
,
945 opcode
=ppc
.opcode
, bits
=self
.section
.bitsel
))
948 for (value
, mask
) in pairs
:
949 value
= Opcode
.Value(binary(value
))
950 mask
= Opcode
.Mask(binary(mask
))
951 result
.append(Opcode(value
=value
, mask
=mask
))
957 opcode
= self
.section
.opcode
959 opcode
= self
.ppc
[0].opcode
960 if isinstance(opcode
, PatternOpcode
):
961 value
= int(opcode
.value
)
962 bits
= opcode
.value
.bit_length()
963 return int(_SelectableInt(value
=value
, bits
=bits
)[0:6])
965 return int(opcode
.value
)
969 return tuple(ppc
.opcode
for ppc
in self
.ppc
)
971 def match(self
, key
):
972 for opcode
in self
.opcodes
:
973 if opcode
.match(key
):
980 return self
.svp64
.mode
1000 if self
.svp64
is None:
1006 return self
.ppc
.cr_in
1010 return self
.ppc
.cr_in2
1014 return self
.ppc
.cr_out
1016 ptype
= property(lambda self
: self
.svp64
.ptype
)
1017 etype
= property(lambda self
: self
.svp64
.etype
)
1019 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
1020 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
1021 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
1022 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
1023 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
1024 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
1025 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
1026 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
1028 def __contains__(self
, key
):
1029 return self
.mdwn
.operands
.__contains
__(key
)
1031 def __getitem__(self
, key
):
1032 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
1033 return cls(record
=self
, **kwargs
)
1037 if "Rc" not in self
:
1039 return self
["Rc"].value
1043 def __init__(self
, record
, name
):
1044 self
.__record
= record
1048 yield ("record", self
.record
)
1049 yield ("name", self
.__name
)
1052 return f
"{self.__class__.__name__}({self.name})"
1060 return self
.__record
1064 return self
.record
.fields
[self
.name
]
1066 def assemble(self
, insn
):
1067 raise NotImplementedError()
1069 def disassemble(self
, insn
,
1070 style
=Style
.NORMAL
, indent
=""):
1071 raise NotImplementedError()
1074 class DynamicOperand(Operand
):
1075 def assemble(self
, insn
, value
):
1077 if isinstance(value
, str):
1078 value
= int(value
, 0)
1080 raise ValueError("signed operands not allowed")
1083 def disassemble(self
, insn
,
1084 style
=Style
.NORMAL
, indent
=""):
1088 if style
>= Style
.VERBOSE
:
1089 span
= map(str, span
)
1090 yield f
"{indent}{self.name}"
1091 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1092 yield f
"{indent}{indent}{', '.join(span)}"
1094 yield str(int(value
))
1097 class SignedOperand(DynamicOperand
):
1098 def assemble(self
, insn
, value
):
1099 if isinstance(value
, str):
1100 value
= int(value
, 0)
1101 return super().assemble(value
=value
, insn
=insn
)
1103 def assemble(self
, insn
, value
):
1105 if isinstance(value
, str):
1106 value
= int(value
, 0)
1109 def disassemble(self
, insn
,
1110 style
=Style
.NORMAL
, indent
=""):
1112 value
= insn
[span
].to_signed_int()
1113 sign
= "-" if (value
< 0) else ""
1116 if style
>= Style
.VERBOSE
:
1117 span
= map(str, span
)
1118 yield f
"{indent}{self.name}"
1119 yield f
"{indent}{indent}{sign}{value}"
1120 yield f
"{indent}{indent}{', '.join(span)}"
1122 yield f
"{sign}{value}"
1125 class StaticOperand(Operand
):
1126 def __init__(self
, record
, name
, value
):
1127 self
.__value
= value
1128 return super().__init
__(record
=record
, name
=name
)
1131 yield ("value", self
.__value
)
1132 yield from super().__iter
__()
1135 return f
"{self.__class__.__name__}({self.name}, value={self.value})"
1141 def assemble(self
, insn
):
1142 insn
[self
.span
] = self
.value
1144 def disassemble(self
, insn
,
1145 style
=Style
.NORMAL
, indent
=""):
1149 if style
>= Style
.VERBOSE
:
1150 span
= map(str, span
)
1151 yield f
"{indent}{self.name}"
1152 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1153 yield f
"{indent}{indent}{', '.join(span)}"
1155 yield str(int(value
))
1158 class SpanStaticOperand(StaticOperand
):
1159 def __init__(self
, record
, name
, value
, span
):
1160 self
.__span
= tuple(span
)
1161 return super().__init
__(record
=record
, name
=name
, value
=value
)
1164 yield ("span", self
.__span
)
1165 yield from super().__iter
__()
1172 class POStaticOperand(SpanStaticOperand
):
1173 def __init__(self
, record
, value
):
1174 return super().__init
__(record
=record
, name
="PO",
1175 value
=value
, span
=range(0, 6))
1178 for (key
, value
) in super().__iter
__():
1179 if key
not in {"name", "span"}:
1183 class XOStaticOperand(SpanStaticOperand
):
1184 def __init__(self
, record
, value
, span
):
1185 bits
= record
.section
.bitsel
1186 value
= _SelectableInt(value
=value
, bits
=len(bits
))
1187 span
= dict(zip(bits
, range(len(bits
))))
1188 span_rev
= {value
:key
for (key
, value
) in span
.items()}
1190 # This part is tricky: we cannot use record.operands,
1191 # as this code is called by record.static_operands method.
1192 for (cls
, kwargs
) in record
.mdwn
.operands
:
1193 operand
= cls(record
=record
, **kwargs
)
1194 for idx
in operand
.span
:
1195 rev
= span
.pop(idx
, None)
1197 span_rev
.pop(rev
, None)
1199 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1200 span
= tuple(span
.keys())
1202 return super().__init
__(record
=record
, name
="XO",
1203 value
=value
, span
=span
)
1206 for (key
, value
) in super().__iter
__():
1207 if key
not in {"name"}:
1211 class ImmediateOperand(DynamicOperand
):
1215 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1219 class NonZeroOperand(DynamicOperand
):
1220 def assemble(self
, insn
, value
):
1221 if isinstance(value
, str):
1222 value
= int(value
, 0)
1223 if not isinstance(value
, int):
1224 raise ValueError("non-integer operand")
1226 raise ValueError("non-zero operand")
1228 return super().assemble(value
=value
, insn
=insn
)
1230 def disassemble(self
, insn
,
1231 style
=Style
.NORMAL
, indent
=""):
1235 if style
>= Style
.VERBOSE
:
1236 span
= map(str, span
)
1237 yield f
"{indent}{self.name}"
1238 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1239 yield f
"{indent}{indent}{', '.join(span)}"
1241 yield str(int(value
) + 1)
1244 class ExtendableOperand(DynamicOperand
):
1245 def sv_spec_enter(self
, value
, span
):
1246 return (value
, span
)
1248 def sv_spec(self
, insn
):
1252 span
= tuple(map(str, span
))
1254 if isinstance(insn
, SVP64Instruction
):
1255 (origin_value
, origin_span
) = (value
, span
)
1256 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1258 for extra_idx
in self
.extra_idx
:
1259 if self
.record
.etype
is _SVEType
.EXTRA3
:
1260 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1261 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1262 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1264 raise ValueError(self
.record
.etype
)
1267 vector
= bool(spec
[0])
1268 spec_span
= spec
.__class
__
1269 if self
.record
.etype
is _SVEType
.EXTRA3
:
1270 spec_span
= tuple(map(str, spec_span
[1, 2]))
1272 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1273 spec_span
= tuple(map(str, spec_span
[1,]))
1274 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1277 spec_span
= (spec_span
+ ("{0}",))
1279 spec_span
= (("{0}",) + spec_span
)
1281 raise ValueError(self
.record
.etype
)
1283 vector_shift
= (2 + (5 - value
.bits
))
1284 scalar_shift
= value
.bits
1285 spec_shift
= (5 - value
.bits
)
1287 bits
= (len(span
) + len(spec_span
))
1288 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1289 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1291 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1292 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1294 value
= ((spec
<< scalar_shift
) | value
)
1295 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1297 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1298 origin_value
=origin_value
, origin_span
=origin_span
)
1300 return (vector
, value
, span
)
1302 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1303 return (value
, span
)
1306 def extra_idx(self
):
1307 for (key
, record
) in self
.record
.svp64
.extras
.items():
1308 if record
["reg"].alias
is self
.extra_reg
.alias
:
1312 def extra_reg(self
):
1313 return _Reg(self
.name
)
1315 def remap(self
, value
, vector
):
1316 raise NotImplementedError()
1318 def assemble(self
, value
, insn
, prefix
):
1321 if isinstance(value
, str):
1322 value
= value
.lower()
1323 if value
.startswith("%"):
1325 if value
.startswith("*"):
1326 if not isinstance(insn
, SVP64Instruction
):
1327 raise ValueError(value
)
1330 if value
.startswith(prefix
):
1331 if (self
.extra_reg
.or_zero
and (value
== f
"{prefix}0")):
1332 raise ValueError(value
)
1333 value
= value
[len(prefix
):]
1334 value
= int(value
, 0)
1336 if isinstance(insn
, SVP64Instruction
):
1337 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1339 for extra_idx
in self
.extra_idx
:
1340 if self
.record
.etype
is _SVEType
.EXTRA3
:
1341 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1342 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1343 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1345 raise ValueError(self
.record
.etype
)
1347 return super().assemble(value
=value
, insn
=insn
)
1349 def disassemble(self
, insn
,
1350 style
=Style
.NORMAL
, prefix
="", indent
=""):
1351 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1353 if (self
.extra_reg
.or_zero
and (value
== 0)):
1356 if style
>= Style
.VERBOSE
:
1357 mode
= "vector" if vector
else "scalar"
1358 yield f
"{indent}{self.name} ({mode})"
1359 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1360 yield f
"{indent}{indent}{', '.join(span)}"
1361 if isinstance(insn
, SVP64Instruction
):
1362 for extra_idx
in frozenset(self
.extra_idx
):
1363 if self
.record
.etype
is _SVEType
.NONE
:
1364 yield f
"{indent}{indent}extra[none]"
1366 etype
= repr(self
.record
.etype
).lower()
1367 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1369 vector
= "*" if vector
else ""
1370 yield f
"{vector}{prefix}{int(value)}"
1373 class SimpleRegisterOperand(ExtendableOperand
):
1374 def remap(self
, value
, vector
):
1376 extra
= (value
& 0b11)
1377 value
= (value
>> 2)
1379 extra
= (value
>> 5)
1380 value
= (value
& 0b11111)
1382 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1383 # (and shrink to a single bit if ok)
1384 if self
.record
.etype
is _SVEType
.EXTRA2
:
1386 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1387 assert (extra
& 0b01) == 0, \
1388 ("vector field %s cannot fit into EXTRA2" % value
)
1389 extra
= (0b10 |
(extra
>> 1))
1391 # range is r0-r63 in increments of 1
1392 assert (extra
>> 1) == 0, \
1393 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1395 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1397 # EXTRA3 vector bit needs marking
1400 raise ValueError(self
.record
.etype
)
1402 return (value
, extra
)
1405 class GPROperand(SimpleRegisterOperand
):
1406 def assemble(self
, insn
, value
):
1407 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1409 def disassemble(self
, insn
,
1410 style
=Style
.NORMAL
, indent
=""):
1411 prefix
= "" if (style
<= Style
.SHORT
) else "r"
1412 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1413 style
=style
, indent
=indent
)
1416 class GPRPairOperand(GPROperand
):
1420 class FPROperand(SimpleRegisterOperand
):
1421 def assemble(self
, insn
, value
):
1422 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1424 def disassemble(self
, insn
,
1425 style
=Style
.NORMAL
, indent
=""):
1426 prefix
= "" if (style
<= Style
.SHORT
) else "f"
1427 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1428 style
=style
, indent
=indent
)
1431 class FPRPairOperand(FPROperand
):
1435 class ConditionRegisterFieldOperand(ExtendableOperand
):
1436 def pattern(name_pattern
):
1437 (name
, pattern
) = name_pattern
1438 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1447 CR
= r
"(?:CR|cr)([0-9]+)"
1449 BIT
= rf
"({'|'.join(CONDS.keys())})"
1450 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1451 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1452 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1453 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1454 XCR
= fr
"{CR}\.{BIT}"
1455 PATTERNS
= tuple(map(pattern
, (
1460 ("BIT+CR", (LBIT
+ CR
)),
1461 ("CR+BIT", (CR
+ RBIT
)),
1462 ("BIT+CR*N", (LBIT
+ CRN
)),
1463 ("CR*N+BIT", (CRN
+ RBIT
)),
1464 ("BIT+N*CR", (LBIT
+ NCR
)),
1465 ("N*CR+BIT", (NCR
+ RBIT
)),
1468 def remap(self
, value
, vector
, regtype
):
1469 if regtype
is _RegType
.CR_5BIT
:
1470 subvalue
= (value
& 0b11)
1474 extra
= (value
& 0b1111)
1477 extra
= (value
>> 3)
1480 if self
.record
.etype
is _SVEType
.EXTRA2
:
1482 assert (extra
& 0b111) == 0, \
1483 "vector CR cannot fit into EXTRA2"
1484 extra
= (0b10 |
(extra
>> 3))
1486 assert (extra
>> 1) == 0, \
1487 "scalar CR cannot fit into EXTRA2"
1489 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1491 assert (extra
& 0b11) == 0, \
1492 "vector CR cannot fit into EXTRA3"
1493 extra
= (0b100 |
(extra
>> 2))
1495 assert (extra
>> 2) == 0, \
1496 "scalar CR cannot fit into EXTRA3"
1499 if regtype
is _RegType
.CR_5BIT
:
1500 value
= ((value
<< 2) | subvalue
)
1502 return (value
, extra
)
1504 def assemble(self
, insn
, value
):
1505 if isinstance(value
, str):
1508 if value
.startswith("*"):
1509 if not isinstance(insn
, SVP64Instruction
):
1510 raise ValueError(value
)
1514 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1515 match
= pattern
.match(value
)
1516 if match
is not None:
1517 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1518 values
= match
.groups()
1519 match
= dict(zip(keys
, values
))
1520 CR
= int(match
["CR"])
1524 N
= int(match
.get("N", "1"))
1525 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1526 value
= ((CR
* N
) + BIT
)
1533 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1535 def disassemble(self
, insn
,
1536 style
=Style
.NORMAL
, prefix
="", indent
=""):
1537 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1539 if style
>= Style
.VERBOSE
:
1540 mode
= "vector" if vector
else "scalar"
1541 yield f
"{indent}{self.name} ({mode})"
1542 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1543 yield f
"{indent}{indent}{', '.join(span)}"
1544 if isinstance(insn
, SVP64Instruction
):
1545 for extra_idx
in frozenset(self
.extra_idx
):
1546 if self
.record
.etype
is _SVEType
.NONE
:
1547 yield f
"{indent}{indent}extra[none]"
1549 etype
= repr(self
.record
.etype
).lower()
1550 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1552 vector
= "*" if vector
else ""
1553 CR
= int(value
>> 2)
1555 cond
= ("lt", "gt", "eq", "so")[CC
]
1556 if style
>= Style
.NORMAL
:
1558 if isinstance(insn
, SVP64Instruction
):
1559 yield f
"{vector}cr{CR}.{cond}"
1561 yield f
"4*cr{CR}+{cond}"
1565 yield f
"{vector}{prefix}{int(value)}"
1568 class CR3Operand(ConditionRegisterFieldOperand
):
1569 def remap(self
, value
, vector
):
1570 return super().remap(value
=value
, vector
=vector
,
1571 regtype
=_RegType
.CR_3BIT
)
1574 class CR5Operand(ConditionRegisterFieldOperand
):
1575 def remap(self
, value
, vector
):
1576 return super().remap(value
=value
, vector
=vector
,
1577 regtype
=_RegType
.CR_5BIT
)
1579 def sv_spec_enter(self
, value
, span
):
1580 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1581 return (value
, span
)
1583 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1584 value
= _selectconcat(value
, origin_value
[3:5])
1586 return (value
, span
)
1589 class EXTSOperand(SignedOperand
):
1590 field
: str # real name to report
1591 nz
: int = 0 # number of zeros
1592 fmt
: str = "d" # integer formatter
1594 def __init__(self
, record
, name
, field
, nz
=0, fmt
="d"):
1595 self
.__field
= field
1598 return super().__init
__(record
=record
, name
=name
)
1614 return self
.record
.fields
[self
.field
]
1616 def assemble(self
, insn
, value
):
1618 if isinstance(value
, str):
1619 value
= int(value
, 0)
1620 insn
[span
] = (value
>> self
.nz
)
1622 def disassemble(self
, insn
,
1623 style
=Style
.NORMAL
, indent
=""):
1625 value
= insn
[span
].to_signed_int()
1626 sign
= "-" if (value
< 0) else ""
1627 value
= (abs(value
) << self
.nz
)
1629 if style
>= Style
.VERBOSE
:
1630 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1631 zeros
= ("0" * self
.nz
)
1632 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1633 yield f
"{indent * 1}{hint}"
1634 yield f
"{indent * 2}{self.field}"
1635 yield f
"{indent * 3}{sign}{value:{self.fmt}}"
1636 yield f
"{indent * 3}{', '.join(span)}"
1638 yield f
"{sign}{value:{self.fmt}}"
1641 class TargetAddrOperand(EXTSOperand
):
1642 def __init__(self
, record
, name
, field
):
1643 return super().__init
__(record
=record
, name
=name
, field
=field
,
1647 class TargetAddrOperandLI(TargetAddrOperand
):
1648 def __init__(self
, record
, name
):
1649 return super().__init
__(record
=record
, name
=name
, field
="LI")
1652 class TargetAddrOperandBD(TargetAddrOperand
):
1653 def __init__(self
, record
, name
):
1654 return super().__init
__(record
=record
, name
=name
, field
="BD")
1657 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1658 def __init__(self
, record
, name
):
1659 return super().__init
__(record
=record
, name
=name
, field
="DS", nz
=2)
1662 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1663 def __init__(self
, record
, name
):
1664 return super().__init
__(record
=record
, name
=name
, field
="DQ", nz
=4)
1667 class DOperandDX(SignedOperand
):
1670 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1671 operands
= map(cls
, ("d0", "d1", "d2"))
1672 spans
= map(lambda operand
: operand
.span
, operands
)
1673 return sum(spans
, tuple())
1675 def disassemble(self
, insn
,
1676 style
=Style
.NORMAL
, indent
=""):
1678 value
= insn
[span
].to_signed_int()
1679 sign
= "-" if (value
< 0) else ""
1682 if style
>= Style
.VERBOSE
:
1689 for (subname
, subspan
) in mapping
.items():
1690 operand
= DynamicOperand(name
=subname
)
1692 span
= map(str, span
)
1693 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1694 yield f
"{indent}{indent}{indent}{sign}{value}"
1695 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1697 yield f
"{sign}{value}"
1700 class Instruction(_Mapping
):
1702 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1703 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1704 raise ValueError(bits
)
1706 if isinstance(value
, bytes
):
1707 if ((len(value
) * 8) != bits
):
1708 raise ValueError(f
"bit length mismatch")
1709 value
= int.from_bytes(value
, byteorder
=byteorder
)
1711 if isinstance(value
, int):
1712 value
= _SelectableInt(value
=value
, bits
=bits
)
1713 elif isinstance(value
, Instruction
):
1714 value
= value
.storage
1716 if not isinstance(value
, _SelectableInt
):
1717 raise ValueError(value
)
1720 if len(value
) != bits
:
1721 raise ValueError(value
)
1723 value
= _SelectableInt(value
=value
, bits
=bits
)
1725 return cls(storage
=value
)
1728 return hash(int(self
))
1730 def __getitem__(self
, key
):
1731 return self
.storage
.__getitem
__(key
)
1733 def __setitem__(self
, key
, value
):
1734 return self
.storage
.__setitem
__(key
, value
)
1736 def bytes(self
, byteorder
="little"):
1737 nr_bytes
= (len(self
.__class
__) // 8)
1738 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1741 def record(cls
, db
, entry
):
1744 raise KeyError(entry
)
1748 def operands(cls
, record
):
1749 yield from record
.operands
1752 def static_operands(cls
, record
):
1753 return filter(lambda operand
: isinstance(operand
, StaticOperand
),
1754 cls
.operands(record
=record
))
1757 def dynamic_operands(cls
, record
):
1758 return filter(lambda operand
: isinstance(operand
, DynamicOperand
),
1759 cls
.operands(record
=record
))
1761 def spec(self
, record
, prefix
):
1762 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1763 self
.spec_dynamic_operands(record
=record
)))
1765 static_operands
= []
1766 for (name
, value
) in self
.spec_static_operands(record
=record
):
1767 static_operands
.append(f
"{name}={value}")
1770 if dynamic_operands
:
1772 operands
+= ",".join(dynamic_operands
)
1775 operands
+= " ".join(static_operands
)
1777 return f
"{prefix}{record.name}{operands}"
1779 def spec_static_operands(self
, record
):
1780 for operand
in self
.static_operands(record
=record
):
1781 if not isinstance(operand
, (POStaticOperand
, XOStaticOperand
)):
1782 yield (operand
.name
, operand
.value
)
1784 def spec_dynamic_operands(self
, record
, style
=Style
.NORMAL
):
1788 for operand
in self
.dynamic_operands(record
=record
):
1790 value
= " ".join(operand
.disassemble(insn
=self
,
1791 style
=min(style
, Style
.NORMAL
)))
1793 name
= f
"{imm_name}({name})"
1794 value
= f
"{imm_value}({value})"
1796 if isinstance(operand
, ImmediateOperand
):
1804 def assemble(cls
, record
, arguments
=None):
1805 if arguments
is None:
1808 insn
= cls
.integer(value
=0)
1810 for operand
in cls
.static_operands(record
=record
):
1811 operand
.assemble(insn
=insn
)
1813 arguments
= Arguments(record
=record
,
1814 arguments
=arguments
, operands
=cls
.dynamic_operands(record
=record
))
1815 for (value
, operand
) in arguments
:
1816 operand
.assemble(insn
=insn
, value
=value
)
1820 def disassemble(self
, record
,
1822 style
=Style
.NORMAL
):
1823 raise NotImplementedError()
1826 class WordInstruction(Instruction
):
1827 _
: _Field
= range(0, 32)
1828 PO
: _Field
= range(0, 6)
1831 def integer(cls
, value
, byteorder
="little"):
1832 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1837 for idx
in range(32):
1838 bit
= int(self
[idx
])
1840 return "".join(map(str, bits
))
1842 def disassemble(self
, record
,
1844 style
=Style
.NORMAL
):
1845 if style
<= Style
.SHORT
:
1848 blob
= self
.bytes(byteorder
=byteorder
)
1849 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1853 yield f
"{blob}.long 0x{int(self):08x}"
1856 # awful temporary hack: workaround for ld-update
1857 # https://bugs.libre-soc.org/show_bug.cgi?id=1056#c2
1858 # XXX TODO must check that *EXTENDED* RA != extended-RT
1859 if (record
.svp64
is not None and
1860 record
.mode
== _SVMode
.LDST_IMM
and
1861 'u' in record
.name
):
1862 yield f
"{blob}.long 0x{int(self):08x}"
1866 if style
is Style
.LEGACY
:
1868 for operand
in self
.dynamic_operands(record
=record
):
1869 if isinstance(operand
, (GPRPairOperand
, FPRPairOperand
)):
1872 if style
is Style
.LEGACY
and (paired
or record
.ppc
.unofficial
):
1873 yield f
"{blob}.long 0x{int(self):08x}"
1875 operands
= tuple(map(_operator
.itemgetter(1),
1876 self
.spec_dynamic_operands(record
=record
, style
=style
)))
1878 operands
= ",".join(operands
)
1879 yield f
"{blob}{record.name} {operands}"
1881 yield f
"{blob}{record.name}"
1883 if style
>= Style
.VERBOSE
:
1885 binary
= self
.binary
1886 spec
= self
.spec(record
=record
, prefix
="")
1887 yield f
"{indent}spec"
1888 yield f
"{indent}{indent}{spec}"
1889 yield f
"{indent}pcode"
1890 for stmt
in record
.mdwn
.pcode
:
1891 yield f
"{indent}{indent}{stmt}"
1892 yield f
"{indent}binary"
1893 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1894 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1895 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1896 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1897 yield f
"{indent}opcodes"
1898 for opcode
in record
.opcodes
:
1899 yield f
"{indent}{indent}{opcode!r}"
1900 for operand
in self
.operands(record
=record
):
1901 yield from operand
.disassemble(insn
=self
,
1902 style
=style
, indent
=indent
)
1906 class PrefixedInstruction(Instruction
):
1907 class Prefix(WordInstruction
.remap(range(0, 32))):
1910 class Suffix(WordInstruction
.remap(range(32, 64))):
1913 _
: _Field
= range(64)
1919 def integer(cls
, value
, byteorder
="little"):
1920 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
1923 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
1924 def transform(value
):
1925 return WordInstruction
.integer(value
=value
,
1926 byteorder
=byteorder
)[0:32]
1928 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
1929 value
= _selectconcat(prefix
, suffix
)
1931 return super().integer(bits
=64, value
=value
)
1934 class Mode(_Mapping
):
1935 _
: _Field
= range(0, 5)
1936 sel
: _Field
= (0, 1)
1939 class ExtraRM(_Mapping
):
1940 _
: _Field
= range(0, 9)
1943 class Extra2RM(ExtraRM
):
1944 idx0
: _Field
= range(0, 2)
1945 idx1
: _Field
= range(2, 4)
1946 idx2
: _Field
= range(4, 6)
1947 idx3
: _Field
= range(6, 8)
1949 def __getitem__(self
, key
):
1955 _SVExtra
.Idx0
: self
.idx0
,
1956 _SVExtra
.Idx1
: self
.idx1
,
1957 _SVExtra
.Idx2
: self
.idx2
,
1958 _SVExtra
.Idx3
: self
.idx3
,
1961 def __setitem__(self
, key
, value
):
1962 self
[key
].assign(value
)
1965 class Extra3RM(ExtraRM
):
1966 idx0
: _Field
= range(0, 3)
1967 idx1
: _Field
= range(3, 6)
1968 idx2
: _Field
= range(6, 9)
1970 def __getitem__(self
, key
):
1975 _SVExtra
.Idx0
: self
.idx0
,
1976 _SVExtra
.Idx1
: self
.idx1
,
1977 _SVExtra
.Idx2
: self
.idx2
,
1980 def __setitem__(self
, key
, value
):
1981 self
[key
].assign(value
)
1984 class BaseRM(_Mapping
):
1985 _
: _Field
= range(24)
1986 mmode
: _Field
= (0,)
1987 mask
: _Field
= range(1, 4)
1988 elwidth
: _Field
= range(4, 6)
1989 ewsrc
: _Field
= range(6, 8)
1990 subvl
: _Field
= range(8, 10)
1991 mode
: Mode
.remap(range(19, 24))
1992 smask_extra322
: _Field
= (6,7,18,) # LDST_IDX is EXTRA332
1993 smask
: _Field
= range(16, 19) # everything else use this
1994 extra
: ExtraRM
.remap(range(10, 19))
1995 extra2
: Extra2RM
.remap(range(10, 19))
1996 extra3
: Extra3RM
.remap(range(10, 19))
1997 # XXX extra332 = (extra3[0], extra3[1], extra2[3])
1999 def specifiers(self
, record
):
2000 subvl
= int(self
.subvl
)
2008 def disassemble(self
, style
=Style
.NORMAL
):
2009 if style
>= Style
.VERBOSE
:
2011 for (name
, span
) in self
.traverse(path
="RM"):
2012 value
= self
.storage
[span
]
2014 yield f
"{indent}{int(value):0{value.bits}b}"
2015 yield f
"{indent}{', '.join(map(str, span))}"
2018 class FFRc1BaseRM(BaseRM
):
2019 def specifiers(self
, record
, mode
):
2020 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
2021 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
2022 mask
= int(_selectconcat(CR
, inv
))
2023 predicate
= PredicateBaseRM
.predicate(True, mask
)
2024 yield f
"{mode}={predicate}"
2026 yield from super().specifiers(record
=record
)
2029 class FFRc0BaseRM(BaseRM
):
2030 def specifiers(self
, record
, mode
):
2032 inv
= "~" if self
.inv
else ""
2033 yield f
"{mode}={inv}RC1"
2035 yield from super().specifiers(record
=record
)
2038 class SatBaseRM(BaseRM
):
2039 def specifiers(self
, record
):
2045 yield from super().specifiers(record
=record
)
2048 class ZZBaseRM(BaseRM
):
2049 def specifiers(self
, record
):
2053 yield from super().specifiers(record
=record
)
2056 class ZZCombinedBaseRM(BaseRM
):
2057 def specifiers(self
, record
):
2058 if self
.sz
and self
.dz
:
2065 yield from super().specifiers(record
=record
)
2068 class DZBaseRM(BaseRM
):
2069 def specifiers(self
, record
):
2073 yield from super().specifiers(record
=record
)
2076 class SZBaseRM(BaseRM
):
2077 def specifiers(self
, record
):
2081 yield from super().specifiers(record
=record
)
2084 class MRBaseRM(BaseRM
):
2085 def specifiers(self
, record
):
2091 yield from super().specifiers(record
=record
)
2094 class ElsBaseRM(BaseRM
):
2095 def specifiers(self
, record
):
2099 yield from super().specifiers(record
=record
)
2102 class WidthBaseRM(BaseRM
):
2104 def width(FP
, width
):
2113 width
= ("fp" + width
)
2116 def specifiers(self
, record
):
2117 # elwidths: use "w=" if same otherwise dw/sw
2118 # FIXME this should consider FP instructions
2120 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
2121 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2122 if record
.svp64
.mode
is _SVMode
.CROP
:
2126 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2135 yield from super().specifiers(record
=record
)
2138 class PredicateBaseRM(BaseRM
):
2140 def predicate(CR
, mask
):
2143 (False, 0b001): "1<<r3",
2144 (False, 0b010): "r3",
2145 (False, 0b011): "~r3",
2146 (False, 0b100): "r10",
2147 (False, 0b101): "~r10",
2148 (False, 0b110): "r30",
2149 (False, 0b111): "~r30",
2151 (True, 0b000): "lt",
2152 (True, 0b001): "ge",
2153 (True, 0b010): "gt",
2154 (True, 0b011): "le",
2155 (True, 0b100): "eq",
2156 (True, 0b101): "ne",
2157 (True, 0b110): "so",
2158 (True, 0b111): "ns",
2161 def specifiers(self
, record
):
2162 # predication - single and twin
2163 # use "m=" if same otherwise sm/dm
2164 CR
= (int(self
.mmode
) == 1)
2165 mask
= int(self
.mask
)
2166 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
2167 if record
.svp64
.ptype
is _SVPType
.P2
:
2168 # LDST_IDX smask moving to extra322 but not straight away (False)
2169 if False and record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2170 smask
= int(self
.smask_extra332
)
2172 smask
= int(self
.smask
)
2173 sm
= PredicateBaseRM
.predicate(CR
, smask
)
2182 yield from super().specifiers(record
=record
)
2185 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
2189 class SEABaseRM(BaseRM
):
2190 def specifiers(self
, record
):
2194 yield from super().specifiers(record
=record
)
2197 class VLiBaseRM(BaseRM
):
2198 def specifiers(self
, record
):
2202 yield from super().specifiers(record
=record
)
2205 class NormalBaseRM(PredicateWidthBaseRM
):
2208 https://libre-soc.org/openpower/sv/normal/
2213 class NormalSimpleRM(ZZCombinedBaseRM
, NormalBaseRM
):
2214 """normal: simple mode"""
2218 def specifiers(self
, record
):
2219 yield from super().specifiers(record
=record
)
2222 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
2223 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
2227 class NormalFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, NormalBaseRM
):
2228 """normal: Rc=1: ffirst CR sel"""
2231 CR
: BaseRM
.mode
[3, 4]
2233 def specifiers(self
, record
):
2234 yield from super().specifiers(record
=record
, mode
="ff")
2237 class NormalFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
2238 """normal: Rc=0: ffirst z/nonz"""
2243 def specifiers(self
, record
):
2244 yield from super().specifiers(record
=record
, mode
="ff")
2247 class NormalSatRM(SatBaseRM
, ZZCombinedBaseRM
, NormalBaseRM
):
2248 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2254 class NormalRM(NormalBaseRM
):
2255 simple
: NormalSimpleRM
2257 ffrc1
: NormalFFRc1RM
2258 ffrc0
: NormalFFRc0RM
2262 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2264 LD/ST Immediate mode
2265 https://libre-soc.org/openpower/sv/ldst/
2270 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2271 """ld/st immediate: simple mode"""
2272 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2273 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2279 def specifiers(self
, record
):
2285 yield from super().specifiers(record
=record
)
2288 class LDSTFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2289 """ld/st immediate&indexed: Rc=1: ffirst CR sel"""
2292 CR
: BaseRM
.mode
[3, 4]
2294 def specifiers(self
, record
):
2295 yield from super().specifiers(record
=record
, mode
="ff")
2298 class LDSTFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2299 """ld/st immediate&indexed: Rc=0: ffirst z/nonz"""
2304 def specifiers(self
, record
):
2305 yield from super().specifiers(record
=record
, mode
="ff")
2308 class LDSTImmRM(LDSTImmBaseRM
):
2309 simple
: LDSTImmSimpleRM
2314 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2317 https://libre-soc.org/openpower/sv/ldst/
2322 class LDSTIdxSimpleRM(SEABaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2323 """ld/st index: simple mode (includes element-strided and Signed-EA)"""
2324 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2331 def specifiers(self
, record
):
2337 yield from super().specifiers(record
=record
)
2340 class LDSTIdxRM(LDSTIdxBaseRM
):
2341 simple
: LDSTIdxSimpleRM
2347 class CROpBaseRM(BaseRM
):
2350 https://libre-soc.org/openpower/sv/cr_ops/
2355 class CROpSimpleRM(PredicateBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2356 """crop: simple mode"""
2361 def specifiers(self
, record
):
2363 yield "rg" # simple CR Mode reports /rg
2365 yield from super().specifiers(record
=record
)
2368 class CROpMRRM(MRBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2369 """crop: scalar reduce mode (mapreduce)"""
2375 class CROpFF5RM(FFRc0BaseRM
, PredicateBaseRM
, VLiBaseRM
, DZBaseRM
,
2376 SZBaseRM
, CROpBaseRM
):
2377 """crop: ffirst 5-bit mode"""
2384 def specifiers(self
, record
):
2385 yield from super().specifiers(record
=record
, mode
="ff")
2388 # FIXME: almost everything in this class contradicts the specs (it doesn't)
2389 # The modes however are swapped: 5-bit is 3-bit, 3-bit is 5-bit
2390 class CROpFF3RM(FFRc1BaseRM
, PredicateBaseRM
, VLiBaseRM
, ZZBaseRM
, CROpBaseRM
):
2391 """cr_op: ffirst 3-bit mode"""
2397 def specifiers(self
, record
):
2398 yield from super().specifiers(record
=record
, mode
="ff")
2401 class CROpRM(CROpBaseRM
):
2402 simple
: CROpSimpleRM
2408 # ********************
2410 # https://libre-soc.org/openpower/sv/branches/
2411 class BranchBaseRM(BaseRM
):
2421 def specifiers(self
, record
):
2433 raise ValueError(self
.sz
)
2445 # Branch modes lack source mask.
2446 # Therefore a custom code is needed.
2447 CR
= (int(self
.mmode
) == 1)
2448 mask
= int(self
.mask
)
2449 m
= PredicateBaseRM
.predicate(CR
, mask
)
2453 yield from super().specifiers(record
=record
)
2456 class BranchSimpleRM(BranchBaseRM
):
2457 """branch: simple mode"""
2461 class BranchVLSRM(BranchBaseRM
):
2462 """branch: VLSET mode"""
2466 def specifiers(self
, record
):
2472 }[int(self
.VSb
), int(self
.VLi
)]
2474 yield from super().specifiers(record
=record
)
2477 class BranchCTRRM(BranchBaseRM
):
2478 """branch: CTR-test mode"""
2481 def specifiers(self
, record
):
2487 yield from super().specifiers(record
=record
)
2490 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2491 """branch: CTR-test+VLSET mode"""
2495 class BranchRM(BranchBaseRM
):
2496 simple
: BranchSimpleRM
2499 ctrvls
: BranchCTRVLSRM
2510 @_dataclasses.dataclass(eq
=True, frozen
=True)
2515 def match(cls
, desc
, record
):
2516 raise NotImplementedError()
2518 def validate(self
, others
):
2521 def assemble(self
, insn
):
2522 raise NotImplementedError()
2525 @_dataclasses.dataclass(eq
=True, frozen
=True)
2526 class SpecifierWidth(Specifier
):
2530 def match(cls
, desc
, record
, etalon
):
2531 (mode
, _
, value
) = desc
.partition("=")
2533 value
= value
.strip()
2536 width
= _SVP64Width(value
)
2538 return cls(record
=record
, width
=width
)
2541 @_dataclasses.dataclass(eq
=True, frozen
=True)
2542 class SpecifierW(SpecifierWidth
):
2544 def match(cls
, desc
, record
):
2545 return super().match(desc
=desc
, record
=record
, etalon
="w")
2547 def assemble(self
, insn
):
2548 selector
= insn
.select(record
=self
.record
)
2549 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2550 selector
.ewsrc
= self
.width
.value
2551 selector
.elwidth
= self
.width
.value
2554 @_dataclasses.dataclass(eq
=True, frozen
=True)
2555 class SpecifierSW(SpecifierWidth
):
2557 def match(cls
, desc
, record
):
2558 if record
.svp64
.mode
is _SVMode
.CROP
:
2560 return super().match(desc
=desc
, record
=record
, etalon
="sw")
2562 def assemble(self
, insn
):
2563 selector
= insn
.select(record
=self
.record
)
2564 selector
.ewsrc
= self
.width
.value
2567 @_dataclasses.dataclass(eq
=True, frozen
=True)
2568 class SpecifierDW(SpecifierWidth
):
2570 def match(cls
, desc
, record
):
2571 return super().match(desc
=desc
, record
=record
, etalon
="dw")
2573 def assemble(self
, insn
):
2574 selector
= insn
.select(record
=self
.record
)
2575 selector
.elwidth
= self
.width
.value
2578 @_dataclasses.dataclass(eq
=True, frozen
=True)
2579 class SpecifierSubVL(Specifier
):
2583 def match(cls
, desc
, record
):
2585 value
= _SVP64SubVL(desc
)
2589 return cls(record
=record
, value
=value
)
2591 def assemble(self
, insn
):
2592 selector
= insn
.select(record
=self
.record
)
2593 selector
.subvl
= int(self
.value
.value
)
2596 @_dataclasses.dataclass(eq
=True, frozen
=True)
2597 class SpecifierPredicate(Specifier
):
2602 def match(cls
, desc
, record
, mode_match
, pred_match
):
2603 (mode
, _
, pred
) = desc
.partition("=")
2606 if not mode_match(mode
):
2609 pred
= _SVP64Pred(pred
.strip())
2610 if not pred_match(pred
):
2611 raise ValueError(pred
)
2613 return cls(record
=record
, mode
=mode
, pred
=pred
)
2616 @_dataclasses.dataclass(eq
=True, frozen
=True)
2617 class SpecifierFF(SpecifierPredicate
):
2619 def match(cls
, desc
, record
):
2620 return super().match(desc
=desc
, record
=record
,
2621 mode_match
=lambda mode_arg
: mode_arg
== "ff",
2622 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2627 def assemble(self
, insn
):
2628 selector
= insn
.select(record
=self
.record
)
2629 if selector
.mode
.sel
!= 0:
2630 raise ValueError("cannot override mode")
2631 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2632 selector
.mode
.sel
= 0b01
2633 # HACK: please finally provide correct logic for CRs.
2634 if self
.pred
in (_SVP64Pred
.RC1
, _SVP64Pred
.RC1_N
):
2635 selector
.mode
[2] = (self
.pred
is _SVP64Pred
.RC1_N
)
2637 selector
.mode
[2] = self
.pred
.inv
2638 selector
.mode
[3, 4] = self
.pred
.state
2640 selector
.mode
.sel
= 0b01 if self
.mode
== "ff" else 0b11
2641 selector
.inv
= self
.pred
.inv
2643 selector
.CR
= self
.pred
.state
2645 selector
.RC1
= self
.pred
.state
2648 @_dataclasses.dataclass(eq
=True, frozen
=True)
2649 class SpecifierMask(SpecifierPredicate
):
2651 def match(cls
, desc
, record
, mode
):
2652 return super().match(desc
=desc
, record
=record
,
2653 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2654 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2659 def assemble(self
, insn
):
2660 raise NotImplementedError()
2663 @_dataclasses.dataclass(eq
=True, frozen
=True)
2664 class SpecifierM(SpecifierMask
):
2666 def match(cls
, desc
, record
):
2667 return super().match(desc
=desc
, record
=record
, mode
="m")
2669 def validate(self
, others
):
2671 if isinstance(spec
, SpecifierSM
):
2672 raise ValueError("source-mask and predicate mask conflict")
2673 elif isinstance(spec
, SpecifierDM
):
2674 raise ValueError("dest-mask and predicate mask conflict")
2676 def assemble(self
, insn
):
2677 selector
= insn
.select(record
=self
.record
)
2678 selector
.mask
= int(self
.pred
)
2679 if ((self
.record
.ptype
is _SVPType
.P2
) and
2680 (self
.record
.svp64
.mode
is not _SVMode
.BRANCH
)):
2681 selector
.smask
= int(self
.pred
)
2682 # LDST_IDX smask moving to extra322 but not straight away (False)
2683 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2684 selector
.smask_extra332
= int(self
.pred
)
2686 selector
.smask
= int(self
.pred
)
2688 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2691 @_dataclasses.dataclass(eq
=True, frozen
=True)
2692 class SpecifierSM(SpecifierMask
):
2694 def match(cls
, desc
, record
):
2695 return super().match(desc
=desc
, record
=record
, mode
="sm")
2697 def validate(self
, others
):
2698 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2699 raise ValueError("source-mask on non-twin predicate")
2701 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2704 if isinstance(spec
, SpecifierDM
):
2708 raise ValueError("missing dest-mask in CR twin predication")
2709 if self
.pred
.mode
!= twin
.pred
.mode
:
2710 raise ValueError(f
"predicate masks mismatch: "
2711 f
"{self.pred!r} vs {twin.pred!r}")
2713 def assemble(self
, insn
):
2714 selector
= insn
.select(record
=self
.record
)
2715 # LDST_IDX smask moving to extra322 but not straight away (False)
2716 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2717 selector
.smask_extra332
= int(self
.pred
)
2719 selector
.smask
= int(self
.pred
)
2720 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2723 @_dataclasses.dataclass(eq
=True, frozen
=True)
2724 class SpecifierDM(SpecifierMask
):
2726 def match(cls
, desc
, record
):
2727 return super().match(desc
=desc
, record
=record
, mode
="dm")
2729 def validate(self
, others
):
2730 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2731 raise ValueError("dest-mask on non-twin predicate")
2733 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2736 if isinstance(spec
, SpecifierSM
):
2740 raise ValueError("missing source-mask in CR twin predication")
2741 if self
.pred
.mode
!= twin
.pred
.mode
:
2742 raise ValueError(f
"predicate masks mismatch: "
2743 f
"{self.pred!r} vs {twin.pred!r}")
2745 def assemble(self
, insn
):
2746 selector
= insn
.select(record
=self
.record
)
2747 selector
.mask
= int(self
.pred
)
2748 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2751 @_dataclasses.dataclass(eq
=True, frozen
=True)
2752 class SpecifierZZ(Specifier
):
2754 def match(cls
, desc
, record
):
2758 return cls(record
=record
)
2760 def validate(self
, others
):
2762 # Since zz takes precedence (overrides) sz and dz,
2763 # treat them as mutually exclusive.
2764 if isinstance(spec
, (SpecifierSZ
, SpecifierDZ
)):
2765 raise ValueError("mutually exclusive predicate masks")
2767 def assemble(self
, insn
):
2768 selector
= insn
.select(record
=self
.record
)
2769 if hasattr(selector
, "zz"): # this should be done in a different way
2776 @_dataclasses.dataclass(eq
=True, frozen
=True)
2777 class SpecifierXZ(Specifier
):
2779 hint
: str = _dataclasses
.field(repr=False)
2782 def match(cls
, desc
, record
, etalon
, hint
):
2786 return cls(desc
=desc
, record
=record
, hint
=hint
)
2788 def validate(self
, others
):
2789 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2790 raise ValueError(f
"{self.hint} on non-twin predicate")
2792 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2795 if isinstance(spec
, SpecifierXZ
):
2799 raise ValueError(f
"missing {self.hint} in CR twin predication")
2800 if self
.pred
!= twin
.pred
:
2801 raise ValueError(f
"predicate masks mismatch: "
2802 f
"{self.pred!r} vs {twin.pred!r}")
2804 def assemble(self
, insn
):
2805 selector
= insn
.select(record
=self
.record
)
2806 setattr(selector
, self
.desc
, 1)
2809 @_dataclasses.dataclass(eq
=True, frozen
=True)
2810 class SpecifierSZ(SpecifierXZ
):
2812 def match(cls
, desc
, record
):
2813 return super().match(desc
=desc
, record
=record
,
2814 etalon
="sz", hint
="source-mask")
2816 def validate(self
, others
):
2818 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2819 if isinstance(spec
, SpecifierFF
):
2820 raise ValueError("source-zero not allowed in ff mode")
2823 @_dataclasses.dataclass(eq
=True, frozen
=True)
2824 class SpecifierDZ(SpecifierXZ
):
2826 def match(cls
, desc
, record
):
2827 return super().match(desc
=desc
, record
=record
,
2828 etalon
="dz", hint
="dest-mask")
2830 def validate(self
, others
):
2832 if ((self
.record
.svp64
.mode
is not _SVMode
.CROP
) and
2833 isinstance(spec
, SpecifierFF
) and
2834 (spec
.pred
.mode
is _SVP64PredMode
.RC1
)):
2835 raise ValueError(f
"dest-zero not allowed in ff mode BO")
2838 @_dataclasses.dataclass(eq
=True, frozen
=True)
2839 class SpecifierEls(Specifier
):
2841 def match(cls
, desc
, record
):
2845 if record
.svp64
.mode
not in (_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
):
2846 raise ValueError("els is only valid in ld/st modes, not "
2847 "%s" % str(self
.record
.svp64
.mode
))
2849 return cls(record
=record
)
2851 def assemble(self
, insn
):
2852 if self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
: # stride mode
2853 insn
.prefix
.rm
.mode
[1] = 0
2855 selector
= insn
.select(record
=self
.record
)
2860 @_dataclasses.dataclass(eq
=True, frozen
=True)
2861 class SpecifierSEA(Specifier
):
2863 def match(cls
, desc
, record
):
2867 return cls(record
=record
)
2869 def validate(self
, others
):
2870 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
:
2871 raise ValueError("sea is only valid in ld/st modes, not "
2872 "%s" % str(self
.record
.svp64
.mode
))
2875 if isinstance(spec
, SpecifierFF
):
2876 raise ValueError(f
"sea cannot be used in ff mode")
2878 def assemble(self
, insn
):
2879 selector
= insn
.select(record
=self
.record
)
2880 if selector
.mode
.sel
not in (0b10, 0b00):
2881 raise ValueError("sea is only valid for normal and els modes, "
2882 "not %d" % int(selector
.mode
.sel
))
2886 @_dataclasses.dataclass(eq
=True, frozen
=True)
2887 class SpecifierSat(Specifier
):
2892 def match(cls
, desc
, record
, etalon
, sign
):
2896 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.LDST_IMM
,
2898 raise ValueError("only normal, ld/st imm and "
2899 "ld/st idx modes supported")
2901 return cls(record
=record
, desc
=desc
, sign
=sign
)
2903 def assemble(self
, insn
):
2904 selector
= insn
.select(record
=self
.record
)
2905 selector
.mode
[0] = 0b1
2906 selector
.mode
[1] = 0b0
2907 selector
.N
= int(self
.sign
)
2910 @_dataclasses.dataclass(eq
=True, frozen
=True)
2911 class SpecifierSatS(SpecifierSat
):
2913 def match(cls
, desc
, record
):
2914 return super().match(desc
=desc
, record
=record
,
2915 etalon
="sats", sign
=True)
2918 @_dataclasses.dataclass(eq
=True, frozen
=True)
2919 class SpecifierSatU(SpecifierSat
):
2921 def match(cls
, desc
, record
):
2922 return super().match(desc
=desc
, record
=record
,
2923 etalon
="satu", sign
=False)
2926 @_dataclasses.dataclass(eq
=True, frozen
=True)
2927 class SpecifierMapReduce(Specifier
):
2931 def match(cls
, record
, RG
):
2932 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2933 raise ValueError("only normal and crop modes supported")
2935 return cls(record
=record
, RG
=RG
)
2937 def assemble(self
, insn
):
2938 selector
= insn
.select(record
=self
.record
)
2939 if self
.record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2940 raise ValueError("only normal and crop modes supported")
2941 selector
.mode
[0] = 0
2942 selector
.mode
[1] = 0
2943 selector
.mode
[2] = 1
2944 selector
.RG
= self
.RG
2947 @_dataclasses.dataclass(eq
=True, frozen
=True)
2948 class SpecifierMR(SpecifierMapReduce
):
2950 def match(cls
, desc
, record
):
2954 return super().match(record
=record
, RG
=False)
2957 @_dataclasses.dataclass(eq
=True, frozen
=True)
2958 class SpecifierMRR(SpecifierMapReduce
):
2960 def match(cls
, desc
, record
):
2964 return super().match(record
=record
, RG
=True)
2967 @_dataclasses.dataclass(eq
=True, frozen
=True)
2968 class SpecifierBranch(Specifier
):
2970 def match(cls
, desc
, record
, etalon
):
2974 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
2975 raise ValueError("only branch modes supported")
2977 return cls(record
=record
)
2980 @_dataclasses.dataclass(eq
=True, frozen
=True)
2981 class SpecifierAll(SpecifierBranch
):
2983 def match(cls
, desc
, record
):
2984 return super().match(desc
=desc
, record
=record
, etalon
="all")
2986 def assemble(self
, insn
):
2987 selector
= insn
.select(record
=self
.record
)
2991 @_dataclasses.dataclass(eq
=True, frozen
=True)
2992 class SpecifierSNZ(Specifier
):
2994 def match(cls
, desc
, record
):
2998 if record
.svp64
.mode
not in (_SVMode
.BRANCH
, _SVMode
.CROP
):
2999 raise ValueError("only branch and crop modes supported")
3001 return cls(record
=record
)
3003 def assemble(self
, insn
):
3004 selector
= insn
.select(record
=self
.record
)
3005 if self
.record
.svp64
.mode
in (_SVMode
.CROP
, _SVMode
.BRANCH
):
3007 if self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3010 raise ValueError("only branch and crop modes supported")
3013 @_dataclasses.dataclass(eq
=True, frozen
=True)
3014 class SpecifierSL(SpecifierBranch
):
3016 def match(cls
, desc
, record
):
3017 return super().match(desc
=desc
, record
=record
, etalon
="sl")
3019 def assemble(self
, insn
):
3020 selector
= insn
.select(record
=self
.record
)
3024 @_dataclasses.dataclass(eq
=True, frozen
=True)
3025 class SpecifierSLu(SpecifierBranch
):
3027 def match(cls
, desc
, record
):
3028 return super().match(desc
=desc
, record
=record
, etalon
="slu")
3030 def assemble(self
, insn
):
3031 selector
= insn
.select(record
=self
.record
)
3035 @_dataclasses.dataclass(eq
=True, frozen
=True)
3036 class SpecifierLRu(SpecifierBranch
):
3038 def match(cls
, desc
, record
):
3039 return super().match(desc
=desc
, record
=record
, etalon
="lru")
3041 def assemble(self
, insn
):
3042 selector
= insn
.select(record
=self
.record
)
3046 @_dataclasses.dataclass(eq
=True, frozen
=True)
3047 class SpecifierVSXX(SpecifierBranch
):
3052 def match(cls
, desc
, record
, etalon
, VSb
, VLi
):
3056 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3057 raise ValueError("only branch modes supported")
3059 return cls(record
=record
, VSb
=VSb
, VLi
=VLi
)
3061 def assemble(self
, insn
):
3062 selector
= insn
.select(record
=self
.record
)
3064 selector
.VSb
= int(self
.VSb
)
3065 selector
.VLi
= int(self
.VLi
)
3068 @_dataclasses.dataclass(eq
=True, frozen
=True)
3069 class SpecifierVS(SpecifierVSXX
):
3071 def match(cls
, desc
, record
):
3072 return super().match(desc
=desc
, record
=record
,
3073 etalon
="vs", VSb
=False, VLi
=False)
3076 @_dataclasses.dataclass(eq
=True, frozen
=True)
3077 class SpecifierVSi(SpecifierVSXX
):
3079 def match(cls
, desc
, record
):
3080 return super().match(desc
=desc
, record
=record
,
3081 etalon
="vsi", VSb
=False, VLi
=True)
3084 @_dataclasses.dataclass(eq
=True, frozen
=True)
3085 class SpecifierVSb(SpecifierVSXX
):
3087 def match(cls
, desc
, record
):
3088 return super().match(desc
=desc
, record
=record
,
3089 etalon
="vsb", VSb
=True, VLi
=False)
3092 @_dataclasses.dataclass(eq
=True, frozen
=True)
3093 class SpecifierVSbi(SpecifierVSXX
):
3095 def match(cls
, desc
, record
):
3096 return super().match(desc
=desc
, record
=record
,
3097 etalon
="vsbi", VSb
=True, VLi
=True)
3100 @_dataclasses.dataclass(eq
=True, frozen
=True)
3101 class SpecifierCTX(Specifier
):
3105 def match(cls
, desc
, record
, etalon
, CTi
):
3109 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3110 raise ValueError("only branch modes supported")
3112 return cls(record
=record
, CTi
=CTi
)
3114 def assemble(self
, insn
):
3115 selector
= insn
.select(record
=self
.record
)
3117 selector
.CTi
= int(self
.CTi
)
3120 @_dataclasses.dataclass(eq
=True, frozen
=True)
3121 class SpecifierCTR(SpecifierCTX
):
3123 def match(cls
, desc
, record
):
3124 return super().match(desc
=desc
, record
=record
,
3125 etalon
="ctr", CTi
=False)
3128 @_dataclasses.dataclass(eq
=True, frozen
=True)
3129 class SpecifierCTi(SpecifierCTX
):
3131 def match(cls
, desc
, record
):
3132 return super().match(desc
=desc
, record
=record
,
3133 etalon
="cti", CTi
=True)
3136 @_dataclasses.dataclass(eq
=True, frozen
=True)
3137 class SpecifierPI(Specifier
):
3139 def match(cls
, desc
, record
):
3143 if record
.svp64
.mode
not in [_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
]:
3144 raise ValueError("only ld/st imm/idx mode supported")
3146 return cls(record
=record
)
3148 def assemble(self
, insn
):
3149 selector
= insn
.select(record
=self
.record
)
3150 selector
.mode
[2] = 0b1
3154 @_dataclasses.dataclass(eq
=True, frozen
=True)
3155 class SpecifierLF(Specifier
):
3157 def match(cls
, desc
, record
):
3161 if record
.svp64
.mode
is not _SVMode
.LDST_IMM
:
3162 raise ValueError("only ld/st imm mode supported")
3164 return cls(record
=record
)
3166 def assemble(self
, insn
):
3167 selector
= insn
.select(record
=self
.record
)
3168 selector
.mode
[1] = 0
3172 @_dataclasses.dataclass(eq
=True, frozen
=True)
3173 class SpecifierVLi(Specifier
):
3175 def match(cls
, desc
, record
):
3179 return cls(record
=record
)
3181 def validate(self
, others
):
3183 if isinstance(spec
, SpecifierFF
):
3186 raise ValueError("VLi only allowed in failfirst")
3188 def assemble(self
, insn
):
3189 selector
= insn
.select(record
=self
.record
)
3190 selector
.mode
[1] = 1
3194 class Specifiers(tuple):
3229 def __new__(cls
, items
, record
):
3230 def transform(item
):
3231 for spec_cls
in cls
.SPECS
:
3232 spec
= spec_cls
.match(item
, record
=record
)
3233 if spec
is not None:
3235 raise ValueError(item
)
3237 # TODO: remove this hack
3238 items
= dict.fromkeys(items
)
3242 items
= tuple(items
)
3244 specs
= tuple(map(transform
, items
))
3245 for (index
, spec
) in enumerate(specs
):
3246 head
= specs
[:index
]
3247 tail
= specs
[index
+ 1:]
3248 spec
.validate(others
=(head
+ tail
))
3250 return super().__new
__(cls
, specs
)
3253 class SVP64OperandMeta(type):
3254 class SVP64NonZeroOperand(NonZeroOperand
):
3255 def assemble(self
, insn
, value
):
3256 if isinstance(value
, str):
3257 value
= int(value
, 0)
3258 if not isinstance(value
, int):
3259 raise ValueError("non-integer operand")
3261 # FIXME: this is really weird
3262 if self
.record
.name
in ("svstep", "svstep."):
3263 value
+= 1 # compensation
3265 return super().assemble(value
=value
, insn
=insn
)
3267 class SVP64XOStaticOperand(SpanStaticOperand
):
3268 def __init__(self
, record
, value
, span
):
3269 return super().__init
__(record
=record
, name
="XO",
3270 value
=value
, span
=span
)
3273 NonZeroOperand
: SVP64NonZeroOperand
,
3274 XOStaticOperand
: SVP64XOStaticOperand
,
3277 def __new__(metacls
, name
, bases
, ns
):
3279 for (index
, base_cls
) in enumerate(bases
):
3280 bases
[index
] = metacls
.__TRANSFORM
.get(base_cls
, base_cls
)
3282 bases
= tuple(bases
)
3284 return super().__new
__(metacls
, name
, bases
, ns
)
3287 class SVP64Operand(Operand
, metaclass
=SVP64OperandMeta
):
3290 return tuple(map(lambda bit
: (bit
+ 32), super().span
))
3294 def __init__(self
, insn
, record
):
3296 self
.__record
= record
3297 return super().__init
__()
3300 return self
.rm
.__doc
__
3303 return repr(self
.rm
)
3311 return self
.__record
3315 rm
= getattr(self
.insn
.prefix
.rm
, self
.record
.svp64
.mode
.name
.lower())
3317 # The idea behind these tables is that they are now literally
3318 # in identical format to insndb.csv and minor_xx.csv and can
3319 # be done precisely as that. The only thing to watch out for
3320 # is the insertion of Rc=1 as a "mask/value" bit and likewise
3321 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
3324 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
3325 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3326 # mode Rc mask Rc member
3328 (0b000000, 0b111000, "simple"), # simple (no Rc)
3329 (0b001000, 0b111100, "mr"), # mapreduce (no Rc)
3330 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3331 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3332 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3333 (0b001100, 0b111100, "rsvd"), # reserved
3335 mode
= int(self
.insn
.prefix
.rm
.normal
.mode
)
3336 search
= ((mode
<< 1) | self
.record
.Rc
)
3338 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
3339 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3340 # mode Rc mask Rc member
3341 # ironically/coincidentally this table is identical to NORMAL
3342 # mode except reserved in place of mr
3344 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3345 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3346 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3348 search
= ((int(self
.insn
.prefix
.rm
.ldst_imm
.mode
) << 1) |
3351 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
3352 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3353 # mode Rc mask Rc member
3355 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3356 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3357 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3359 search
= ((int(self
.insn
.prefix
.rm
.ldst_idx
.mode
) << 1) |
3362 elif self
.record
.svp64
.mode
is _SVMode
.CROP
:
3363 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
3364 # mode 3b mask 3b member
3366 (0b000000, 0b111000, "simple"), # simple
3367 (0b001000, 0b111000, "mr"), # mapreduce
3368 (0b010001, 0b010001, "ff3"), # ffirst, 3-bit CR
3369 (0b010000, 0b010000, "ff5"), # ffirst, 5-bit CR
3371 search
= ((int(self
.insn
.prefix
.rm
.crop
.mode
) << 1) |
3372 int(self
.record
.svp64
.extra_CR_3bit
))
3374 elif self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3378 (0b00, 0b11, "simple"), # simple
3379 (0b01, 0b11, "vls"), # VLset
3380 (0b10, 0b11, "ctr"), # CTR mode
3381 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
3383 # slightly weird: doesn't have a 5-bit "mode" field like others
3384 search
= int(self
.insn
.prefix
.rm
.branch
.mode
.sel
)
3387 if table
is not None:
3388 for (value
, mask
, field
) in table
:
3389 if field
.startswith("rsvd"):
3391 if ((value
& mask
) == (search
& mask
)):
3392 return getattr(rm
, field
)
3396 def __getattr__(self
, key
):
3397 if key
.startswith(f
"_{self.__class__.__name__}__"):
3398 return super().__getattribute
__(key
)
3400 return getattr(self
.rm
, key
)
3402 def __setattr__(self
, key
, value
):
3403 if key
.startswith(f
"_{self.__class__.__name__}__"):
3404 return super().__setattr
__(key
, value
)
3407 if not hasattr(rm
, key
):
3408 raise AttributeError(key
)
3410 return setattr(rm
, key
, value
)
3413 class SVP64Instruction(PrefixedInstruction
):
3414 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
3415 class Prefix(PrefixedInstruction
.Prefix
):
3417 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
3421 def select(self
, record
):
3422 return RMSelector(insn
=self
, record
=record
)
3427 for idx
in range(64):
3428 bit
= int(self
[idx
])
3430 return "".join(map(str, bits
))
3433 def assemble(cls
, record
, arguments
=None, specifiers
=None):
3434 insn
= super().assemble(record
=record
, arguments
=arguments
)
3436 specifiers
= Specifiers(items
=specifiers
, record
=record
)
3437 for specifier
in specifiers
:
3438 specifier
.assemble(insn
=insn
)
3440 insn
.prefix
.PO
= 0x1
3441 insn
.prefix
.id = 0x3
3445 def disassemble(self
, record
,
3447 style
=Style
.NORMAL
):
3449 if style
<= Style
.SHORT
:
3452 blob
= insn
.bytes(byteorder
=byteorder
)
3453 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
3456 blob_prefix
= blob(self
.prefix
)
3457 blob_suffix
= blob(self
.suffix
)
3459 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3460 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
3463 assert record
.svp64
is not None
3465 name
= f
"sv.{record.name}"
3467 rm
= self
.select(record
=record
)
3469 # convert specifiers to /x/y/z (sorted lexicographically)
3470 specifiers
= sorted(rm
.specifiers(record
=record
))
3471 if specifiers
: # if any add one extra to get the extra "/"
3472 specifiers
= ([""] + specifiers
)
3473 specifiers
= "/".join(specifiers
)
3475 # convert operands to " ,x,y,z"
3476 operands
= tuple(map(_operator
.itemgetter(1),
3477 self
.spec_dynamic_operands(record
=record
, style
=style
)))
3478 operands
= ",".join(operands
)
3479 if len(operands
) > 0: # if any separate with a space
3480 operands
= (" " + operands
)
3482 if style
<= Style
.LEGACY
:
3483 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3484 suffix
= WordInstruction
.integer(value
=int(self
.suffix
))
3485 yield from suffix
.disassemble(record
=record
,
3486 byteorder
=byteorder
, style
=style
)
3488 yield f
"{blob_prefix}{name}{specifiers}{operands}"
3490 yield f
"{blob_suffix}"
3492 if style
>= Style
.VERBOSE
:
3494 binary
= self
.binary
3495 spec
= self
.spec(record
=record
, prefix
="sv.")
3497 yield f
"{indent}spec"
3498 yield f
"{indent}{indent}{spec}"
3499 yield f
"{indent}pcode"
3500 for stmt
in record
.mdwn
.pcode
:
3501 yield f
"{indent}{indent}{stmt}"
3502 yield f
"{indent}binary"
3503 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
3504 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
3505 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
3506 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
3507 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
3508 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
3509 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
3510 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
3511 yield f
"{indent}opcodes"
3512 for opcode
in record
.opcodes
:
3513 yield f
"{indent}{indent}{opcode!r}"
3514 for operand
in self
.operands(record
=record
):
3515 yield from operand
.disassemble(insn
=self
,
3516 style
=style
, indent
=indent
)
3518 yield f
"{indent}{indent}{str(rm)}"
3519 for line
in rm
.disassemble(style
=style
):
3520 yield f
"{indent}{indent}{line}"
3524 def operands(cls
, record
):
3525 for operand
in super().operands(record
=record
):
3526 parent
= operand
.__class
__
3527 name
= f
"SVP64{parent.__name__}"
3528 bases
= (SVP64Operand
, parent
)
3529 child
= type(name
, bases
, {})
3530 yield child(**dict(operand
))
3533 def parse(stream
, factory
):
3535 return ("TODO" not in frozenset(entry
.values()))
3537 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
3538 entries
= _csv
.DictReader(lines
)
3539 entries
= filter(match
, entries
)
3540 return tuple(map(factory
, entries
))
3543 class MarkdownDatabase
:
3546 for (name
, desc
) in _ISA():
3549 (dynamic
, *static
) = desc
.regs
3550 operands
.extend(dynamic
)
3551 operands
.extend(static
)
3552 pcode
= PCode(iterable
=filter(str.strip
, desc
.pcode
))
3553 operands
= Operands(insn
=name
, operands
=operands
)
3554 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
3556 self
.__db
= dict(sorted(db
.items()))
3558 return super().__init
__()
3561 yield from self
.__db
.items()
3563 def __contains__(self
, key
):
3564 return self
.__db
.__contains
__(key
)
3566 def __getitem__(self
, key
):
3567 return self
.__db
.__getitem
__(key
)
3570 class FieldsDatabase
:
3573 df
= _DecodeFields()
3575 for (form
, fields
) in df
.instrs
.items():
3576 if form
in {"DQE", "TX"}:
3580 db
[_Form
[form
]] = Fields(fields
)
3584 return super().__init
__()
3586 def __getitem__(self
, key
):
3587 return self
.__db
.__getitem
__(key
)
3591 def __init__(self
, root
, mdwndb
):
3592 # The code below groups the instructions by name:section.
3593 # There can be multiple names for the same instruction.
3594 # The point is to capture different opcodes for the same instruction.
3596 records
= _collections
.defaultdict(set)
3597 path
= (root
/ "insndb.csv")
3598 with
open(path
, "r", encoding
="UTF-8") as stream
:
3599 for section
in sorted(parse(stream
, Section
.CSV
)):
3600 path
= (root
/ section
.path
)
3602 section
.Mode
.INTEGER
: IntegerOpcode
,
3603 section
.Mode
.PATTERN
: PatternOpcode
,
3605 factory
= _functools
.partial(
3606 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
3607 with
open(path
, "r", encoding
="UTF-8") as stream
:
3608 for insn
in parse(stream
, factory
):
3609 for name
in insn
.names
:
3610 records
[name
].add(insn
)
3611 sections
[name
] = section
3613 items
= sorted(records
.items())
3615 for (name
, multirecord
) in items
:
3616 records
[name
] = PPCMultiRecord(sorted(multirecord
))
3618 def exact_match(name
):
3619 record
= records
.get(name
)
3625 if not name
.endswith("l"):
3627 alias
= exact_match(name
[:-1])
3630 record
= records
[alias
]
3631 if "lk" not in record
.flags
:
3632 raise ValueError(record
)
3636 if not name
.endswith("a"):
3638 alias
= LK_match(name
[:-1])
3641 record
= records
[alias
]
3642 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
3643 raise ValueError(record
)
3644 if "AA" not in mdwndb
[name
].operands
:
3645 raise ValueError(record
)
3649 if not name
.endswith("."):
3651 alias
= exact_match(name
[:-1])
3654 record
= records
[alias
]
3655 if record
.Rc
is _RCOE
.NONE
:
3656 raise ValueError(record
)
3660 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
3661 for (name
, _
) in mdwndb
:
3662 if name
.startswith("sv."):
3665 for match
in matches
:
3667 if alias
is not None:
3671 section
= sections
[alias
]
3672 record
= records
[alias
]
3673 db
[name
] = (section
, record
)
3675 self
.__db
= dict(sorted(db
.items()))
3677 return super().__init
__()
3679 @_functools.lru_cache(maxsize
=512, typed
=False)
3680 def __getitem__(self
, key
):
3681 return self
.__db
.get(key
, (None, None))
3684 class SVP64Database
:
3685 def __init__(self
, root
, ppcdb
):
3687 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
3688 for (prefix
, _
, names
) in _os
.walk(root
):
3689 prefix
= _pathlib
.Path(prefix
)
3690 for name
in filter(lambda name
: pattern
.match(name
), names
):
3691 path
= (prefix
/ _pathlib
.Path(name
))
3692 with
open(path
, "r", encoding
="UTF-8") as stream
:
3693 db
.update(parse(stream
, SVP64Record
.CSV
))
3694 db
= {record
.name
:record
for record
in db
}
3696 self
.__db
= dict(sorted(db
.items()))
3697 self
.__ppcdb
= ppcdb
3699 return super().__init
__()
3701 def __getitem__(self
, key
):
3702 (_
, record
) = self
.__ppcdb
[key
]
3706 for name
in record
.names
:
3707 record
= self
.__db
.get(name
, None)
3708 if record
is not None:
3714 class Database(Node
):
3715 def __init__(self
, root
):
3716 root
= _pathlib
.Path(root
)
3717 mdwndb
= MarkdownDatabase()
3718 fieldsdb
= FieldsDatabase()
3719 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
3720 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
3724 opcodes
= _collections
.defaultdict(
3725 lambda: _collections
.defaultdict(set))
3727 for (name
, mdwn
) in mdwndb
:
3728 if name
.startswith("sv."):
3730 (section
, ppc
) = ppcdb
[name
]
3733 svp64
= svp64db
[name
]
3734 fields
= fieldsdb
[ppc
.form
]
3735 record
= Record(name
=name
,
3736 section
=section
, ppc
=ppc
, svp64
=svp64
,
3737 mdwn
=mdwn
, fields
=fields
)
3739 names
[record
.name
] = record
3740 opcodes
[section
][record
.PO
].add(record
)
3742 self
.__db
= sorted(db
)
3743 self
.__names
= dict(sorted(names
.items()))
3744 self
.__opcodes
= dict(sorted(opcodes
.items()))
3746 return super().__init
__()
3753 return repr(self
.__db
)
3756 yield from self
.__db
3758 @_functools.lru_cache(maxsize
=None)
3759 def __contains__(self
, key
):
3760 return self
.__getitem