1 import collections
as _collections
3 import dataclasses
as _dataclasses
5 import functools
as _functools
7 import operator
as _operator
8 import pathlib
as _pathlib
12 from functools
import cached_property
14 from cached_property
import cached_property
16 from openpower
.decoder
.power_enums
import (
17 Function
as _Function
,
24 CRIn2Sel
as _CRIn2Sel
,
25 CROutSel
as _CROutSel
,
27 LDSTMode
as _LDSTMode
,
32 SVMaskSrc
as _SVMaskSrc
,
37 SVP64RMMode
as _SVP64RMMode
,
38 SVExtraRegType
as _SVExtraRegType
,
39 SVExtraReg
as _SVExtraReg
,
40 SVP64SubVL
as _SVP64SubVL
,
41 SVP64Pred
as _SVP64Pred
,
42 SVP64PredMode
as _SVP64PredMode
,
43 SVP64Width
as _SVP64Width
,
45 from openpower
.decoder
.selectable_int
import (
46 SelectableInt
as _SelectableInt
,
47 selectconcat
as _selectconcat
,
49 from openpower
.decoder
.power_fields
import (
52 DecodeFields
as _DecodeFields
,
54 from openpower
.decoder
.pseudo
.pagereader
import ISA
as _ISA
57 @_functools.total_ordering
58 class Style(_enum
.Enum
):
62 VERBOSE
= _enum
.auto()
64 def __lt__(self
, other
):
65 if not isinstance(other
, self
.__class
__):
67 return (self
.value
< other
.value
)
70 @_functools.total_ordering
71 class Priority(_enum
.Enum
):
77 def _missing_(cls
, value
):
78 if isinstance(value
, str):
83 return super()._missing
_(value
)
85 def __lt__(self
, other
):
86 if not isinstance(other
, self
.__class
__):
89 # NOTE: the order is inversed, LOW < NORMAL < HIGH
90 return (self
.value
> other
.value
)
93 def dataclass(cls
, record
, keymap
=None, typemap
=None):
97 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
99 def transform(key_value
):
100 (key
, value
) = key_value
101 key
= keymap
.get(key
, key
)
102 hook
= typemap
.get(key
, lambda value
: value
)
103 if hook
is bool and value
in ("", "0"):
109 record
= dict(map(transform
, record
.items()))
110 for key
in frozenset(record
.keys()):
111 if record
[key
] == "":
117 @_functools.total_ordering
118 @_dataclasses.dataclass(eq
=True, frozen
=True)
121 def __new__(cls
, value
):
122 if isinstance(value
, str):
123 value
= int(value
, 0)
124 if not isinstance(value
, int):
125 raise ValueError(value
)
127 if value
.bit_length() > 64:
128 raise ValueError(value
)
130 return super().__new
__(cls
, value
)
133 return self
.__repr
__()
136 return f
"{self:0{self.bit_length()}b}"
138 def bit_length(self
):
139 if super().bit_length() > 32:
143 class Value(Integer
):
152 def __lt__(self
, other
):
153 if not isinstance(other
, Opcode
):
154 return NotImplemented
155 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
158 def pattern(value
, mask
, bit_length
):
159 for bit
in range(bit_length
):
160 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
162 elif (value
& (1 << (bit_length
- bit
- 1))):
167 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
169 def match(self
, key
):
170 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
173 @_functools.total_ordering
174 @_dataclasses.dataclass(eq
=True, frozen
=True)
175 class IntegerOpcode(Opcode
):
176 def __init__(self
, value
):
177 if value
.startswith("0b"):
178 mask
= int(("1" * len(value
[2:])), 2)
182 value
= Opcode
.Value(value
)
183 mask
= Opcode
.Mask(mask
)
185 return super().__init
__(value
=value
, mask
=mask
)
188 @_functools.total_ordering
189 @_dataclasses.dataclass(eq
=True, frozen
=True)
190 class PatternOpcode(Opcode
):
191 def __init__(self
, pattern
):
192 if not isinstance(pattern
, str):
193 raise ValueError(pattern
)
195 (value
, mask
) = (0, 0)
196 for symbol
in pattern
:
197 if symbol
not in {"0", "1", "-"}:
198 raise ValueError(pattern
)
199 value |
= (symbol
== "1")
200 mask |
= (symbol
!= "-")
206 value
= Opcode
.Value(value
)
207 mask
= Opcode
.Mask(mask
)
209 return super().__init
__(value
=value
, mask
=mask
)
212 @_dataclasses.dataclass(eq
=True, frozen
=True)
214 class FlagsMeta(type):
229 class Flags(tuple, metaclass
=FlagsMeta
):
230 def __new__(cls
, flags
=frozenset()):
231 flags
= frozenset(flags
)
232 diff
= (flags
- frozenset(cls
))
234 raise ValueError(flags
)
235 return super().__new
__(cls
, sorted(flags
))
239 flags
: Flags
= Flags()
241 function
: _Function
= _Function
.NONE
242 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
243 in1
: _In1Sel
= _In1Sel
.RA
244 in2
: _In2Sel
= _In2Sel
.NONE
245 in3
: _In3Sel
= _In3Sel
.NONE
246 out
: _OutSel
= _OutSel
.NONE
247 cr_in
: _CRInSel
= _CRInSel
.NONE
248 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
249 cr_out
: _CROutSel
= _CROutSel
.NONE
250 cry_in
: _CryIn
= _CryIn
.ZERO
251 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
252 upd
: _LDSTMode
= _LDSTMode
.NONE
253 Rc
: _RCOE
= _RCOE
.NONE
254 form
: _Form
= _Form
.NONE
256 unofficial
: bool = False
260 "internal op": "intop",
264 "ldst len": "ldst_len",
266 "CONDITIONS": "conditions",
269 def __lt__(self
, other
):
270 if not isinstance(other
, self
.__class
__):
271 return NotImplemented
272 lhs
= (self
.opcode
, self
.comment
)
273 rhs
= (other
.opcode
, other
.comment
)
277 def CSV(cls
, record
, opcode_cls
):
278 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
279 typemap
["opcode"] = opcode_cls
281 if record
["CR in"] == "BA_BB":
282 record
["cr_in"] = "BA"
283 record
["cr_in2"] = "BB"
287 for flag
in frozenset(PPCRecord
.Flags
):
288 if bool(record
.pop(flag
, "")):
290 record
["flags"] = PPCRecord
.Flags(flags
)
292 return dataclass(cls
, record
,
293 keymap
=PPCRecord
.__KEYMAP
,
298 return frozenset(self
.comment
.split("=")[-1].split("/"))
301 class PPCMultiRecord(tuple):
302 def __getattr__(self
, attr
):
305 raise AttributeError(attr
)
306 return getattr(self
[0], attr
)
309 @_dataclasses.dataclass(eq
=True, frozen
=True)
311 class ExtraMap(tuple):
313 @_dataclasses.dataclass(eq
=True, frozen
=True)
315 regtype
: _SVExtraRegType
= _SVExtraRegType
.NONE
316 reg
: _SVExtraReg
= _SVExtraReg
.NONE
319 return f
"{self.regtype.value}:{self.reg.name}"
321 def __new__(cls
, value
="0"):
322 if isinstance(value
, str):
323 def transform(value
):
324 (regtype
, reg
) = value
.split(":")
325 regtype
= _SVExtraRegType(regtype
)
326 reg
= _SVExtraReg(reg
)
327 return cls
.Entry(regtype
=regtype
, reg
=reg
)
332 value
= map(transform
, value
.split(";"))
334 return super().__new
__(cls
, value
)
337 return repr(list(self
))
339 def __new__(cls
, value
=tuple()):
343 return super().__new
__(cls
, map(cls
.Extra
, value
))
346 return repr({index
:self
[index
] for index
in range(0, 4)})
349 ptype
: _SVPType
= _SVPType
.NONE
350 etype
: _SVEType
= _SVEType
.NONE
351 msrc
: _SVMaskSrc
= _SVMaskSrc
.NO
# MASK_SRC is active
352 in1
: _In1Sel
= _In1Sel
.NONE
353 in2
: _In2Sel
= _In2Sel
.NONE
354 in3
: _In3Sel
= _In3Sel
.NONE
355 out
: _OutSel
= _OutSel
.NONE
356 out2
: _OutSel
= _OutSel
.NONE
357 cr_in
: _CRInSel
= _CRInSel
.NONE
358 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
359 cr_out
: _CROutSel
= _CROutSel
.NONE
360 extra
: ExtraMap
= ExtraMap()
362 mode
: _SVMode
= _SVMode
.NORMAL
366 "CONDITIONS": "conditions",
375 def CSV(cls
, record
):
376 for key
in frozenset({
377 "in1", "in2", "in3", "CR in",
378 "out", "out2", "CR out",
384 if record
["CR in"] == "BA_BB":
385 record
["cr_in"] = "BA"
386 record
["cr_in2"] = "BB"
390 for idx
in range(0, 4):
391 extra
.append(record
.pop(f
"{idx}"))
393 record
["extra"] = cls
.ExtraMap(extra
)
395 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
397 @_functools.lru_cache(maxsize
=None)
398 def extra_idx(self
, key
):
406 if key
not in frozenset({
407 "in1", "in2", "in3", "cr_in", "cr_in2",
408 "out", "out2", "cr_out",
412 sel
= getattr(self
, key
)
413 if sel
is _CRInSel
.BA_BB
:
414 return _SVExtra
.Idx_1_2
415 reg
= _SVExtraReg(sel
)
416 if reg
is _SVExtraReg
.NONE
:
420 _SVExtraRegType
.SRC
: {},
421 _SVExtraRegType
.DST
: {},
423 for index
in range(0, 4):
424 for entry
in self
.extra
[index
]:
425 extra_map
[entry
.regtype
][entry
.reg
] = extra_idx
[index
]
427 for regtype
in (_SVExtraRegType
.SRC
, _SVExtraRegType
.DST
):
428 extra
= extra_map
[regtype
].get(reg
, _SVExtra
.NONE
)
429 if extra
is not _SVExtra
.NONE
:
434 extra_idx_in1
= property(_functools
.partial(extra_idx
, key
="in1"))
435 extra_idx_in2
= property(_functools
.partial(extra_idx
, key
="in2"))
436 extra_idx_in3
= property(_functools
.partial(extra_idx
, key
="in3"))
437 extra_idx_out
= property(_functools
.partial(extra_idx
, key
="out"))
438 extra_idx_out2
= property(_functools
.partial(extra_idx
, key
="out2"))
439 extra_idx_cr_in
= property(_functools
.partial(extra_idx
, key
="cr_in"))
440 extra_idx_cr_in2
= property(_functools
.partial(extra_idx
, key
="cr_in2"))
441 extra_idx_cr_out
= property(_functools
.partial(extra_idx
, key
="cr_out"))
443 @_functools.lru_cache(maxsize
=None)
444 def extra_reg(self
, key
):
445 return _SVExtraReg(getattr(self
, key
))
447 extra_reg_in1
= property(_functools
.partial(extra_reg
, key
="in1"))
448 extra_reg_in2
= property(_functools
.partial(extra_reg
, key
="in2"))
449 extra_reg_in3
= property(_functools
.partial(extra_reg
, key
="in3"))
450 extra_reg_out
= property(_functools
.partial(extra_reg
, key
="out"))
451 extra_reg_out2
= property(_functools
.partial(extra_reg
, key
="out2"))
452 extra_reg_cr_in
= property(_functools
.partial(extra_reg
, key
="cr_in"))
453 extra_reg_cr_in2
= property(_functools
.partial(extra_reg
, key
="cr_in2"))
454 extra_reg_cr_out
= property(_functools
.partial(extra_reg
, key
="cr_out"))
459 for idx
in range(0, 4):
460 for entry
in self
.extra
[idx
]:
461 if entry
.regtype
is _SVExtraRegType
.DST
:
462 if extra
is not None:
463 raise ValueError(self
.svp64
)
467 if _RegType(extra
.reg
) not in (_RegType
.CR_3BIT
, _RegType
.CR_5BIT
):
468 raise ValueError(self
.svp64
)
473 def extra_CR_3bit(self
):
474 return (_RegType(self
.extra_CR
.reg
) is _RegType
.CR_3BIT
)
478 def __init__(self
, value
=(0, 32)):
479 if isinstance(value
, str):
480 (start
, end
) = map(int, value
.split(":"))
483 if start
< 0 or end
< 0 or start
>= end
:
484 raise ValueError(value
)
489 return super().__init
__()
492 return (self
.__end
- self
.__start
+ 1)
495 return f
"[{self.__start}:{self.__end}]"
498 yield from range(self
.start
, (self
.end
+ 1))
500 def __reversed__(self
):
501 return tuple(reversed(tuple(self
)))
512 @_dataclasses.dataclass(eq
=True, frozen
=True)
514 class Mode(_enum
.Enum
):
515 INTEGER
= _enum
.auto()
516 PATTERN
= _enum
.auto()
519 def _missing_(cls
, value
):
520 if isinstance(value
, str):
521 return cls
[value
.upper()]
522 return super()._missing
_(value
)
525 def __new__(cls
, value
=None):
526 if isinstance(value
, str):
527 if value
.upper() == "NONE":
530 value
= int(value
, 0)
534 return super().__new
__(cls
, value
)
540 return (bin(self
) if self
else "None")
546 opcode
: IntegerOpcode
= None
547 priority
: Priority
= Priority
.NORMAL
549 def __lt__(self
, other
):
550 if not isinstance(other
, self
.__class
__):
551 return NotImplemented
552 return (self
.priority
< other
.priority
)
555 def CSV(cls
, record
):
556 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
557 if record
["opcode"] == "NONE":
558 typemap
["opcode"] = lambda _
: None
560 return dataclass(cls
, record
, typemap
=typemap
)
564 def __init__(self
, items
):
565 if isinstance(items
, dict):
566 items
= items
.items()
569 (name
, bitrange
) = item
570 return (name
, tuple(bitrange
.values()))
572 self
.__mapping
= dict(map(transform
, items
))
574 return super().__init
__()
577 return repr(self
.__mapping
)
580 yield from self
.__mapping
.items()
582 def __contains__(self
, key
):
583 return self
.__mapping
.__contains
__(key
)
585 def __getitem__(self
, key
):
586 return self
.__mapping
.get(key
, None)
601 def __init__(self
, insn
, iterable
):
603 "b": {"target_addr": TargetAddrOperandLI
},
604 "ba": {"target_addr": TargetAddrOperandLI
},
605 "bl": {"target_addr": TargetAddrOperandLI
},
606 "bla": {"target_addr": TargetAddrOperandLI
},
607 "bc": {"target_addr": TargetAddrOperandBD
},
608 "bca": {"target_addr": TargetAddrOperandBD
},
609 "bcl": {"target_addr": TargetAddrOperandBD
},
610 "bcla": {"target_addr": TargetAddrOperandBD
},
611 "addpcis": {"D": DOperandDX
},
612 "fishmv": {"D": DOperandDX
},
613 "fmvis": {"D": DOperandDX
},
616 "SVi": NonZeroOperand
,
617 "SVd": NonZeroOperand
,
618 "SVxd": NonZeroOperand
,
619 "SVyd": NonZeroOperand
,
620 "SVzd": NonZeroOperand
,
622 "D": SignedImmediateOperand
,
626 "SIM": SignedOperand
,
627 "SVD": SignedOperand
,
628 "SVDS": SignedOperand
,
629 "RSp": GPRPairOperand
,
630 "RTp": GPRPairOperand
,
631 "FRAp": FPRPairOperand
,
632 "FRBp": FPRPairOperand
,
633 "FRSp": FPRPairOperand
,
634 "FRTp": FPRPairOperand
,
636 custom_immediates
= {
642 for operand
in iterable
:
646 (name
, value
) = operand
.split("=")
647 mapping
[name
] = (StaticOperand
, {
653 if name
.endswith(")"):
654 name
= name
.replace("(", " ").replace(")", "")
655 (imm_name
, _
, name
) = name
.partition(" ")
659 if imm_name
is not None:
660 imm_cls
= custom_immediates
.get(imm_name
, ImmediateOperand
)
662 if insn
in custom_insns
and name
in custom_insns
[insn
]:
663 cls
= custom_insns
[insn
][name
]
664 elif name
in custom_fields
:
665 cls
= custom_fields
[name
]
667 if name
in _SVExtraReg
.__members
__:
668 reg
= _SVExtraReg
[name
]
669 if reg
in self
.__class
__.__GPR
_PAIRS
:
671 elif reg
in self
.__class
__.__FPR
_PAIRS
:
674 regtype
= _RegType
[name
]
675 if regtype
is _RegType
.GPR
:
677 elif regtype
is _RegType
.FPR
:
679 elif regtype
is _RegType
.CR_3BIT
:
681 elif regtype
is _RegType
.CR_5BIT
:
684 if imm_name
is not None:
685 mapping
[imm_name
] = (imm_cls
, {"name": imm_name
})
686 mapping
[name
] = (cls
, {"name": name
})
690 for (name
, (cls
, kwargs
)) in mapping
.items():
691 kwargs
= dict(kwargs
)
692 kwargs
["name"] = name
693 if issubclass(cls
, StaticOperand
):
694 static
.append((cls
, kwargs
))
695 elif issubclass(cls
, DynamicOperand
):
696 dynamic
.append((cls
, kwargs
))
698 raise ValueError(name
)
700 self
.__mapping
= mapping
701 self
.__static
= tuple(static
)
702 self
.__dynamic
= tuple(dynamic
)
704 return super().__init
__()
707 for (_
, items
) in self
.__mapping
.items():
708 (cls
, kwargs
) = items
712 return self
.__mapping
.__repr
__()
714 def __contains__(self
, key
):
715 return self
.__mapping
.__contains
__(key
)
717 def __getitem__(self
, key
):
718 return self
.__mapping
.__getitem
__(key
)
726 return self
.__dynamic
729 class Arguments(tuple):
730 def __new__(cls
, fields
, operands
):
731 iterable
= iter(tuple(fields
))
732 operands
= iter(tuple(operands
))
737 operand
= next(operands
)
738 except StopIteration:
742 argument
= next(iterable
)
743 except StopIteration:
744 raise ValueError("operands count mismatch")
746 (op_cls
, _
) = operand
747 if issubclass(op_cls
, ImmediateOperand
):
748 argument
= argument
.replace("(", " ").replace(")", "")
749 (imm_argument
, _
, argument
) = argument
.partition(" ")
751 (imm_operand
, operand
) = (operand
, next(operands
))
752 except StopIteration:
753 raise ValueError("operands count mismatch")
754 arguments
.append((imm_argument
, imm_operand
))
755 arguments
.append((argument
, operand
))
759 except StopIteration:
762 raise ValueError("operands count mismatch")
764 return super().__new
__(cls
, arguments
)
768 def __init__(self
, iterable
):
769 self
.__pcode
= tuple(iterable
)
770 return super().__init
__()
773 yield from self
.__pcode
776 return self
.__pcode
.__repr
__()
779 @_dataclasses.dataclass(eq
=True, frozen
=True)
780 class MarkdownRecord
:
785 @_functools.total_ordering
786 @_dataclasses.dataclass(eq
=True, frozen
=True)
793 svp64
: SVP64Record
= None
795 def __lt__(self
, other
):
796 if not isinstance(other
, Record
):
797 return NotImplemented
798 lhs
= (min(self
.opcodes
), self
.name
)
799 rhs
= (min(other
.opcodes
), other
.name
)
803 def static_operands(self
):
805 return (XOStaticOperand
, {
806 "span": self
.section
.bitsel
,
807 "value": ppc
.opcode
.value
,
810 yield (POStaticOperand
, {"value": self
.PO
})
811 yield from map(XO
, self
.ppc
)
812 yield from self
.mdwn
.operands
.static
815 def dynamic_operands(self
):
816 yield from self
.mdwn
.operands
.dynamic
821 return int("".join(str(int(mapping
[bit
])) for bit
in sorted(mapping
)), 2)
823 def PO_XO(value
, mask
, opcode
, bits
):
826 for (src
, dst
) in enumerate(reversed(bits
)):
827 value
[dst
] = ((opcode
.value
& (1 << src
)) != 0)
828 mask
[dst
] = ((opcode
.mask
& (1 << src
)) != 0)
831 def PO(value
, mask
, opcode
, bits
):
832 return PO_XO(value
=value
, mask
=mask
, opcode
=opcode
, bits
=bits
)
834 def XO(value
, mask
, opcode
, bits
):
835 (value
, mask
) = PO_XO(value
=value
, mask
=mask
, opcode
=opcode
, bits
=bits
)
836 for (op_cls
, op_kwargs
) in self
.mdwn
.operands
.static
:
837 operand
= op_cls(record
=self
, **op_kwargs
)
838 for (src
, dst
) in enumerate(reversed(operand
.span
)):
839 value
[dst
] = ((operand
.value
& (1 << src
)) != 0)
844 value
= {bit
:False for bit
in range(32)}
845 mask
= {bit
:False for bit
in range(32)}
846 if self
.section
.opcode
is not None:
847 (value
, mask
) = PO(value
=value
, mask
=mask
,
848 opcode
=self
.section
.opcode
, bits
=range(0, 6))
850 pairs
.append(XO(value
=value
, mask
=mask
,
851 opcode
=ppc
.opcode
, bits
=self
.section
.bitsel
))
854 for (value
, mask
) in pairs
:
855 value
= Opcode
.Value(binary(value
))
856 mask
= Opcode
.Mask(binary(mask
))
857 result
.append(Opcode(value
=value
, mask
=mask
))
863 opcode
= self
.section
.opcode
865 opcode
= self
.ppc
[0].opcode
866 if isinstance(opcode
, PatternOpcode
):
867 value
= int(opcode
.value
)
868 bits
= opcode
.value
.bit_length()
869 return int(_SelectableInt(value
=value
, bits
=bits
)[0:6])
871 return int(opcode
.value
)
873 def match(self
, key
):
874 for opcode
in self
.opcodes
:
875 if opcode
.match(key
):
882 return self
.svp64
.mode
902 if self
.svp64
is None:
908 return self
.ppc
.cr_in
912 return self
.ppc
.cr_in2
916 return self
.ppc
.cr_out
918 ptype
= property(lambda self
: self
.svp64
.ptype
)
919 etype
= property(lambda self
: self
.svp64
.etype
)
921 def extra_idx(self
, key
):
922 return self
.svp64
.extra_idx(key
)
924 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
925 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
926 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
927 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
928 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
929 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
930 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
931 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
933 def __contains__(self
, key
):
934 return self
.mdwn
.operands
.__contains
__(key
)
936 def __getitem__(self
, key
):
937 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
938 return cls(record
=self
, **kwargs
)
944 return self
["Rc"].value
948 def __init__(self
, record
, name
):
949 self
.__record
= record
953 return f
"{self.__class__.__name__}({self.name})"
965 return self
.record
.fields
[self
.name
]
967 def assemble(self
, value
, insn
):
969 if isinstance(value
, str):
970 value
= int(value
, 0)
972 raise ValueError("signed operands not allowed")
975 def disassemble(self
, insn
,
976 style
=Style
.NORMAL
, indent
=""):
977 raise NotImplementedError()
980 class DynamicOperand(Operand
):
981 def disassemble(self
, insn
,
982 style
=Style
.NORMAL
, indent
=""):
986 if style
>= Style
.VERBOSE
:
987 span
= map(str, span
)
988 yield f
"{indent}{self.name}"
989 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
990 yield f
"{indent}{indent}{', '.join(span)}"
992 yield str(int(value
))
995 class SignedOperand(DynamicOperand
):
996 def assemble(self
, value
, insn
):
997 if isinstance(value
, str):
998 value
= int(value
, 0)
999 return super().assemble(value
=value
, insn
=insn
)
1001 def assemble(self
, value
, insn
):
1003 if isinstance(value
, str):
1004 value
= int(value
, 0)
1007 def disassemble(self
, insn
,
1008 style
=Style
.NORMAL
, indent
=""):
1010 value
= insn
[span
].to_signed_int()
1011 sign
= "-" if (value
< 0) else ""
1014 if style
>= Style
.VERBOSE
:
1015 span
= map(str, span
)
1016 yield f
"{indent}{self.name}"
1017 yield f
"{indent}{indent}{sign}{value}"
1018 yield f
"{indent}{indent}{', '.join(span)}"
1020 yield f
"{sign}{value}"
1023 class StaticOperand(Operand
):
1024 def __init__(self
, record
, name
, value
):
1025 self
.__value
= value
1026 return super().__init
__(record
=record
, name
=name
)
1029 return f
"{self.__class__.__name__}({self.name}, value={self.value})"
1035 def assemble(self
, insn
):
1036 return super().assemble(value
=self
.value
, insn
=insn
)
1038 def disassemble(self
, insn
,
1039 style
=Style
.NORMAL
, indent
=""):
1043 if style
>= Style
.VERBOSE
:
1044 span
= map(str, span
)
1045 yield f
"{indent}{self.name}"
1046 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1047 yield f
"{indent}{indent}{', '.join(span)}"
1049 yield str(int(value
))
1052 class SpanStaticOperand(StaticOperand
):
1053 def __init__(self
, record
, name
, value
, span
):
1055 return super().__init
__(record
=record
, name
=name
, value
=value
)
1062 class POStaticOperand(SpanStaticOperand
):
1063 def __init__(self
, record
, value
):
1064 return super().__init
__(record
=record
, name
="PO", value
=value
, span
=range(0, 6))
1067 class XOStaticOperand(SpanStaticOperand
):
1068 def __init__(self
, record
, value
, span
):
1069 bits
= record
.section
.bitsel
1070 value
= _SelectableInt(value
=value
, bits
=len(bits
))
1071 span
= dict(zip(bits
, range(len(bits
))))
1072 span_rev
= {value
:key
for (key
, value
) in span
.items()}
1074 # This part is tricky: we could have used record.static_operands,
1075 # but this would cause an infinite recursion, since this code is called
1076 # from the record.static_operands method already.
1078 operands
.extend(record
.mdwn
.operands
.static
)
1079 operands
.extend(record
.mdwn
.operands
.dynamic
)
1080 for (cls
, kwargs
) in operands
:
1081 operand
= cls(record
=record
, **kwargs
)
1082 for idx
in operand
.span
:
1083 rev
= span
.pop(idx
, None)
1085 span_rev
.pop(rev
, None)
1087 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1088 span
= tuple(span
.keys())
1090 return super().__init
__(record
=record
, name
="XO", value
=value
, span
=span
)
1093 class ImmediateOperand(DynamicOperand
):
1097 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1101 class NonZeroOperand(DynamicOperand
):
1102 def assemble(self
, value
, insn
):
1103 if isinstance(value
, str):
1104 value
= int(value
, 0)
1105 if not isinstance(value
, int):
1106 raise ValueError("non-integer operand")
1108 return super().assemble(value
=value
, insn
=insn
)
1110 def disassemble(self
, insn
,
1111 style
=Style
.NORMAL
, indent
=""):
1115 if style
>= Style
.VERBOSE
:
1116 span
= map(str, span
)
1117 yield f
"{indent}{self.name}"
1118 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1119 yield f
"{indent}{indent}{', '.join(span)}"
1121 yield str(int(value
) + 1)
1124 class ExtendableOperand(DynamicOperand
):
1125 def sv_spec_enter(self
, value
, span
):
1126 return (value
, span
)
1128 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1129 return (value
, span
)
1131 def spec(self
, insn
):
1135 span
= tuple(map(str, span
))
1137 if isinstance(insn
, SVP64Instruction
):
1138 (origin_value
, origin_span
) = (value
, span
)
1139 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1141 extra_idx
= self
.extra_idx
1142 if extra_idx
is _SVExtra
.NONE
:
1143 return (vector
, value
, span
)
1145 if self
.record
.etype
is _SVEType
.EXTRA3
:
1146 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1147 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1148 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1150 raise ValueError(self
.record
.etype
)
1153 vector
= bool(spec
[0])
1154 spec_span
= spec
.__class
__
1155 if self
.record
.etype
is _SVEType
.EXTRA3
:
1156 spec_span
= tuple(map(str, spec_span
[1, 2]))
1158 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1159 spec_span
= tuple(map(str, spec_span
[1,]))
1160 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1163 spec_span
= (spec_span
+ ("{0}",))
1165 spec_span
= (("{0}",) + spec_span
)
1167 raise ValueError(self
.record
.etype
)
1169 vector_shift
= (2 + (5 - value
.bits
))
1170 scalar_shift
= value
.bits
1171 spec_shift
= (5 - value
.bits
)
1173 bits
= (len(span
) + len(spec_span
))
1174 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1175 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1177 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1178 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1180 value
= ((spec
<< scalar_shift
) | value
)
1181 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1183 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1184 origin_value
=origin_value
, origin_span
=origin_span
)
1186 return (vector
, value
, span
)
1189 def extra_reg(self
):
1190 return _SVExtraReg(self
.name
)
1193 def extra_idx(self
):
1195 _SVExtraReg
.RSp
: _SVExtraReg
.RS
,
1196 _SVExtraReg
.RTp
: _SVExtraReg
.RT
,
1197 _SVExtraReg
.FRAp
: _SVExtraReg
.FRA
,
1198 _SVExtraReg
.FRBp
: _SVExtraReg
.FRB
,
1199 _SVExtraReg
.FRSp
: _SVExtraReg
.FRS
,
1200 _SVExtraReg
.FRTp
: _SVExtraReg
.FRT
,
1203 for key
in frozenset({
1204 "in1", "in2", "in3", "cr_in", "cr_in2",
1205 "out", "out2", "cr_out",
1207 extra_reg
= self
.record
.svp64
.extra_reg(key
=key
)
1208 if pairs
.get(extra_reg
, extra_reg
) is pairs
.get(self
.extra_reg
, self
.extra_reg
):
1209 return self
.record
.extra_idx(key
=key
)
1211 return _SVExtra
.NONE
1213 def remap(self
, value
, vector
):
1214 raise NotImplementedError()
1216 def assemble(self
, value
, insn
, prefix
):
1219 if isinstance(value
, str):
1220 value
= value
.lower()
1221 if value
.startswith("%"):
1223 if value
.startswith("*"):
1224 if not isinstance(insn
, SVP64Instruction
):
1225 raise ValueError(value
)
1228 if value
.startswith(prefix
):
1229 value
= value
[len(prefix
):]
1230 value
= int(value
, 0)
1232 if isinstance(insn
, SVP64Instruction
):
1233 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1235 extra_idx
= self
.extra_idx
1236 if extra_idx
is _SVExtra
.NONE
:
1237 raise ValueError(self
.record
)
1239 if self
.record
.etype
is _SVEType
.EXTRA3
:
1240 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1241 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1242 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1244 raise ValueError(self
.record
.etype
)
1246 return super().assemble(value
=value
, insn
=insn
)
1248 return super().assemble(value
=value
, insn
=insn
)
1250 def disassemble(self
, insn
,
1251 style
=Style
.NORMAL
, prefix
="", indent
=""):
1252 (vector
, value
, span
) = self
.spec(insn
=insn
)
1254 if style
>= Style
.VERBOSE
:
1255 mode
= "vector" if vector
else "scalar"
1256 yield f
"{indent}{self.name} ({mode})"
1257 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1258 yield f
"{indent}{indent}{', '.join(span)}"
1259 if isinstance(insn
, SVP64Instruction
):
1260 extra_idx
= self
.extra_idx
1261 if self
.record
.etype
is _SVEType
.NONE
:
1262 yield f
"{indent}{indent}extra[none]"
1264 etype
= repr(self
.record
.etype
).lower()
1265 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1267 vector
= "*" if vector
else ""
1268 yield f
"{vector}{prefix}{int(value)}"
1271 class SimpleRegisterOperand(ExtendableOperand
):
1272 def remap(self
, value
, vector
):
1274 extra
= (value
& 0b11)
1275 value
= (value
>> 2)
1277 extra
= (value
>> 5)
1278 value
= (value
& 0b11111)
1280 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1281 # (and shrink to a single bit if ok)
1282 if self
.record
.etype
is _SVEType
.EXTRA2
:
1284 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1285 assert (extra
& 0b01) == 0, \
1286 ("vector field %s cannot fit into EXTRA2" % value
)
1287 extra
= (0b10 |
(extra
>> 1))
1289 # range is r0-r63 in increments of 1
1290 assert (extra
>> 1) == 0, \
1291 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1293 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1295 # EXTRA3 vector bit needs marking
1298 raise ValueError(self
.record
.etype
)
1300 return (value
, extra
)
1303 class GPROperand(SimpleRegisterOperand
):
1304 def assemble(self
, value
, insn
):
1305 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1307 def disassemble(self
, insn
,
1308 style
=Style
.NORMAL
, indent
=""):
1309 prefix
= "" if (style
<= Style
.SHORT
) else "r"
1310 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1311 style
=style
, indent
=indent
)
1314 class GPRPairOperand(GPROperand
):
1318 class FPROperand(SimpleRegisterOperand
):
1319 def assemble(self
, value
, insn
):
1320 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1322 def disassemble(self
, insn
,
1323 style
=Style
.NORMAL
, indent
=""):
1324 prefix
= "" if (style
<= Style
.SHORT
) else "f"
1325 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1326 style
=style
, indent
=indent
)
1329 class FPRPairOperand(FPROperand
):
1333 class ConditionRegisterFieldOperand(ExtendableOperand
):
1334 def pattern(name_pattern
):
1335 (name
, pattern
) = name_pattern
1336 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1345 CR
= r
"(?:CR|cr)([0-9]+)"
1347 BIT
= rf
"({'|'.join(CONDS.keys())})"
1348 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1349 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1350 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1351 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1352 XCR
= fr
"{CR}\.{BIT}"
1353 PATTERNS
= tuple(map(pattern
, (
1358 ("BIT+CR", (LBIT
+ CR
)),
1359 ("CR+BIT", (CR
+ RBIT
)),
1360 ("BIT+CR*N", (LBIT
+ CRN
)),
1361 ("CR*N+BIT", (CRN
+ RBIT
)),
1362 ("BIT+N*CR", (LBIT
+ NCR
)),
1363 ("N*CR+BIT", (NCR
+ RBIT
)),
1366 def remap(self
, value
, vector
, regtype
):
1367 if regtype
is _RegType
.CR_5BIT
:
1368 subvalue
= (value
& 0b11)
1372 extra
= (value
& 0b1111)
1375 extra
= (value
>> 3)
1378 if self
.record
.etype
is _SVEType
.EXTRA2
:
1380 assert (extra
& 0b111) == 0, \
1381 "vector CR cannot fit into EXTRA2"
1382 extra
= (0b10 |
(extra
>> 3))
1384 assert (extra
>> 1) == 0, \
1385 "scalar CR cannot fit into EXTRA2"
1387 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1389 assert (extra
& 0b11) == 0, \
1390 "vector CR cannot fit into EXTRA3"
1391 extra
= (0b100 |
(extra
>> 2))
1393 assert (extra
>> 2) == 0, \
1394 "scalar CR cannot fit into EXTRA3"
1397 if regtype
is _RegType
.CR_5BIT
:
1398 value
= ((value
<< 2) | subvalue
)
1400 return (value
, extra
)
1402 def assemble(self
, value
, insn
):
1403 if isinstance(value
, str):
1406 if value
.startswith("*"):
1407 if not isinstance(insn
, SVP64Instruction
):
1408 raise ValueError(value
)
1412 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1413 match
= pattern
.match(value
)
1414 if match
is not None:
1415 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1416 values
= match
.groups()
1417 match
= dict(zip(keys
, values
))
1418 CR
= int(match
["CR"])
1422 N
= int(match
.get("N", "1"))
1423 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1424 value
= ((CR
* N
) + BIT
)
1431 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1433 def disassemble(self
, insn
,
1434 style
=Style
.NORMAL
, prefix
="", indent
=""):
1435 (vector
, value
, span
) = self
.spec(insn
=insn
)
1437 if style
>= Style
.VERBOSE
:
1438 mode
= "vector" if vector
else "scalar"
1439 yield f
"{indent}{self.name} ({mode})"
1440 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1441 yield f
"{indent}{indent}{', '.join(span)}"
1442 if isinstance(insn
, SVP64Instruction
):
1443 extra_idx
= self
.extra_idx
1444 if self
.record
.etype
is _SVEType
.NONE
:
1445 yield f
"{indent}{indent}extra[none]"
1447 etype
= repr(self
.record
.etype
).lower()
1448 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1450 vector
= "*" if vector
else ""
1451 CR
= int(value
>> 2)
1453 cond
= ("lt", "gt", "eq", "so")[CC
]
1454 if style
>= Style
.NORMAL
:
1456 if isinstance(insn
, SVP64Instruction
):
1457 yield f
"{vector}cr{CR}.{cond}"
1459 yield f
"4*cr{CR}+{cond}"
1463 yield f
"{vector}{prefix}{int(value)}"
1466 class CR3Operand(ConditionRegisterFieldOperand
):
1467 def remap(self
, value
, vector
):
1468 return super().remap(value
=value
, vector
=vector
,
1469 regtype
=_RegType
.CR_3BIT
)
1472 class CR5Operand(ConditionRegisterFieldOperand
):
1473 def remap(self
, value
, vector
):
1474 return super().remap(value
=value
, vector
=vector
,
1475 regtype
=_RegType
.CR_5BIT
)
1477 def sv_spec_enter(self
, value
, span
):
1478 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1479 return (value
, span
)
1481 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1482 value
= _selectconcat(value
, origin_value
[3:5])
1484 return (value
, span
)
1487 class EXTSOperand(SignedOperand
):
1488 field
: str # real name to report
1489 nz
: int = 0 # number of zeros
1490 fmt
: str = "d" # integer formatter
1492 def __init__(self
, record
, name
, field
, nz
=0, fmt
="d"):
1493 self
.__field
= field
1496 return super().__init
__(record
=record
, name
=name
)
1512 return self
.record
.fields
[self
.field
]
1514 def assemble(self
, value
, insn
):
1516 if isinstance(value
, str):
1517 value
= int(value
, 0)
1518 insn
[span
] = (value
>> self
.nz
)
1520 def disassemble(self
, insn
,
1521 style
=Style
.NORMAL
, indent
=""):
1523 value
= insn
[span
].to_signed_int()
1524 sign
= "-" if (value
< 0) else ""
1525 value
= (abs(value
) << self
.nz
)
1527 if style
>= Style
.VERBOSE
:
1528 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1529 zeros
= ("0" * self
.nz
)
1530 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1531 yield f
"{indent * 1}{hint}"
1532 yield f
"{indent * 2}{self.field}"
1533 yield f
"{indent * 3}{sign}{value:{self.fmt}}"
1534 yield f
"{indent * 3}{', '.join(span)}"
1536 yield f
"{sign}{value:{self.fmt}}"
1539 class TargetAddrOperand(EXTSOperand
):
1540 def __init__(self
, record
, name
, field
):
1541 return super().__init
__(record
=record
, name
=name
, field
=field
, nz
=2, fmt
="#x")
1544 class TargetAddrOperandLI(TargetAddrOperand
):
1545 def __init__(self
, record
, name
):
1546 return super().__init
__(record
=record
, name
=name
, field
="LI")
1549 class TargetAddrOperandBD(TargetAddrOperand
):
1550 def __init__(self
, record
, name
):
1551 return super().__init
__(record
=record
, name
=name
, field
="BD")
1554 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1555 def __init__(self
, record
, name
):
1556 return super().__init
__(record
=record
, name
=name
, field
="DS", nz
=2)
1559 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1560 def __init__(self
, record
, name
):
1561 return super().__init
__(record
=record
, name
=name
, field
="DQ", nz
=4)
1564 class DOperandDX(SignedOperand
):
1567 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1568 operands
= map(cls
, ("d0", "d1", "d2"))
1569 spans
= map(lambda operand
: operand
.span
, operands
)
1570 return sum(spans
, tuple())
1572 def disassemble(self
, insn
,
1573 style
=Style
.NORMAL
, indent
=""):
1575 value
= insn
[span
].to_signed_int()
1576 sign
= "-" if (value
< 0) else ""
1579 if style
>= Style
.VERBOSE
:
1586 for (subname
, subspan
) in mapping
.items():
1587 operand
= DynamicOperand(name
=subname
)
1589 span
= map(str, span
)
1590 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1591 yield f
"{indent}{indent}{indent}{sign}{value}"
1592 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1594 yield f
"{sign}{value}"
1597 class Instruction(_Mapping
):
1599 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1600 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1601 raise ValueError(bits
)
1603 if isinstance(value
, bytes
):
1604 if ((len(value
) * 8) != bits
):
1605 raise ValueError(f
"bit length mismatch")
1606 value
= int.from_bytes(value
, byteorder
=byteorder
)
1608 if isinstance(value
, int):
1609 value
= _SelectableInt(value
=value
, bits
=bits
)
1610 elif isinstance(value
, Instruction
):
1611 value
= value
.storage
1613 if not isinstance(value
, _SelectableInt
):
1614 raise ValueError(value
)
1617 if len(value
) != bits
:
1618 raise ValueError(value
)
1620 value
= _SelectableInt(value
=value
, bits
=bits
)
1622 return cls(storage
=value
)
1625 return hash(int(self
))
1627 def __getitem__(self
, key
):
1628 return self
.storage
.__getitem
__(key
)
1630 def __setitem__(self
, key
, value
):
1631 return self
.storage
.__setitem
__(key
, value
)
1633 def bytes(self
, byteorder
="little"):
1634 nr_bytes
= (len(self
.__class
__) // 8)
1635 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1638 def record(cls
, db
, entry
):
1641 raise KeyError(entry
)
1644 def spec(self
, db
, prefix
):
1645 record
= self
.record(db
=db
, entry
=self
)
1647 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1648 self
.dynamic_operands(db
=db
)))
1650 static_operands
= []
1651 for (name
, value
) in record
.static_operands
:
1652 static_operands
.append(f
"{name}={value}")
1655 if dynamic_operands
:
1657 operands
+= ",".join(dynamic_operands
)
1660 operands
+= " ".join(static_operands
)
1662 return f
"{prefix}{record.name}{operands}"
1664 def static_operands(self
, db
):
1665 record
= self
.record(db
=db
, entry
=self
)
1666 for (op_cls
, op_kwargs
) in record
.static_operands
:
1667 operand
= op_cls(record
=record
, **op_kwargs
)
1668 yield (operand
.name
, operand
.value
)
1670 def dynamic_operands(self
, db
, style
=Style
.NORMAL
):
1671 record
= self
.record(db
=db
, entry
=self
)
1676 for (op_cls
, op_kwargs
) in record
.dynamic_operands
:
1677 operand
= op_cls(record
=record
, **op_kwargs
)
1679 value
= " ".join(operand
.disassemble(insn
=self
,
1680 style
=min(style
, Style
.NORMAL
)))
1682 name
= f
"{imm_name}({name})"
1683 value
= f
"{imm_value}({value})"
1685 if isinstance(operand
, ImmediateOperand
):
1693 def assemble(cls
, db
, entry
, arguments
=None):
1694 raise NotImplementedError()
1696 def disassemble(self
, db
,
1698 style
=Style
.NORMAL
):
1699 raise NotImplementedError()
1702 class WordInstruction(Instruction
):
1703 _
: _Field
= range(0, 32)
1704 PO
: _Field
= range(0, 6)
1707 def record(cls
, db
, entry
):
1708 record
= super().record(db
=db
, entry
=entry
)
1709 return _dataclasses
.replace(record
, svp64
=None)
1712 def integer(cls
, value
, byteorder
="little"):
1713 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1718 for idx
in range(32):
1719 bit
= int(self
[idx
])
1721 return "".join(map(str, bits
))
1724 def assemble(cls
, db
, entry
, arguments
=None, specifiers
=None):
1725 if arguments
is None:
1727 if specifiers
is None:
1730 record
= cls
.record(db
=db
, entry
=entry
)
1731 insn
= cls
.integer(value
=0)
1733 for (op_cls
, op_kwargs
) in record
.static_operands
:
1734 operand
= op_cls(record
=record
, **op_kwargs
)
1735 operand
.assemble(insn
=insn
)
1737 dynamic_operands
= tuple(record
.dynamic_operands
)
1738 for (value
, (op_cls
, op_kwargs
)) in Arguments(arguments
, dynamic_operands
):
1739 operand
= op_cls(record
=record
, **op_kwargs
)
1740 operand
.assemble(value
=value
, insn
=insn
)
1744 def disassemble(self
, db
,
1746 style
=Style
.NORMAL
):
1747 if style
<= Style
.SHORT
:
1750 blob
= self
.bytes(byteorder
=byteorder
)
1751 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1754 record
= self
.record(db
=db
, entry
=self
)
1756 yield f
"{blob}.long 0x{int(self):08x}"
1760 if style
is Style
.LEGACY
:
1762 for (op_cls
, _
) in record
.dynamic_operands
:
1763 if issubclass(op_cls
, (GPRPairOperand
, FPRPairOperand
)):
1766 if style
is Style
.LEGACY
and (paired
or record
.ppc
.unofficial
):
1767 yield f
"{blob}.long 0x{int(self):08x}"
1769 operands
= tuple(map(_operator
.itemgetter(1),
1770 self
.dynamic_operands(db
=db
, style
=style
)))
1772 operands
= ",".join(operands
)
1773 yield f
"{blob}{record.name} {operands}"
1775 yield f
"{blob}{record.name}"
1777 if style
>= Style
.VERBOSE
:
1779 binary
= self
.binary
1780 spec
= self
.spec(db
=db
, prefix
="")
1781 yield f
"{indent}spec"
1782 yield f
"{indent}{indent}{spec}"
1783 yield f
"{indent}pcode"
1784 for stmt
in record
.mdwn
.pcode
:
1785 yield f
"{indent}{indent}{stmt}"
1786 yield f
"{indent}binary"
1787 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1788 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1789 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1790 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1791 yield f
"{indent}opcodes"
1792 for opcode
in record
.opcodes
:
1793 yield f
"{indent}{indent}{opcode!r}"
1794 for (cls
, kwargs
) in record
.mdwn
.operands
:
1795 operand
= cls(record
=record
, **kwargs
)
1796 yield from operand
.disassemble(insn
=self
,
1797 style
=style
, indent
=indent
)
1801 class PrefixedInstruction(Instruction
):
1802 class Prefix(WordInstruction
.remap(range(0, 32))):
1805 class Suffix(WordInstruction
.remap(range(32, 64))):
1808 _
: _Field
= range(64)
1814 def integer(cls
, value
, byteorder
="little"):
1815 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
1818 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
1819 def transform(value
):
1820 return WordInstruction
.integer(value
=value
,
1821 byteorder
=byteorder
)[0:32]
1823 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
1824 value
= _selectconcat(prefix
, suffix
)
1826 return super().integer(bits
=64, value
=value
)
1829 class Mode(_Mapping
):
1830 _
: _Field
= range(0, 5)
1831 sel
: _Field
= (0, 1)
1834 class Extra(_Mapping
):
1835 _
: _Field
= range(0, 9)
1838 class Extra2(Extra
):
1839 idx0
: _Field
= range(0, 2)
1840 idx1
: _Field
= range(2, 4)
1841 idx2
: _Field
= range(4, 6)
1842 idx3
: _Field
= range(6, 8)
1844 def __getitem__(self
, key
):
1850 _SVExtra
.Idx0
: self
.idx0
,
1851 _SVExtra
.Idx1
: self
.idx1
,
1852 _SVExtra
.Idx2
: self
.idx2
,
1853 _SVExtra
.Idx3
: self
.idx3
,
1856 def __setitem__(self
, key
, value
):
1857 self
[key
].assign(value
)
1860 class Extra3(Extra
):
1861 idx0
: _Field
= range(0, 3)
1862 idx1
: _Field
= range(3, 6)
1863 idx2
: _Field
= range(6, 9)
1865 def __getitem__(self
, key
):
1870 _SVExtra
.Idx0
: self
.idx0
,
1871 _SVExtra
.Idx1
: self
.idx1
,
1872 _SVExtra
.Idx2
: self
.idx2
,
1875 def __setitem__(self
, key
, value
):
1876 self
[key
].assign(value
)
1879 class BaseRM(_Mapping
):
1880 _
: _Field
= range(24)
1881 mmode
: _Field
= (0,)
1882 mask
: _Field
= range(1, 4)
1883 elwidth
: _Field
= range(4, 6)
1884 ewsrc
: _Field
= range(6, 8)
1885 subvl
: _Field
= range(8, 10)
1886 mode
: Mode
.remap(range(19, 24))
1887 smask
: _Field
= range(16, 19)
1888 extra
: Extra
.remap(range(10, 19))
1889 extra2
: Extra2
.remap(range(10, 19))
1890 extra3
: Extra3
.remap(range(10, 19))
1892 def specifiers(self
, record
):
1893 subvl
= int(self
.subvl
)
1901 def disassemble(self
, style
=Style
.NORMAL
):
1902 if style
>= Style
.VERBOSE
:
1904 for (name
, span
) in self
.traverse(path
="RM"):
1905 value
= self
.storage
[span
]
1907 yield f
"{indent}{int(value):0{value.bits}b}"
1908 yield f
"{indent}{', '.join(map(str, span))}"
1911 class FFPRRc1BaseRM(BaseRM
):
1912 def specifiers(self
, record
, mode
):
1913 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
1914 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
1915 mask
= int(_selectconcat(CR
, inv
))
1916 predicate
= PredicateBaseRM
.predicate(True, mask
)
1917 yield f
"{mode}={predicate}"
1919 yield from super().specifiers(record
=record
)
1922 class FFPRRc0BaseRM(BaseRM
):
1923 def specifiers(self
, record
, mode
):
1925 inv
= "~" if self
.inv
else ""
1926 yield f
"{mode}={inv}RC1"
1928 yield from super().specifiers(record
=record
)
1931 class SatBaseRM(BaseRM
):
1932 def specifiers(self
, record
):
1938 yield from super().specifiers(record
=record
)
1941 class ZZBaseRM(BaseRM
):
1942 def specifiers(self
, record
):
1946 yield from super().specifiers(record
=record
)
1949 class ZZCombinedBaseRM(BaseRM
):
1950 def specifiers(self
, record
):
1951 if self
.sz
and self
.dz
:
1958 yield from super().specifiers(record
=record
)
1961 class DZBaseRM(BaseRM
):
1962 def specifiers(self
, record
):
1966 yield from super().specifiers(record
=record
)
1969 class SZBaseRM(BaseRM
):
1970 def specifiers(self
, record
):
1974 yield from super().specifiers(record
=record
)
1977 class MRBaseRM(BaseRM
):
1978 def specifiers(self
, record
):
1984 yield from super().specifiers(record
=record
)
1987 class ElsBaseRM(BaseRM
):
1988 def specifiers(self
, record
):
1992 yield from super().specifiers(record
=record
)
1995 class WidthBaseRM(BaseRM
):
1997 def width(FP
, width
):
2006 width
= ("fp" + width
)
2009 def specifiers(self
, record
):
2010 # elwidths: use "w=" if same otherwise dw/sw
2011 # FIXME this should consider FP instructions
2013 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
2014 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2023 yield from super().specifiers(record
=record
)
2026 class PredicateBaseRM(BaseRM
):
2028 def predicate(CR
, mask
):
2031 (False, 0b001): "1<<r3",
2032 (False, 0b010): "r3",
2033 (False, 0b011): "~r3",
2034 (False, 0b100): "r10",
2035 (False, 0b101): "~r10",
2036 (False, 0b110): "r30",
2037 (False, 0b111): "~r30",
2039 (True, 0b000): "lt",
2040 (True, 0b001): "ge",
2041 (True, 0b010): "gt",
2042 (True, 0b011): "le",
2043 (True, 0b100): "eq",
2044 (True, 0b101): "ne",
2045 (True, 0b110): "so",
2046 (True, 0b111): "ns",
2049 def specifiers(self
, record
):
2050 # predication - single and twin
2051 # use "m=" if same otherwise sm/dm
2052 CR
= (int(self
.mmode
) == 1)
2053 mask
= int(self
.mask
)
2054 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
2055 if record
.svp64
.ptype
is _SVPType
.P2
:
2056 smask
= int(self
.smask
)
2057 sm
= PredicateBaseRM
.predicate(CR
, smask
)
2066 yield from super().specifiers(record
=record
)
2069 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
2073 class SEABaseRM(BaseRM
):
2074 def specifiers(self
, record
):
2078 yield from super().specifiers(record
=record
)
2081 class VLiBaseRM(BaseRM
):
2082 def specifiers(self
, record
):
2086 yield from super().specifiers(record
=record
)
2089 class NormalBaseRM(PredicateWidthBaseRM
):
2092 https://libre-soc.org/openpower/sv/normal/
2097 class NormalSimpleRM(ZZCombinedBaseRM
, NormalBaseRM
):
2098 """normal: simple mode"""
2102 def specifiers(self
, record
):
2103 yield from super().specifiers(record
=record
)
2106 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
2107 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
2111 class NormalFFRc1RM(FFPRRc1BaseRM
, NormalBaseRM
):
2112 """normal: Rc=1: ffirst CR sel"""
2114 CR
: BaseRM
.mode
[3, 4]
2116 def specifiers(self
, record
):
2117 yield from super().specifiers(record
=record
, mode
="ff")
2120 class NormalFFRc0RM(FFPRRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
2121 """normal: Rc=0: ffirst z/nonz"""
2126 def specifiers(self
, record
):
2127 yield from super().specifiers(record
=record
, mode
="ff")
2130 class NormalSatRM(SatBaseRM
, ZZCombinedBaseRM
, NormalBaseRM
):
2131 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2137 class NormalPRRc1RM(FFPRRc1BaseRM
, NormalBaseRM
):
2138 """normal: Rc=1: pred-result CR sel"""
2140 CR
: BaseRM
.mode
[3, 4]
2142 def specifiers(self
, record
):
2143 yield from super().specifiers(record
=record
, mode
="pr")
2146 class NormalPRRc0RM(FFPRRc0BaseRM
, ZZBaseRM
, NormalBaseRM
):
2147 """normal: Rc=0: pred-result z/nonz"""
2154 def specifiers(self
, record
):
2155 yield from super().specifiers(record
=record
, mode
="pr")
2158 class NormalRM(NormalBaseRM
):
2159 simple
: NormalSimpleRM
2161 ffrc1
: NormalFFRc1RM
2162 ffrc0
: NormalFFRc0RM
2164 prrc1
: NormalPRRc1RM
2165 prrc0
: NormalPRRc0RM
2168 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2170 LD/ST Immediate mode
2171 https://libre-soc.org/openpower/sv/ldst/
2176 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2177 """ld/st immediate: simple mode"""
2184 class LDSTImmPostRM(LDSTImmBaseRM
):
2185 """ld/st immediate: postinc mode (and load-fault)"""
2186 pi
: BaseRM
.mode
[3] # Post-Increment Mode
2187 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2189 def specifiers(self
, record
):
2196 class LDSTImmFFRc1RM(FFPRRc1BaseRM
, LDSTImmBaseRM
):
2197 """ld/st immediate: Rc=1: ffirst CR sel"""
2199 CR
: BaseRM
.mode
[3, 4]
2201 def specifiers(self
, record
):
2202 yield from super().specifiers(record
=record
, mode
="ff")
2205 class LDSTImmFFRc0RM(FFPRRc0BaseRM
, ElsBaseRM
, LDSTImmBaseRM
):
2206 """ld/st immediate: Rc=0: ffirst z/nonz"""
2211 def specifiers(self
, record
):
2212 yield from super().specifiers(record
=record
, mode
="ff")
2215 class LDSTImmSatRM(ElsBaseRM
, SatBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2216 """ld/st immediate: sat mode: N=0/1 u/s"""
2224 class LDSTImmPRRc1RM(FFPRRc1BaseRM
, LDSTImmBaseRM
):
2225 """ld/st immediate: Rc=1: pred-result CR sel"""
2227 CR
: BaseRM
.mode
[3, 4]
2229 def specifiers(self
, record
):
2230 yield from super().specifiers(record
=record
, mode
="pr")
2233 class LDSTImmPRRc0RM(FFPRRc0BaseRM
, ElsBaseRM
, LDSTImmBaseRM
):
2234 """ld/st immediate: Rc=0: pred-result z/nonz"""
2239 def specifiers(self
, record
):
2240 yield from super().specifiers(record
=record
, mode
="pr")
2243 class LDSTImmRM(LDSTImmBaseRM
):
2244 simple
: LDSTImmSimpleRM
2246 ffrc1
: LDSTImmFFRc1RM
2247 ffrc0
: LDSTImmFFRc0RM
2249 prrc1
: LDSTImmPRRc1RM
2250 prrc0
: LDSTImmPRRc0RM
2253 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2256 https://libre-soc.org/openpower/sv/ldst/
2261 class LDSTIdxSimpleRM(SEABaseRM
, ZZCombinedBaseRM
, LDSTIdxBaseRM
):
2262 """ld/st index: simple mode"""
2268 class LDSTIdxStrideRM(SEABaseRM
, ZZCombinedBaseRM
, LDSTIdxBaseRM
):
2269 """ld/st index: strided (scalar only source)"""
2274 def specifiers(self
, record
):
2277 yield from super().specifiers(record
=record
)
2280 class LDSTIdxSatRM(SatBaseRM
, ZZCombinedBaseRM
, LDSTIdxBaseRM
):
2281 """ld/st index: sat mode: N=0/1 u/s"""
2287 class LDSTIdxPRRc1RM(LDSTIdxBaseRM
):
2288 """ld/st index: Rc=1: pred-result CR sel"""
2290 CR
: BaseRM
.mode
[3, 4]
2292 def specifiers(self
, record
):
2293 yield from super().specifiers(record
=record
, mode
="pr")
2296 class LDSTIdxPRRc0RM(FFPRRc0BaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2297 """ld/st index: Rc=0: pred-result z/nonz"""
2304 def specifiers(self
, record
):
2305 yield from super().specifiers(record
=record
, mode
="pr")
2308 class LDSTIdxRM(LDSTIdxBaseRM
):
2309 simple
: LDSTIdxSimpleRM
2310 stride
: LDSTIdxStrideRM
2312 prrc1
: LDSTIdxPRRc1RM
2313 prrc0
: LDSTIdxPRRc0RM
2317 class CROpBaseRM(BaseRM
):
2320 https://libre-soc.org/openpower/sv/cr_ops/
2325 class CROpSimpleRM(PredicateBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2326 """crop: simple mode"""
2331 def specifiers(self
, record
):
2333 yield "rg" # simple CR Mode reports /rg
2335 yield from super().specifiers(record
=record
)
2338 class CROpMRRM(MRBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2339 """crop: scalar reduce mode (mapreduce), SUBVL=1"""
2345 class CROpFF3RM(FFPRRc0BaseRM
, PredicateBaseRM
, VLiBaseRM
, DZBaseRM
, SZBaseRM
, CROpBaseRM
):
2346 """crop: ffirst 3-bit mode"""
2353 def specifiers(self
, record
):
2354 yield from super().specifiers(record
=record
, mode
="ff")
2357 # FIXME: almost everything in this class contradicts the specs.
2358 # However, this is the direct translation of the pysvp64asm code.
2359 # Please revisit this code; there is an inactive sketch below.
2360 class CROpFF5RM(FFPRRc1BaseRM
, PredicateBaseRM
, VLiBaseRM
, CROpBaseRM
):
2361 """cr_op: ffirst 5-bit mode"""
2368 def specifiers(self
, record
):
2369 # FIXME: this is a slightly hackish way.
2370 # Ideally the class should be generated.
2373 for (op_cls
, op_kwargs
) in record
.dynamic_operands
:
2374 operand
= op_cls(record
=record
, **op_kwargs
)
2375 if operand
.name
== record
.svp64
.extra_CR
.reg
.name
:
2376 span
= tuple(map(lambda bit
: (bit
+ 32), operand
.span
))
2379 value
= int(self
.storage
[span
])
2380 CR
= int(value
>> 2)
2383 cond
= ("lt", "gt", "eq", "so")[CC
]
2386 yield from super().specifiers(record
=record
, mode
="ff")
2389 class CROpRM(CROpBaseRM
):
2390 simple
: CROpSimpleRM
2396 # ********************
2398 # https://libre-soc.org/openpower/sv/branches/
2399 class BranchBaseRM(BaseRM
):
2409 def specifiers(self
, record
):
2421 raise ValueError(self
.sz
)
2433 # Branch modes lack source mask.
2434 # Therefore a custom code is needed.
2435 CR
= (int(self
.mmode
) == 1)
2436 mask
= int(self
.mask
)
2437 m
= PredicateBaseRM
.predicate(CR
, mask
)
2441 yield from super().specifiers(record
=record
)
2444 class BranchSimpleRM(BranchBaseRM
):
2445 """branch: simple mode"""
2449 class BranchVLSRM(BranchBaseRM
):
2450 """branch: VLSET mode"""
2454 def specifiers(self
, record
):
2460 }[int(self
.VSb
), int(self
.VLi
)]
2462 yield from super().specifiers(record
=record
)
2465 class BranchCTRRM(BranchBaseRM
):
2466 """branch: CTR-test mode"""
2469 def specifiers(self
, record
):
2475 yield from super().specifiers(record
=record
)
2478 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2479 """branch: CTR-test+VLSET mode"""
2483 class BranchRM(BranchBaseRM
):
2484 simple
: BranchSimpleRM
2487 ctrvls
: BranchCTRVLSRM
2498 @_dataclasses.dataclass(eq
=True, frozen
=True)
2503 def match(cls
, desc
, record
):
2504 raise NotImplementedError()
2506 def validate(self
, others
):
2509 def assemble(self
, insn
):
2510 raise NotImplementedError()
2513 @_dataclasses.dataclass(eq
=True, frozen
=True)
2514 class SpecifierWidth(Specifier
):
2518 def match(cls
, desc
, record
, etalon
):
2519 (mode
, _
, value
) = desc
.partition("=")
2521 value
= value
.strip()
2524 width
= _SVP64Width(value
)
2526 return cls(record
=record
, width
=width
)
2529 @_dataclasses.dataclass(eq
=True, frozen
=True)
2530 class SpecifierW(SpecifierWidth
):
2532 def match(cls
, desc
, record
):
2533 return super().match(desc
=desc
, record
=record
, etalon
="w")
2535 def assemble(self
, insn
):
2536 selector
= insn
.select(record
=self
.record
)
2537 selector
.ewsrc
= self
.width
.value
2538 selector
.elwidth
= self
.width
.value
2541 @_dataclasses.dataclass(eq
=True, frozen
=True)
2542 class SpecifierSW(SpecifierWidth
):
2544 def match(cls
, desc
, record
):
2545 return super().match(desc
=desc
, record
=record
, etalon
="sw")
2547 def assemble(self
, insn
):
2548 selector
= insn
.select(record
=self
.record
)
2549 selector
.ewsrc
= self
.width
.value
2552 @_dataclasses.dataclass(eq
=True, frozen
=True)
2553 class SpecifierDW(SpecifierWidth
):
2555 def match(cls
, desc
, record
):
2556 return super().match(desc
=desc
, record
=record
, etalon
="dw")
2558 def assemble(self
, insn
):
2559 selector
= insn
.select(record
=self
.record
)
2560 selector
.elwidth
= self
.width
.value
2563 @_dataclasses.dataclass(eq
=True, frozen
=True)
2564 class SpecifierSubVL(Specifier
):
2568 def match(cls
, desc
, record
):
2570 value
= _SVP64SubVL(desc
)
2574 return cls(record
=record
, value
=value
)
2576 def assemble(self
, insn
):
2577 selector
= insn
.select(record
=self
.record
)
2578 selector
.subvl
= int(self
.value
.value
)
2581 @_dataclasses.dataclass(eq
=True, frozen
=True)
2582 class SpecifierPredicate(Specifier
):
2587 def match(cls
, desc
, record
, mode_match
, pred_match
):
2588 (mode
, _
, pred
) = desc
.partition("=")
2591 if not mode_match(mode
):
2594 pred
= _SVP64Pred(pred
.strip())
2595 if not pred_match(pred
):
2596 raise ValueError(pred
)
2598 return cls(record
=record
, mode
=mode
, pred
=pred
)
2601 @_dataclasses.dataclass(eq
=True, frozen
=True)
2602 class SpecifierFFPR(SpecifierPredicate
):
2604 def match(cls
, desc
, record
, mode
):
2605 return super().match(desc
=desc
, record
=record
,
2606 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2607 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2612 def validate(self
, others
):
2613 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2614 if self
.mode
== "pr":
2615 raise ValueError("crop: 'pr' mode not supported")
2616 if (self
.record
.svp64
.extra_CR_3bit
and
2617 (self
.pred
.mode
is not _SVP64PredMode
.RC1
)):
2618 raise ValueError("3-bit CRs only support RC1/~RC1 BO")
2620 def assemble(self
, insn
):
2621 selector
= insn
.select(record
=self
.record
)
2622 if selector
.mode
.sel
!= 0:
2623 raise ValueError("cannot override mode")
2624 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2625 selector
.mode
.sel
= 0b10
2626 selector
.inv
= self
.pred
.inv
2627 if not self
.record
.svp64
.extra_CR_3bit
:
2628 selector
.CR
= self
.pred
.state
2630 selector
.mode
.sel
= 0b01 if self
.mode
== "ff" else 0b11
2631 selector
.inv
= self
.pred
.inv
2633 selector
.CR
= self
.pred
.state
2635 selector
.RC1
= self
.pred
.state
2638 @_dataclasses.dataclass(eq
=True, frozen
=True)
2639 class SpecifierFF(SpecifierFFPR
):
2641 def match(cls
, desc
, record
):
2642 return super().match(desc
=desc
, record
=record
, mode
="ff")
2645 @_dataclasses.dataclass(eq
=True, frozen
=True)
2646 class SpecifierPR(SpecifierFFPR
):
2648 def match(cls
, desc
, record
):
2649 return super().match(desc
=desc
, record
=record
, mode
="pr")
2652 @_dataclasses.dataclass(eq
=True, frozen
=True)
2653 class SpecifierMask(SpecifierPredicate
):
2655 def match(cls
, desc
, record
, mode
):
2656 return super().match(desc
=desc
, record
=record
,
2657 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2658 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2663 def assemble(self
, insn
):
2664 raise NotImplementedError()
2667 @_dataclasses.dataclass(eq
=True, frozen
=True)
2668 class SpecifierM(SpecifierMask
):
2670 def match(cls
, desc
, record
):
2671 return super().match(desc
=desc
, record
=record
, mode
="m")
2673 def validate(self
, others
):
2675 if isinstance(spec
, SpecifierSM
):
2676 raise ValueError("source-mask and predicate mask conflict")
2677 elif isinstance(spec
, SpecifierDM
):
2678 raise ValueError("dest-mask and predicate mask conflict")
2680 def assemble(self
, insn
):
2681 selector
= insn
.select(record
=self
.record
)
2682 selector
.mask
= int(self
.pred
)
2683 if ((self
.record
.ptype
is _SVPType
.P2
) and
2684 (self
.record
.svp64
.mode
is not _SVMode
.BRANCH
)):
2685 selector
.smask
= int(self
.pred
)
2686 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2689 @_dataclasses.dataclass(eq
=True, frozen
=True)
2690 class SpecifierSM(SpecifierMask
):
2692 def match(cls
, desc
, record
):
2693 return super().match(desc
=desc
, record
=record
, mode
="sm")
2695 def validate(self
, others
):
2696 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2697 raise ValueError("source-mask on non-twin predicate")
2699 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2702 if isinstance(spec
, SpecifierDM
):
2706 raise ValueError("missing dest-mask in CR twin predication")
2707 if self
.pred
.mode
!= twin
.pred
.mode
:
2708 raise ValueError(f
"predicate masks mismatch: {self.pred!r} vs {twin.pred!r}")
2710 def assemble(self
, insn
):
2711 selector
= insn
.select(record
=self
.record
)
2712 selector
.smask
= int(self
.pred
)
2713 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2716 @_dataclasses.dataclass(eq
=True, frozen
=True)
2717 class SpecifierDM(SpecifierMask
):
2719 def match(cls
, desc
, record
):
2720 return super().match(desc
=desc
, record
=record
, mode
="dm")
2722 def validate(self
, others
):
2723 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2724 raise ValueError("dest-mask on non-twin predicate")
2726 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2729 if isinstance(spec
, SpecifierSM
):
2733 raise ValueError("missing source-mask in CR twin predication")
2734 if self
.pred
.mode
!= twin
.pred
.mode
:
2735 raise ValueError(f
"predicate masks mismatch: {self.pred!r} vs {twin.pred!r}")
2737 def assemble(self
, insn
):
2738 selector
= insn
.select(record
=self
.record
)
2739 selector
.mask
= int(self
.pred
)
2740 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2743 @_dataclasses.dataclass(eq
=True, frozen
=True)
2744 class SpecifierZZ(Specifier
):
2746 def match(cls
, desc
, record
):
2750 return cls(record
=record
)
2752 def validate(self
, others
):
2754 # Since zz takes precedence (overrides) sz and dz,
2755 # treat them as mutually exclusive.
2756 if isinstance(spec
, (SpecifierSZ
, SpecifierDZ
)):
2757 raise ValueError("mutually exclusive predicate masks")
2759 def assemble(self
, insn
):
2760 selector
= insn
.select(record
=self
.record
)
2761 if hasattr(selector
, "zz"): # this should be done in a different way
2768 @_dataclasses.dataclass(eq
=True, frozen
=True)
2769 class SpecifierXZ(Specifier
):
2771 hint
: str = _dataclasses
.field(repr=False)
2774 def match(cls
, desc
, record
, etalon
, hint
):
2778 return cls(desc
=desc
, record
=record
, hint
=hint
)
2780 def validate(self
, others
):
2781 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2782 raise ValueError(f
"{self.hint} on non-twin predicate")
2784 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2787 if isinstance(spec
, SpecifierXZ
):
2791 raise ValueError(f
"missing {self.hint} in CR twin predication")
2792 if self
.pred
!= twin
.pred
:
2793 raise ValueError(f
"predicate masks mismatch: {self.pred!r} vs {twin.pred!r}")
2795 def assemble(self
, insn
):
2796 selector
= insn
.select(record
=self
.record
)
2797 setattr(selector
, self
.desc
, 1)
2800 @_dataclasses.dataclass(eq
=True, frozen
=True)
2801 class SpecifierSZ(SpecifierXZ
):
2803 def match(cls
, desc
, record
):
2804 return super().match(desc
=desc
, record
=record
,
2805 etalon
="sz", hint
="source-mask")
2807 def validate(self
, others
):
2809 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2810 if isinstance(spec
, SpecifierFF
):
2811 raise ValueError("source-zero not allowed in ff mode")
2812 elif isinstance(spec
, SpecifierPR
):
2813 raise ValueError("source-zero not allowed in pr mode")
2816 @_dataclasses.dataclass(eq
=True, frozen
=True)
2817 class SpecifierDZ(SpecifierXZ
):
2819 def match(cls
, desc
, record
):
2820 return super().match(desc
=desc
, record
=record
,
2821 etalon
="dz", hint
="dest-mask")
2823 def validate(self
, others
):
2825 if ((self
.record
.svp64
.mode
is not _SVMode
.CROP
) and
2826 isinstance(spec
, (SpecifierFF
, SpecifierPR
)) and
2827 (spec
.pred
.mode
is _SVP64PredMode
.RC1
)):
2828 mode
= "ff" if isinstance(spec
, SpecifierFF
) else "pr"
2829 raise ValueError(f
"dest-zero not allowed in {mode} mode BO")
2832 @_dataclasses.dataclass(eq
=True, frozen
=True)
2833 class SpecifierEls(Specifier
):
2835 def match(cls
, desc
, record
):
2839 if record
.svp64
.mode
not in (_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
):
2840 raise ValueError("els is only valid in ld/st modes")
2842 return cls(record
=record
)
2844 def assemble(self
, insn
):
2845 if self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
: # stride mode
2846 insn
.prefix
.rm
.mode
[0] = 0
2847 insn
.prefix
.rm
.mode
[1] = 1
2849 selector
= insn
.select(record
=self
.record
)
2850 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
: # stride mode
2855 @_dataclasses.dataclass(eq
=True, frozen
=True)
2856 class SpecifierSEA(Specifier
):
2858 def match(cls
, desc
, record
):
2862 return cls(record
=record
)
2864 def validate(self
, others
):
2865 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
:
2866 raise ValueError("sea is only valid in ld/st modes")
2869 if isinstance(spec
, SpecifierFF
):
2870 raise ValueError(f
"sea cannot be used in ff mode")
2872 def assemble(self
, insn
):
2873 selector
= insn
.select(record
=self
.record
)
2874 if selector
.mode
.sel
not in (0b00, 0b01):
2875 raise ValueError("sea is only valid for normal and els modes")
2879 @_dataclasses.dataclass(eq
=True, frozen
=True)
2880 class SpecifierSat(Specifier
):
2885 def match(cls
, desc
, record
, etalon
, sign
):
2889 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
):
2890 raise ValueError("only normal, ld/st imm and ld/st idx modes supported")
2892 return cls(record
=record
, desc
=desc
, sign
=sign
)
2894 def assemble(self
, insn
):
2895 selector
= insn
.select(record
=self
.record
)
2896 selector
.mode
[0] = 0b1
2897 selector
.mode
[1] = 0b0
2898 selector
.N
= int(self
.sign
)
2901 @_dataclasses.dataclass(eq
=True, frozen
=True)
2902 class SpecifierSatS(SpecifierSat
):
2904 def match(cls
, desc
, record
):
2905 return super().match(desc
=desc
, record
=record
,
2906 etalon
="sats", sign
=True)
2909 @_dataclasses.dataclass(eq
=True, frozen
=True)
2910 class SpecifierSatU(SpecifierSat
):
2912 def match(cls
, desc
, record
):
2913 return super().match(desc
=desc
, record
=record
,
2914 etalon
="satu", sign
=False)
2917 @_dataclasses.dataclass(eq
=True, frozen
=True)
2918 class SpecifierMapReduce(Specifier
):
2922 def match(cls
, record
, RG
):
2923 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2924 raise ValueError("only normal and crop modes supported")
2926 return cls(record
=record
, RG
=RG
)
2928 def assemble(self
, insn
):
2929 selector
= insn
.select(record
=self
.record
)
2930 if self
.record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2931 raise ValueError("only normal and crop modes supported")
2932 selector
.mode
[0] = 0
2933 selector
.mode
[1] = 0
2934 selector
.mode
[2] = 1
2935 selector
.RG
= self
.RG
2938 @_dataclasses.dataclass(eq
=True, frozen
=True)
2939 class SpecifierMR(SpecifierMapReduce
):
2941 def match(cls
, desc
, record
):
2945 return super().match(record
=record
, RG
=False)
2948 @_dataclasses.dataclass(eq
=True, frozen
=True)
2949 class SpecifierMRR(SpecifierMapReduce
):
2951 def match(cls
, desc
, record
):
2955 return super().match(record
=record
, RG
=True)
2958 @_dataclasses.dataclass(eq
=True, frozen
=True)
2959 class SpecifierBranch(Specifier
):
2961 def match(cls
, desc
, record
, etalon
):
2965 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
2966 raise ValueError("only branch modes supported")
2968 return cls(record
=record
)
2971 @_dataclasses.dataclass(eq
=True, frozen
=True)
2972 class SpecifierAll(SpecifierBranch
):
2974 def match(cls
, desc
, record
):
2975 return super().match(desc
=desc
, record
=record
, etalon
="all")
2977 def assemble(self
, insn
):
2978 selector
= insn
.select(record
=self
.record
)
2982 @_dataclasses.dataclass(eq
=True, frozen
=True)
2983 class SpecifierSNZ(Specifier
):
2985 def match(cls
, desc
, record
):
2989 if record
.svp64
.mode
not in (_SVMode
.BRANCH
, _SVMode
.CROP
):
2990 raise ValueError("only branch and crop modes supported")
2992 return cls(record
=record
)
2994 def assemble(self
, insn
):
2995 selector
= insn
.select(record
=self
.record
)
2996 if self
.record
.svp64
.mode
in (_SVMode
.CROP
, _SVMode
.BRANCH
):
2998 if self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3001 raise ValueError("only branch and crop modes supported")
3004 @_dataclasses.dataclass(eq
=True, frozen
=True)
3005 class SpecifierSL(SpecifierBranch
):
3007 def match(cls
, desc
, record
):
3008 return super().match(desc
=desc
, record
=record
, etalon
="sl")
3010 def assemble(self
, insn
):
3011 selector
= insn
.select(record
=self
.record
)
3015 @_dataclasses.dataclass(eq
=True, frozen
=True)
3016 class SpecifierSLu(SpecifierBranch
):
3018 def match(cls
, desc
, record
):
3019 return super().match(desc
=desc
, record
=record
, etalon
="slu")
3021 def assemble(self
, insn
):
3022 selector
= insn
.select(record
=self
.record
)
3026 @_dataclasses.dataclass(eq
=True, frozen
=True)
3027 class SpecifierLRu(SpecifierBranch
):
3029 def match(cls
, desc
, record
):
3030 return super().match(desc
=desc
, record
=record
, etalon
="lru")
3032 def assemble(self
, insn
):
3033 selector
= insn
.select(record
=self
.record
)
3037 @_dataclasses.dataclass(eq
=True, frozen
=True)
3038 class SpecifierVSXX(SpecifierBranch
):
3043 def match(cls
, desc
, record
, etalon
, VSb
, VLi
):
3047 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3048 raise ValueError("only branch modes supported")
3050 return cls(record
=record
, VSb
=VSb
, VLi
=VLi
)
3052 def assemble(self
, insn
):
3053 selector
= insn
.select(record
=self
.record
)
3055 selector
.VSb
= int(self
.VSb
)
3056 selector
.VLi
= int(self
.VLi
)
3059 @_dataclasses.dataclass(eq
=True, frozen
=True)
3060 class SpecifierVS(SpecifierVSXX
):
3062 def match(cls
, desc
, record
):
3063 return super().match(desc
=desc
, record
=record
,
3064 etalon
="vs", VSb
=False, VLi
=False)
3067 @_dataclasses.dataclass(eq
=True, frozen
=True)
3068 class SpecifierVSi(SpecifierVSXX
):
3070 def match(cls
, desc
, record
):
3071 return super().match(desc
=desc
, record
=record
,
3072 etalon
="vsi", VSb
=False, VLi
=True)
3075 @_dataclasses.dataclass(eq
=True, frozen
=True)
3076 class SpecifierVSb(SpecifierVSXX
):
3078 def match(cls
, desc
, record
):
3079 return super().match(desc
=desc
, record
=record
,
3080 etalon
="vsb", VSb
=True, VLi
=False)
3083 @_dataclasses.dataclass(eq
=True, frozen
=True)
3084 class SpecifierVSbi(SpecifierVSXX
):
3086 def match(cls
, desc
, record
):
3087 return super().match(desc
=desc
, record
=record
,
3088 etalon
="vsbi", VSb
=True, VLi
=True)
3091 @_dataclasses.dataclass(eq
=True, frozen
=True)
3092 class SpecifierCTX(Specifier
):
3096 def match(cls
, desc
, record
, etalon
, CTi
):
3100 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3101 raise ValueError("only branch modes supported")
3103 return cls(record
=record
, CTi
=CTi
)
3105 def assemble(self
, insn
):
3106 selector
= insn
.select(record
=self
.record
)
3108 selector
.CTi
= int(self
.CTi
)
3111 @_dataclasses.dataclass(eq
=True, frozen
=True)
3112 class SpecifierCTR(SpecifierCTX
):
3114 def match(cls
, desc
, record
):
3115 return super().match(desc
=desc
, record
=record
,
3116 etalon
="ctr", CTi
=False)
3119 @_dataclasses.dataclass(eq
=True, frozen
=True)
3120 class SpecifierCTi(SpecifierCTX
):
3122 def match(cls
, desc
, record
):
3123 return super().match(desc
=desc
, record
=record
,
3124 etalon
="cti", CTi
=True)
3127 @_dataclasses.dataclass(eq
=True, frozen
=True)
3128 class SpecifierPI(Specifier
):
3130 def match(cls
, desc
, record
):
3134 if record
.svp64
.mode
is not _SVMode
.LDST_IMM
:
3135 raise ValueError("only ld/st imm mode supported")
3137 return cls(record
=record
)
3139 def assemble(self
, insn
):
3140 selector
= insn
.select(record
=self
.record
)
3141 selector
.mode
[0] = 0b0
3142 selector
.mode
[1] = 0b0
3143 selector
.mode
[2] = 0b1
3147 @_dataclasses.dataclass(eq
=True, frozen
=True)
3148 class SpecifierLF(Specifier
):
3150 def match(cls
, desc
, record
):
3154 if record
.svp64
.mode
is not _SVMode
.LDST_IMM
:
3155 raise ValueError("only ld/st imm mode supported")
3157 return cls(record
=record
)
3159 def assemble(self
, insn
):
3160 selector
= insn
.select(record
=self
.record
)
3161 selector
.mode
[2] = 1
3165 @_dataclasses.dataclass(eq
=True, frozen
=True)
3166 class SpecifierVLi(Specifier
):
3168 def match(cls
, desc
, record
):
3172 return cls(record
=record
)
3174 def validate(self
, others
):
3176 if isinstance(spec
, SpecifierFF
):
3179 raise ValueError("VLi only allowed in failfirst")
3181 def assemble(self
, insn
):
3182 selector
= insn
.select(record
=self
.record
)
3186 class Specifiers(tuple):
3222 def __new__(cls
, items
, record
):
3223 def transform(item
):
3224 for spec_cls
in cls
.SPECS
:
3225 spec
= spec_cls
.match(item
, record
=record
)
3226 if spec
is not None:
3228 raise ValueError(item
)
3230 # TODO: remove this hack
3231 items
= dict.fromkeys(items
)
3235 items
= tuple(items
)
3237 specs
= tuple(map(transform
, items
))
3238 for (index
, spec
) in enumerate(specs
):
3239 head
= specs
[:index
]
3240 tail
= specs
[index
+ 1:]
3241 spec
.validate(others
=(head
+ tail
))
3243 return super().__new
__(cls
, specs
)
3246 class SVP64OperandMeta(type):
3247 class SVP64NonZeroOperand(NonZeroOperand
):
3248 def assemble(self
, value
, insn
):
3249 if isinstance(value
, str):
3250 value
= int(value
, 0)
3251 if not isinstance(value
, int):
3252 raise ValueError("non-integer operand")
3254 # FIXME: this is really weird
3255 if self
.record
.name
in ("svstep", "svstep."):
3256 value
+= 1 # compensation
3258 return super().assemble(value
=value
, insn
=insn
)
3261 NonZeroOperand
: SVP64NonZeroOperand
,
3264 def __new__(metacls
, name
, bases
, ns
):
3266 for (origin_cls
, target_cls
) in metacls
.__TRANSFORM
.items():
3267 for (index
, base_cls
) in enumerate(bases
):
3268 if base_cls
is origin_cls
:
3269 bases
[index
] = target_cls
3271 bases
= tuple(bases
)
3273 return super().__new
__(metacls
, name
, bases
, ns
)
3276 class SVP64Operand(Operand
, metaclass
=SVP64OperandMeta
):
3277 def __init__(self
, record
, *args
, **kwargs
):
3278 return super().__init
__(record
=record
, *args
, **kwargs
)
3282 return tuple(map(lambda bit
: (bit
+ 32), super().span
))
3286 def __init__(self
, insn
, record
):
3288 self
.__record
= record
3289 return super().__init
__()
3292 return repr(self
.rm
)
3300 return self
.__record
3304 rm
= getattr(self
.insn
.prefix
.rm
, self
.record
.svp64
.mode
.name
.lower())
3306 # The idea behind these tables is that they are now literally
3307 # in identical format to insndb.csv and minor_xx.csv and can
3308 # be done precisely as that. The only thing to watch out for
3309 # is the insertion of Rc=1 as a "mask/value" bit and likewise
3310 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
3313 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
3314 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3315 # mode Rc mask Rc member
3317 (0b000000, 0b111000, "simple"), # simple (no Rc)
3318 (0b001000, 0b111000, "mr"), # mapreduce (no Rc)
3319 (0b010001, 0b110001, "ffrc1"), # ffirst, Rc=1
3320 (0b010000, 0b110001, "ffrc0"), # ffirst, Rc=0
3321 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3322 (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
3323 (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
3325 search
= ((int(self
.insn
.prefix
.rm
.normal
.mode
) << 1) | self
.record
.Rc
)
3327 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
3328 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3329 # mode Rc mask Rc member
3330 # ironically/coincidentally this table is identical to NORMAL
3331 # mode except reserved in place of mr
3333 (0b000000, 0b111000, "simple"), # simple (no Rc)
3334 (0b001000, 0b111000, "post"), # post (no Rc)
3335 (0b010001, 0b110001, "ffrc1"), # ffirst, Rc=1
3336 (0b010000, 0b110001, "ffrc0"), # ffirst, Rc=0
3337 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3338 (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
3339 (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
3341 search
= ((int(self
.insn
.prefix
.rm
.ldst_imm
.mode
) << 1) | self
.record
.Rc
)
3343 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
3344 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3345 # mode Rc mask Rc member
3347 (0b000000, 0b110000, "simple"), # simple (no Rc)
3348 (0b010000, 0b110000, "stride"), # strided, (no Rc)
3349 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3350 (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
3351 (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
3353 search
= ((int(self
.insn
.prefix
.rm
.ldst_idx
.mode
) << 1) | self
.record
.Rc
)
3355 elif self
.record
.svp64
.mode
is _SVMode
.CROP
:
3356 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
3357 # mode 3b mask 3b member
3359 (0b000000, 0b111000, "simple"), # simple
3360 (0b001000, 0b111000, "mr"), # mapreduce
3361 (0b100001, 0b100001, "ff3"), # ffirst, 3-bit CR
3362 (0b100000, 0b100000, "ff5"), # ffirst, 5-bit CR
3364 search
= ((int(self
.insn
.prefix
.rm
.crop
.mode
) << 1) |
int(self
.record
.svp64
.extra_CR_3bit
))
3366 elif self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3370 (0b00, 0b11, "simple"), # simple
3371 (0b01, 0b11, "vls"), # VLset
3372 (0b10, 0b11, "ctr"), # CTR mode
3373 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
3375 # slightly weird: doesn't have a 5-bit "mode" field like others
3376 search
= int(self
.insn
.prefix
.rm
.branch
.mode
.sel
)
3379 if table
is not None:
3380 for (value
, mask
, field
) in table
:
3381 if ((value
& mask
) == (search
& mask
)):
3382 return getattr(rm
, field
)
3386 def __getattr__(self
, key
):
3387 if key
.startswith(f
"_{self.__class__.__name__}__"):
3388 return super().__getattribute
__(key
)
3390 return getattr(self
.rm
, key
)
3392 def __setattr__(self
, key
, value
):
3393 if key
.startswith(f
"_{self.__class__.__name__}__"):
3394 return super().__setattr
__(key
, value
)
3397 if not hasattr(rm
, key
):
3398 raise AttributeError(key
)
3400 return setattr(rm
, key
, value
)
3403 class SVP64Instruction(PrefixedInstruction
):
3404 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
3405 class Prefix(PrefixedInstruction
.Prefix
):
3407 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
3411 def select(self
, record
):
3412 return RMSelector(insn
=self
, record
=record
)
3415 def record(cls
, db
, entry
):
3416 if isinstance(entry
, cls
):
3417 entry
= entry
.suffix
3418 return super().record(db
=db
, entry
=entry
)
3423 for idx
in range(64):
3424 bit
= int(self
[idx
])
3426 return "".join(map(str, bits
))
3429 def assemble(cls
, db
, entry
, arguments
=None, specifiers
=None):
3430 if arguments
is None:
3432 if specifiers
is None:
3435 record
= cls
.record(db
=db
, entry
=entry
)
3436 insn
= cls
.integer(value
=0)
3438 for (op_cls
, op_kwargs
) in record
.static_operands
:
3439 op_cls
= type(f
"SVP64{op_cls.__name__}", (SVP64Operand
, op_cls
), {})
3440 operand
= op_cls(record
=record
, **op_kwargs
)
3441 operand
.assemble(insn
=insn
)
3443 specifiers
= Specifiers(items
=specifiers
, record
=record
)
3444 for specifier
in specifiers
:
3445 specifier
.assemble(insn
=insn
)
3447 dynamic_operands
= tuple(record
.dynamic_operands
)
3448 for (value
, (op_cls
, op_kwargs
)) in Arguments(arguments
, dynamic_operands
):
3449 op_cls
= type(f
"SVP64{op_cls.__name__}", (SVP64Operand
, op_cls
), {})
3450 operand
= op_cls(record
=record
, **op_kwargs
)
3451 operand
.assemble(value
=value
, insn
=insn
)
3453 insn
.prefix
.PO
= 0x1
3454 insn
.prefix
.id = 0x3
3459 def disassemble(self
, db
,
3461 style
=Style
.NORMAL
):
3464 if style
<= Style
.SHORT
:
3467 blob
= insn
.bytes(byteorder
=byteorder
)
3468 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
3471 record
= self
.record(db
=db
, entry
=self
)
3472 blob_prefix
= blob(self
.prefix
)
3473 blob_suffix
= blob(self
.suffix
)
3474 if record
is None or record
.svp64
is None:
3475 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3476 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
3479 name
= f
"sv.{record.name}"
3481 rm
= self
.select(record
=record
)
3483 # convert specifiers to /x/y/z (sorted lexicographically)
3484 specifiers
= sorted(rm
.specifiers(record
=record
))
3485 if specifiers
: # if any add one extra to get the extra "/"
3486 specifiers
= ([""] + specifiers
)
3487 specifiers
= "/".join(specifiers
)
3489 # convert operands to " ,x,y,z"
3490 operands
= tuple(map(_operator
.itemgetter(1),
3491 self
.dynamic_operands(db
=db
, style
=style
)))
3492 operands
= ",".join(operands
)
3493 if len(operands
) > 0: # if any separate with a space
3494 operands
= (" " + operands
)
3496 if style
<= Style
.LEGACY
:
3497 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3498 suffix
= WordInstruction
.integer(value
=int(self
.suffix
))
3499 yield from suffix
.disassemble(db
=db
,
3500 byteorder
=byteorder
, style
=style
)
3502 yield f
"{blob_prefix}{name}{specifiers}{operands}"
3504 yield f
"{blob_suffix}"
3506 if style
>= Style
.VERBOSE
:
3508 binary
= self
.binary
3509 spec
= self
.spec(db
=db
, prefix
="sv.")
3511 yield f
"{indent}spec"
3512 yield f
"{indent}{indent}{spec}"
3513 yield f
"{indent}pcode"
3514 for stmt
in record
.mdwn
.pcode
:
3515 yield f
"{indent}{indent}{stmt}"
3516 yield f
"{indent}binary"
3517 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
3518 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
3519 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
3520 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
3521 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
3522 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
3523 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
3524 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
3525 yield f
"{indent}opcodes"
3526 for opcode
in record
.opcodes
:
3527 yield f
"{indent}{indent}{opcode!r}"
3528 for (cls
, kwargs
) in record
.mdwn
.operands
:
3529 operand
= cls(record
=record
, **kwargs
)
3530 yield from operand
.disassemble(insn
=self
,
3531 style
=style
, indent
=indent
)
3533 yield f
"{indent}{indent}{rm.__doc__}"
3534 for line
in rm
.disassemble(style
=style
):
3535 yield f
"{indent}{indent}{line}"
3538 def static_operands(self
, db
):
3539 record
= self
.record(db
=db
, entry
=self
)
3540 for (op_cls
, op_kwargs
) in record
.static_operands
:
3541 op_cls
= type(f
"SVP64{op_cls.__name__}", (SVP64Operand
, op_cls
), {})
3542 operand
= op_cls(record
=record
, **op_kwargs
)
3543 yield (operand
.name
, operand
.value
)
3545 def dynamic_operands(self
, db
, style
=Style
.NORMAL
):
3546 record
= self
.record(db
=db
, entry
=self
)
3551 for (op_cls
, op_kwargs
) in record
.dynamic_operands
:
3552 op_cls
= type(f
"SVP64{op_cls.__name__}", (SVP64Operand
, op_cls
), {})
3553 operand
= op_cls(record
=record
, **op_kwargs
)
3555 value
= " ".join(operand
.disassemble(insn
=self
,
3556 style
=min(style
, Style
.NORMAL
)))
3558 name
= f
"{imm_name}({name})"
3559 value
= f
"{imm_value}({value})"
3561 if isinstance(operand
, ImmediateOperand
):
3569 def parse(stream
, factory
):
3571 return ("TODO" not in frozenset(entry
.values()))
3573 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
3574 entries
= _csv
.DictReader(lines
)
3575 entries
= filter(match
, entries
)
3576 return tuple(map(factory
, entries
))
3579 class MarkdownDatabase
:
3582 for (name
, desc
) in _ISA():
3585 (dynamic
, *static
) = desc
.regs
3586 operands
.extend(dynamic
)
3587 operands
.extend(static
)
3588 pcode
= PCode(iterable
=desc
.pcode
)
3589 operands
= Operands(insn
=name
, iterable
=operands
)
3590 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
3592 self
.__db
= dict(sorted(db
.items()))
3594 return super().__init
__()
3597 yield from self
.__db
.items()
3599 def __contains__(self
, key
):
3600 return self
.__db
.__contains
__(key
)
3602 def __getitem__(self
, key
):
3603 return self
.__db
.__getitem
__(key
)
3606 class FieldsDatabase
:
3609 df
= _DecodeFields()
3611 for (form
, fields
) in df
.instrs
.items():
3612 if form
in {"DQE", "TX"}:
3616 db
[_Form
[form
]] = Fields(fields
)
3620 return super().__init
__()
3622 def __getitem__(self
, key
):
3623 return self
.__db
.__getitem
__(key
)
3627 def __init__(self
, root
, mdwndb
):
3628 # The code below groups the instructions by name:section.
3629 # There can be multiple names for the same instruction.
3630 # The point is to capture different opcodes for the same instruction.
3632 records
= _collections
.defaultdict(set)
3633 path
= (root
/ "insndb.csv")
3634 with
open(path
, "r", encoding
="UTF-8") as stream
:
3635 for section
in sorted(parse(stream
, Section
.CSV
)):
3636 path
= (root
/ section
.path
)
3638 section
.Mode
.INTEGER
: IntegerOpcode
,
3639 section
.Mode
.PATTERN
: PatternOpcode
,
3641 factory
= _functools
.partial(
3642 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
3643 with
open(path
, "r", encoding
="UTF-8") as stream
:
3644 for insn
in parse(stream
, factory
):
3645 for name
in insn
.names
:
3646 records
[name
].add(insn
)
3647 sections
[name
] = section
3649 items
= sorted(records
.items())
3651 for (name
, multirecord
) in items
:
3652 records
[name
] = PPCMultiRecord(sorted(multirecord
))
3654 def exact_match(name
):
3655 record
= records
.get(name
)
3661 if not name
.endswith("l"):
3663 alias
= exact_match(name
[:-1])
3666 record
= records
[alias
]
3667 if "lk" not in record
.flags
:
3668 raise ValueError(record
)
3672 if not name
.endswith("a"):
3674 alias
= LK_match(name
[:-1])
3677 record
= records
[alias
]
3678 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
3679 raise ValueError(record
)
3680 if "AA" not in mdwndb
[name
].operands
:
3681 raise ValueError(record
)
3685 if not name
.endswith("."):
3687 alias
= exact_match(name
[:-1])
3690 record
= records
[alias
]
3691 if record
.Rc
is _RCOE
.NONE
:
3692 raise ValueError(record
)
3696 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
3697 for (name
, _
) in mdwndb
:
3698 if name
.startswith("sv."):
3701 for match
in matches
:
3703 if alias
is not None:
3707 section
= sections
[alias
]
3708 record
= records
[alias
]
3709 db
[name
] = (section
, record
)
3711 self
.__db
= dict(sorted(db
.items()))
3713 return super().__init
__()
3715 @_functools.lru_cache(maxsize
=512, typed
=False)
3716 def __getitem__(self
, key
):
3717 return self
.__db
.get(key
, (None, None))
3720 class SVP64Database
:
3721 def __init__(self
, root
, ppcdb
):
3723 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
3724 for (prefix
, _
, names
) in _os
.walk(root
):
3725 prefix
= _pathlib
.Path(prefix
)
3726 for name
in filter(lambda name
: pattern
.match(name
), names
):
3727 path
= (prefix
/ _pathlib
.Path(name
))
3728 with
open(path
, "r", encoding
="UTF-8") as stream
:
3729 db
.update(parse(stream
, SVP64Record
.CSV
))
3730 db
= {record
.name
:record
for record
in db
}
3732 self
.__db
= dict(sorted(db
.items()))
3733 self
.__ppcdb
= ppcdb
3735 return super().__init
__()
3737 def __getitem__(self
, key
):
3738 (_
, record
) = self
.__ppcdb
[key
]
3742 for name
in record
.names
:
3743 record
= self
.__db
.get(name
, None)
3744 if record
is not None:
3751 def __init__(self
, root
):
3752 root
= _pathlib
.Path(root
)
3753 mdwndb
= MarkdownDatabase()
3754 fieldsdb
= FieldsDatabase()
3755 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
3756 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
3760 opcodes
= _collections
.defaultdict(
3761 lambda: _collections
.defaultdict(set))
3763 for (name
, mdwn
) in mdwndb
:
3764 if name
.startswith("sv."):
3766 (section
, ppc
) = ppcdb
[name
]
3769 svp64
= svp64db
[name
]
3770 fields
= fieldsdb
[ppc
.form
]
3771 record
= Record(name
=name
,
3772 section
=section
, ppc
=ppc
, svp64
=svp64
,
3773 mdwn
=mdwn
, fields
=fields
)
3775 names
[record
.name
] = record
3776 opcodes
[section
][record
.PO
].add(record
)
3778 self
.__db
= sorted(db
)
3779 self
.__names
= dict(sorted(names
.items()))
3780 self
.__opcodes
= dict(sorted(opcodes
.items()))
3782 return super().__init
__()
3785 return repr(self
.__db
)
3788 yield from self
.__db
3790 @_functools.lru_cache(maxsize
=None)
3791 def __contains__(self
, key
):
3792 return self
.__getitem
__(key
) is not None
3794 @_functools.lru_cache(maxsize
=None)
3795 def __getitem__(self
, key
):
3796 if isinstance(key
, Instruction
):
3799 sections
= sorted(self
.__opcodes
)
3800 for section
in sections
:
3801 group
= self
.__opcodes
[section
]
3802 for record
in group
[PO
]:
3803 if record
.match(key
=key
):
3808 elif isinstance(key
, str):
3809 return self
.__names
.get(key
)
3811 raise ValueError("instruction or name expected")