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
13 from functools
import cached_property
15 from cached_property
import cached_property
17 from openpower
.decoder
.power_enums
import (
18 Function
as _Function
,
25 CRIn2Sel
as _CRIn2Sel
,
26 CROutSel
as _CROutSel
,
28 LDSTMode
as _LDSTMode
,
33 SVMaskSrc
as _SVMaskSrc
,
38 SVP64RMMode
as _SVP64RMMode
,
39 SVExtraRegType
as _SVExtraRegType
,
40 SVExtraReg
as _SVExtraReg
,
41 SVP64SubVL
as _SVP64SubVL
,
42 SVP64Pred
as _SVP64Pred
,
43 SVP64PredMode
as _SVP64PredMode
,
44 SVP64Width
as _SVP64Width
,
46 from openpower
.decoder
.selectable_int
import (
47 SelectableInt
as _SelectableInt
,
48 selectconcat
as _selectconcat
,
50 from openpower
.decoder
.power_fields
import (
53 DecodeFields
as _DecodeFields
,
55 from openpower
.decoder
.pseudo
.pagereader
import ISA
as _ISA
58 @_functools.total_ordering
59 class Style(_enum
.Enum
):
63 VERBOSE
= _enum
.auto()
65 def __lt__(self
, other
):
66 if not isinstance(other
, self
.__class
__):
68 return (self
.value
< other
.value
)
71 @_functools.total_ordering
72 class Priority(_enum
.Enum
):
78 def _missing_(cls
, value
):
79 if isinstance(value
, str):
84 return super()._missing
_(value
)
86 def __lt__(self
, other
):
87 if not isinstance(other
, self
.__class
__):
90 # NOTE: the order is inversed, LOW < NORMAL < HIGH
91 return (self
.value
> other
.value
)
94 def dataclass(cls
, record
, keymap
=None, typemap
=None):
98 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
100 def transform(key_value
):
101 (key
, value
) = key_value
102 key
= keymap
.get(key
, key
)
103 hook
= typemap
.get(key
, lambda value
: value
)
104 if hook
is bool and value
in ("", "0"):
110 record
= dict(map(transform
, record
.items()))
111 for key
in frozenset(record
.keys()):
112 if record
[key
] == "":
118 @_functools.total_ordering
119 @_dataclasses.dataclass(eq
=True, frozen
=True)
122 def __new__(cls
, value
):
123 if isinstance(value
, str):
124 value
= int(value
, 0)
125 if not isinstance(value
, int):
126 raise ValueError(value
)
128 if value
.bit_length() > 64:
129 raise ValueError(value
)
131 return super().__new
__(cls
, value
)
134 return self
.__repr
__()
137 return f
"{self:0{self.bit_length()}b}"
139 def bit_length(self
):
140 if super().bit_length() > 32:
144 class Value(Integer
):
153 def __lt__(self
, other
):
154 if not isinstance(other
, Opcode
):
155 return NotImplemented
156 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
159 def pattern(value
, mask
, bit_length
):
160 for bit
in range(bit_length
):
161 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
163 elif (value
& (1 << (bit_length
- bit
- 1))):
168 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
170 def match(self
, key
):
171 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
174 @_functools.total_ordering
175 @_dataclasses.dataclass(eq
=True, frozen
=True)
176 class IntegerOpcode(Opcode
):
177 def __init__(self
, value
):
178 if value
.startswith("0b"):
179 mask
= int(("1" * len(value
[2:])), 2)
183 value
= Opcode
.Value(value
)
184 mask
= Opcode
.Mask(mask
)
186 return super().__init
__(value
=value
, mask
=mask
)
189 @_functools.total_ordering
190 @_dataclasses.dataclass(eq
=True, frozen
=True)
191 class PatternOpcode(Opcode
):
192 def __init__(self
, pattern
):
193 if not isinstance(pattern
, str):
194 raise ValueError(pattern
)
196 (value
, mask
) = (0, 0)
197 for symbol
in pattern
:
198 if symbol
not in {"0", "1", "-"}:
199 raise ValueError(pattern
)
200 value |
= (symbol
== "1")
201 mask |
= (symbol
!= "-")
207 value
= Opcode
.Value(value
)
208 mask
= Opcode
.Mask(mask
)
210 return super().__init
__(value
=value
, mask
=mask
)
213 @_dataclasses.dataclass(eq
=True, frozen
=True)
215 class FlagsMeta(type):
230 class Flags(tuple, metaclass
=FlagsMeta
):
231 def __new__(cls
, flags
=frozenset()):
232 flags
= frozenset(flags
)
233 diff
= (flags
- frozenset(cls
))
235 raise ValueError(flags
)
236 return super().__new
__(cls
, sorted(flags
))
240 flags
: Flags
= Flags()
242 function
: _Function
= _Function
.NONE
243 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
244 in1
: _In1Sel
= _In1Sel
.RA
245 in2
: _In2Sel
= _In2Sel
.NONE
246 in3
: _In3Sel
= _In3Sel
.NONE
247 out
: _OutSel
= _OutSel
.NONE
248 cr_in
: _CRInSel
= _CRInSel
.NONE
249 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
250 cr_out
: _CROutSel
= _CROutSel
.NONE
251 cry_in
: _CryIn
= _CryIn
.ZERO
252 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
253 upd
: _LDSTMode
= _LDSTMode
.NONE
254 Rc
: _RCOE
= _RCOE
.NONE
255 form
: _Form
= _Form
.NONE
257 unofficial
: bool = False
261 "internal op": "intop",
265 "ldst len": "ldst_len",
267 "CONDITIONS": "conditions",
270 def __lt__(self
, other
):
271 if not isinstance(other
, self
.__class
__):
272 return NotImplemented
273 lhs
= (self
.opcode
, self
.comment
)
274 rhs
= (other
.opcode
, other
.comment
)
278 def CSV(cls
, record
, opcode_cls
):
279 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
280 typemap
["opcode"] = opcode_cls
282 if record
["CR in"] == "BA_BB":
283 record
["cr_in"] = "BA"
284 record
["cr_in2"] = "BB"
288 for flag
in frozenset(PPCRecord
.Flags
):
289 if bool(record
.pop(flag
, "")):
291 record
["flags"] = PPCRecord
.Flags(flags
)
293 return dataclass(cls
, record
,
294 keymap
=PPCRecord
.__KEYMAP
,
299 return frozenset(self
.comment
.split("=")[-1].split("/"))
302 class PPCMultiRecord(tuple):
303 def __getattr__(self
, attr
):
306 raise AttributeError(attr
)
307 return getattr(self
[0], attr
)
310 @_dataclasses.dataclass(eq
=True, frozen
=True)
312 class ExtraMap(tuple):
314 @_dataclasses.dataclass(eq
=True, frozen
=True)
316 regtype
: _SVExtraRegType
= _SVExtraRegType
.NONE
317 reg
: _SVExtraReg
= _SVExtraReg
.NONE
320 return f
"{self.regtype.value}:{self.reg.name}"
322 def __new__(cls
, value
="0"):
323 if isinstance(value
, str):
324 def transform(value
):
325 (regtype
, reg
) = value
.split(":")
326 regtype
= _SVExtraRegType(regtype
)
327 reg
= _SVExtraReg(reg
)
328 return cls
.Entry(regtype
=regtype
, reg
=reg
)
333 value
= map(transform
, value
.split(";"))
335 return super().__new
__(cls
, value
)
338 return repr(list(self
))
340 def __new__(cls
, value
=tuple()):
344 return super().__new
__(cls
, map(cls
.Extra
, value
))
347 return repr({index
:self
[index
] for index
in range(0, 4)})
350 ptype
: _SVPType
= _SVPType
.NONE
351 etype
: _SVEType
= _SVEType
.NONE
352 msrc
: _SVMaskSrc
= _SVMaskSrc
.NO
# MASK_SRC is active
353 in1
: _In1Sel
= _In1Sel
.NONE
354 in2
: _In2Sel
= _In2Sel
.NONE
355 in3
: _In3Sel
= _In3Sel
.NONE
356 out
: _OutSel
= _OutSel
.NONE
357 out2
: _OutSel
= _OutSel
.NONE
358 cr_in
: _CRInSel
= _CRInSel
.NONE
359 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
360 cr_out
: _CROutSel
= _CROutSel
.NONE
361 extra
: ExtraMap
= ExtraMap()
363 mode
: _SVMode
= _SVMode
.NORMAL
367 "CONDITIONS": "conditions",
376 def CSV(cls
, record
):
377 record
["insn"] = record
["insn"].split("=")[-1]
379 for key
in frozenset({
380 "in1", "in2", "in3", "CR in",
381 "out", "out2", "CR out",
387 if record
["CR in"] == "BA_BB":
388 record
["cr_in"] = "BA"
389 record
["cr_in2"] = "BB"
393 for idx
in range(0, 4):
394 extra
.append(record
.pop(f
"{idx}"))
396 record
["extra"] = cls
.ExtraMap(extra
)
398 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
400 @_functools.lru_cache(maxsize
=None)
401 def extra_idx(self
, key
):
409 if key
not in frozenset({
410 "in1", "in2", "in3", "cr_in", "cr_in2",
411 "out", "out2", "cr_out",
415 sel
= getattr(self
, key
)
416 if sel
is _CRInSel
.BA_BB
:
417 return _SVExtra
.Idx_1_2
418 reg
= _SVExtraReg(sel
)
419 if reg
is _SVExtraReg
.NONE
:
423 _SVExtraRegType
.SRC
: {},
424 _SVExtraRegType
.DST
: {},
426 for index
in range(0, 4):
427 for entry
in self
.extra
[index
]:
428 extra_map
[entry
.regtype
][entry
.reg
] = extra_idx
[index
]
430 for regtype
in (_SVExtraRegType
.SRC
, _SVExtraRegType
.DST
):
431 extra
= extra_map
[regtype
].get(reg
, _SVExtra
.NONE
)
432 if extra
is not _SVExtra
.NONE
:
437 extra_idx_in1
= property(_functools
.partial(extra_idx
, key
="in1"))
438 extra_idx_in2
= property(_functools
.partial(extra_idx
, key
="in2"))
439 extra_idx_in3
= property(_functools
.partial(extra_idx
, key
="in3"))
440 extra_idx_out
= property(_functools
.partial(extra_idx
, key
="out"))
441 extra_idx_out2
= property(_functools
.partial(extra_idx
, key
="out2"))
442 extra_idx_cr_in
= property(_functools
.partial(extra_idx
, key
="cr_in"))
443 extra_idx_cr_in2
= property(_functools
.partial(extra_idx
, key
="cr_in2"))
444 extra_idx_cr_out
= property(_functools
.partial(extra_idx
, key
="cr_out"))
446 @_functools.lru_cache(maxsize
=None)
447 def extra_reg(self
, key
):
448 return _SVExtraReg(getattr(self
, key
))
450 extra_reg_in1
= property(_functools
.partial(extra_reg
, key
="in1"))
451 extra_reg_in2
= property(_functools
.partial(extra_reg
, key
="in2"))
452 extra_reg_in3
= property(_functools
.partial(extra_reg
, key
="in3"))
453 extra_reg_out
= property(_functools
.partial(extra_reg
, key
="out"))
454 extra_reg_out2
= property(_functools
.partial(extra_reg
, key
="out2"))
455 extra_reg_cr_in
= property(_functools
.partial(extra_reg
, key
="cr_in"))
456 extra_reg_cr_in2
= property(_functools
.partial(extra_reg
, key
="cr_in2"))
457 extra_reg_cr_out
= property(_functools
.partial(extra_reg
, key
="cr_out"))
462 for idx
in range(0, 4):
463 for entry
in self
.extra
[idx
]:
464 if entry
.regtype
is _SVExtraRegType
.DST
:
465 if extra
is not None:
466 raise ValueError(self
.svp64
)
470 if _RegType(extra
.reg
) not in (_RegType
.CR_3BIT
, _RegType
.CR_5BIT
):
471 raise ValueError(self
.svp64
)
476 def extra_CR_3bit(self
):
477 return (_RegType(self
.extra_CR
.reg
) is _RegType
.CR_3BIT
)
481 def __init__(self
, value
=(0, 32)):
482 if isinstance(value
, str):
483 (start
, end
) = map(int, value
.split(":"))
486 if start
< 0 or end
< 0 or start
>= end
:
487 raise ValueError(value
)
492 return super().__init
__()
495 return (self
.__end
- self
.__start
+ 1)
498 return f
"[{self.__start}:{self.__end}]"
501 yield from range(self
.start
, (self
.end
+ 1))
503 def __reversed__(self
):
504 return tuple(reversed(tuple(self
)))
515 @_dataclasses.dataclass(eq
=True, frozen
=True)
517 class Mode(_enum
.Enum
):
518 INTEGER
= _enum
.auto()
519 PATTERN
= _enum
.auto()
522 def _missing_(cls
, value
):
523 if isinstance(value
, str):
524 return cls
[value
.upper()]
525 return super()._missing
_(value
)
528 def __new__(cls
, value
=None):
529 if isinstance(value
, str):
530 if value
.upper() == "NONE":
533 value
= int(value
, 0)
537 return super().__new
__(cls
, value
)
543 return (bin(self
) if self
else "None")
549 opcode
: IntegerOpcode
= None
550 priority
: Priority
= Priority
.NORMAL
552 def __lt__(self
, other
):
553 if not isinstance(other
, self
.__class
__):
554 return NotImplemented
555 return (self
.priority
< other
.priority
)
558 def CSV(cls
, record
):
559 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
560 if record
["opcode"] == "NONE":
561 typemap
["opcode"] = lambda _
: None
563 return dataclass(cls
, record
, typemap
=typemap
)
567 def __init__(self
, items
):
568 if isinstance(items
, dict):
569 items
= items
.items()
572 (name
, bitrange
) = item
573 return (name
, tuple(bitrange
.values()))
575 self
.__mapping
= dict(map(transform
, items
))
577 return super().__init
__()
580 return repr(self
.__mapping
)
583 yield from self
.__mapping
.items()
585 def __contains__(self
, key
):
586 return self
.__mapping
.__contains
__(key
)
588 def __getitem__(self
, key
):
589 return self
.__mapping
.get(key
, None)
604 def __init__(self
, insn
, operands
):
606 "b": {"target_addr": TargetAddrOperandLI
},
607 "ba": {"target_addr": TargetAddrOperandLI
},
608 "bl": {"target_addr": TargetAddrOperandLI
},
609 "bla": {"target_addr": TargetAddrOperandLI
},
610 "bc": {"target_addr": TargetAddrOperandBD
},
611 "bca": {"target_addr": TargetAddrOperandBD
},
612 "bcl": {"target_addr": TargetAddrOperandBD
},
613 "bcla": {"target_addr": TargetAddrOperandBD
},
614 "addpcis": {"D": DOperandDX
},
615 "fishmv": {"D": DOperandDX
},
616 "fmvis": {"D": DOperandDX
},
618 # FIXME: these instructions are broken according to the specs.
619 # The operands in the assembly syntax are FRT,FRA,FRC,FRB.
620 # The real assembly order, however, is FRT,FRA,FRB,FRC.
621 # The legacy assembler placed operands in syntax order.
622 "ffmadds": {"FRB": FMAOperandFRB
, "FRC": FMAOperandFRC
},
623 "ffmadds.": {"FRB": FMAOperandFRB
, "FRC": FMAOperandFRC
},
624 "fdmadds": {"FRB": FMAOperandFRB
, "FRC": FMAOperandFRC
},
625 "fdmadds.": {"FRB": FMAOperandFRB
, "FRC": FMAOperandFRC
},
628 "SVi": NonZeroOperand
,
629 "SVd": NonZeroOperand
,
630 "SVxd": NonZeroOperand
,
631 "SVyd": NonZeroOperand
,
632 "SVzd": NonZeroOperand
,
634 "D": SignedImmediateOperand
,
638 "SIM": SignedOperand
,
639 "SVD": SignedOperand
,
640 "SVDS": SignedOperand
,
641 "RSp": GPRPairOperand
,
642 "RTp": GPRPairOperand
,
643 "FRAp": FPRPairOperand
,
644 "FRBp": FPRPairOperand
,
645 "FRSp": FPRPairOperand
,
646 "FRTp": FPRPairOperand
,
648 custom_immediates
= {
654 for operand
in operands
:
658 (name
, value
) = operand
.split("=")
659 mapping
[name
] = (StaticOperand
, {
665 if name
.endswith(")"):
666 name
= name
.replace("(", " ").replace(")", "")
667 (imm_name
, _
, name
) = name
.partition(" ")
671 if imm_name
is not None:
672 imm_cls
= custom_immediates
.get(imm_name
, ImmediateOperand
)
674 if insn
in custom_insns
and name
in custom_insns
[insn
]:
675 cls
= custom_insns
[insn
][name
]
676 elif name
in custom_fields
:
677 cls
= custom_fields
[name
]
678 elif name
in _SVExtraReg
.__members
__:
679 reg
= _SVExtraReg
[name
]
680 if reg
in self
.__class
__.__GPR
_PAIRS
:
682 elif reg
in self
.__class
__.__FPR
_PAIRS
:
685 regtype
= _RegType
[name
]
686 if regtype
is _RegType
.GPR
:
688 elif regtype
is _RegType
.FPR
:
690 elif regtype
is _RegType
.CR_3BIT
:
692 elif regtype
is _RegType
.CR_5BIT
:
695 if imm_name
is not None:
696 mapping
[imm_name
] = (imm_cls
, {"name": imm_name
})
697 mapping
[name
] = (cls
, {"name": name
})
701 for (name
, (cls
, kwargs
)) in mapping
.items():
702 kwargs
= dict(kwargs
)
703 kwargs
["name"] = name
704 if issubclass(cls
, StaticOperand
):
705 static
.append((cls
, kwargs
))
706 elif issubclass(cls
, DynamicOperand
):
707 dynamic
.append((cls
, kwargs
))
709 raise ValueError(name
)
711 self
.__mapping
= mapping
712 self
.__static
= tuple(static
)
713 self
.__dynamic
= tuple(dynamic
)
715 return super().__init
__()
718 for (_
, items
) in self
.__mapping
.items():
719 (cls
, kwargs
) = items
723 return self
.__mapping
.__repr
__()
725 def __contains__(self
, key
):
726 return self
.__mapping
.__contains
__(key
)
728 def __getitem__(self
, key
):
729 return self
.__mapping
.__getitem
__(key
)
737 return self
.__dynamic
740 class Arguments(tuple):
741 def __new__(cls
, record
, arguments
, operands
):
742 operands
= iter(tuple(operands
))
743 arguments
= iter(tuple(arguments
))
748 operand
= next(operands
)
749 except StopIteration:
753 argument
= next(arguments
)
754 except StopIteration:
755 raise ValueError("operands count mismatch")
757 if isinstance(operand
, ImmediateOperand
):
758 argument
= argument
.replace("(", " ").replace(")", "")
759 (imm_argument
, _
, argument
) = argument
.partition(" ")
761 (imm_operand
, operand
) = (operand
, next(operands
))
762 except StopIteration:
763 raise ValueError("operands count mismatch")
764 items
.append((imm_argument
, imm_operand
))
765 items
.append((argument
, operand
))
769 except StopIteration:
772 raise ValueError("operands count mismatch")
774 return super().__new
__(cls
, items
)
778 def __init__(self
, iterable
):
779 self
.__pcode
= tuple(iterable
)
780 return super().__init
__()
783 yield from self
.__pcode
786 return self
.__pcode
.__repr
__()
789 @_dataclasses.dataclass(eq
=True, frozen
=True)
790 class MarkdownRecord
:
795 @_functools.total_ordering
796 @_dataclasses.dataclass(eq
=True, frozen
=True)
803 svp64
: SVP64Record
= None
805 def __lt__(self
, other
):
806 if not isinstance(other
, Record
):
807 return NotImplemented
808 lhs
= (min(self
.opcodes
), self
.name
)
809 rhs
= (min(other
.opcodes
), other
.name
)
814 return (self
.static_operands
+ self
.dynamic_operands
)
817 def static_operands(self
):
819 operands
.append(POStaticOperand(record
=self
, value
=self
.PO
))
821 operands
.append(XOStaticOperand(
823 value
=ppc
.opcode
.value
,
824 span
=self
.section
.bitsel
,
826 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
827 operands
.append(cls(record
=self
, **kwargs
))
828 return tuple(operands
)
831 def dynamic_operands(self
):
833 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
834 operands
.append(cls(record
=self
, **kwargs
))
835 return tuple(operands
)
840 return int("".join(str(int(mapping
[bit
])) for bit
in sorted(mapping
)), 2)
842 def PO_XO(value
, mask
, opcode
, bits
):
845 for (src
, dst
) in enumerate(reversed(bits
)):
846 value
[dst
] = ((opcode
.value
& (1 << src
)) != 0)
847 mask
[dst
] = ((opcode
.mask
& (1 << src
)) != 0)
850 def PO(value
, mask
, opcode
, bits
):
851 return PO_XO(value
=value
, mask
=mask
, opcode
=opcode
, bits
=bits
)
853 def XO(value
, mask
, opcode
, bits
):
854 (value
, mask
) = PO_XO(value
=value
, mask
=mask
, opcode
=opcode
, bits
=bits
)
855 for (op_cls
, op_kwargs
) in self
.mdwn
.operands
.static
:
856 operand
= op_cls(record
=self
, **op_kwargs
)
857 for (src
, dst
) in enumerate(reversed(operand
.span
)):
858 value
[dst
] = ((operand
.value
& (1 << src
)) != 0)
863 value
= {bit
:False for bit
in range(32)}
864 mask
= {bit
:False for bit
in range(32)}
865 if self
.section
.opcode
is not None:
866 (value
, mask
) = PO(value
=value
, mask
=mask
,
867 opcode
=self
.section
.opcode
, bits
=range(0, 6))
869 pairs
.append(XO(value
=value
, mask
=mask
,
870 opcode
=ppc
.opcode
, bits
=self
.section
.bitsel
))
873 for (value
, mask
) in pairs
:
874 value
= Opcode
.Value(binary(value
))
875 mask
= Opcode
.Mask(binary(mask
))
876 result
.append(Opcode(value
=value
, mask
=mask
))
882 opcode
= self
.section
.opcode
884 opcode
= self
.ppc
[0].opcode
885 if isinstance(opcode
, PatternOpcode
):
886 value
= int(opcode
.value
)
887 bits
= opcode
.value
.bit_length()
888 return int(_SelectableInt(value
=value
, bits
=bits
)[0:6])
890 return int(opcode
.value
)
894 return tuple(ppc
.opcode
for ppc
in self
.ppc
)
896 def match(self
, key
):
897 for opcode
in self
.opcodes
:
898 if opcode
.match(key
):
905 return self
.svp64
.mode
925 if self
.svp64
is None:
931 return self
.ppc
.cr_in
935 return self
.ppc
.cr_in2
939 return self
.ppc
.cr_out
941 ptype
= property(lambda self
: self
.svp64
.ptype
)
942 etype
= property(lambda self
: self
.svp64
.etype
)
944 def extra_idx(self
, key
):
945 return self
.svp64
.extra_idx(key
)
947 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
948 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
949 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
950 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
951 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
952 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
953 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
954 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
956 def __contains__(self
, key
):
957 return self
.mdwn
.operands
.__contains
__(key
)
959 def __getitem__(self
, key
):
960 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
961 return cls(record
=self
, **kwargs
)
967 return self
["Rc"].value
971 def __init__(self
, record
, name
):
972 self
.__record
= record
976 yield ("record", self
.record
)
977 yield ("name", self
.__name
)
980 return f
"{self.__class__.__name__}({self.name})"
992 return self
.record
.fields
[self
.name
]
994 def assemble(self
, insn
):
995 raise NotImplementedError()
997 def disassemble(self
, insn
,
998 style
=Style
.NORMAL
, indent
=""):
999 raise NotImplementedError()
1002 class DynamicOperand(Operand
):
1003 def assemble(self
, insn
, value
):
1005 if isinstance(value
, str):
1006 value
= int(value
, 0)
1008 raise ValueError("signed operands not allowed")
1011 def disassemble(self
, insn
,
1012 style
=Style
.NORMAL
, indent
=""):
1016 if style
>= Style
.VERBOSE
:
1017 span
= map(str, span
)
1018 yield f
"{indent}{self.name}"
1019 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1020 yield f
"{indent}{indent}{', '.join(span)}"
1022 yield str(int(value
))
1025 class SignedOperand(DynamicOperand
):
1026 def assemble(self
, insn
, value
):
1027 if isinstance(value
, str):
1028 value
= int(value
, 0)
1029 return super().assemble(value
=value
, insn
=insn
)
1031 def assemble(self
, insn
, value
):
1033 if isinstance(value
, str):
1034 value
= int(value
, 0)
1037 def disassemble(self
, insn
,
1038 style
=Style
.NORMAL
, indent
=""):
1040 value
= insn
[span
].to_signed_int()
1041 sign
= "-" if (value
< 0) else ""
1044 if style
>= Style
.VERBOSE
:
1045 span
= map(str, span
)
1046 yield f
"{indent}{self.name}"
1047 yield f
"{indent}{indent}{sign}{value}"
1048 yield f
"{indent}{indent}{', '.join(span)}"
1050 yield f
"{sign}{value}"
1053 class StaticOperand(Operand
):
1054 def __init__(self
, record
, name
, value
):
1055 self
.__value
= value
1056 return super().__init
__(record
=record
, name
=name
)
1059 yield ("value", self
.__value
)
1060 yield from super().__iter
__()
1063 return f
"{self.__class__.__name__}({self.name}, value={self.value})"
1069 def assemble(self
, insn
):
1070 insn
[self
.span
] = self
.value
1072 def disassemble(self
, insn
,
1073 style
=Style
.NORMAL
, indent
=""):
1077 if style
>= Style
.VERBOSE
:
1078 span
= map(str, span
)
1079 yield f
"{indent}{self.name}"
1080 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1081 yield f
"{indent}{indent}{', '.join(span)}"
1083 yield str(int(value
))
1086 class SpanStaticOperand(StaticOperand
):
1087 def __init__(self
, record
, name
, value
, span
):
1088 self
.__span
= tuple(span
)
1089 return super().__init
__(record
=record
, name
=name
, value
=value
)
1092 yield ("span", self
.__span
)
1093 yield from super().__iter
__()
1100 class POStaticOperand(SpanStaticOperand
):
1101 def __init__(self
, record
, value
):
1102 return super().__init
__(record
=record
, name
="PO", value
=value
, span
=range(0, 6))
1105 for (key
, value
) in super().__iter
__():
1106 if key
not in {"name", "span"}:
1110 class XOStaticOperand(SpanStaticOperand
):
1111 def __init__(self
, record
, value
, span
):
1112 if record
.name
== "ffadds":
1115 bits
= record
.section
.bitsel
1116 value
= _SelectableInt(value
=value
, bits
=len(bits
))
1117 span
= dict(zip(bits
, range(len(bits
))))
1118 span_rev
= {value
:key
for (key
, value
) in span
.items()}
1120 # This part is tricky: we cannot use record.operands,
1121 # as this code is called by record.static_operands method.
1122 for (cls
, kwargs
) in record
.mdwn
.operands
:
1123 operand
= cls(record
=record
, **kwargs
)
1124 for idx
in operand
.span
:
1125 rev
= span
.pop(idx
, None)
1127 span_rev
.pop(rev
, None)
1129 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1130 span
= tuple(span
.keys())
1132 return super().__init
__(record
=record
, name
="XO", value
=value
, span
=span
)
1135 for (key
, value
) in super().__iter
__():
1136 if key
not in {"name"}:
1140 class ImmediateOperand(DynamicOperand
):
1144 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1148 class NonZeroOperand(DynamicOperand
):
1149 def assemble(self
, insn
, value
):
1150 if isinstance(value
, str):
1151 value
= int(value
, 0)
1152 if not isinstance(value
, int):
1153 raise ValueError("non-integer operand")
1155 return super().assemble(value
=value
, insn
=insn
)
1157 def disassemble(self
, insn
,
1158 style
=Style
.NORMAL
, indent
=""):
1162 if style
>= Style
.VERBOSE
:
1163 span
= map(str, span
)
1164 yield f
"{indent}{self.name}"
1165 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1166 yield f
"{indent}{indent}{', '.join(span)}"
1168 yield str(int(value
) + 1)
1171 class ExtendableOperand(DynamicOperand
):
1172 def sv_spec_enter(self
, value
, span
):
1173 return (value
, span
)
1175 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1176 return (value
, span
)
1178 def spec(self
, insn
):
1182 span
= tuple(map(str, span
))
1184 if isinstance(insn
, SVP64Instruction
):
1185 (origin_value
, origin_span
) = (value
, span
)
1186 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1188 extra_idx
= self
.extra_idx
1189 if extra_idx
is _SVExtra
.NONE
:
1190 return (vector
, value
, span
)
1192 if self
.record
.etype
is _SVEType
.EXTRA3
:
1193 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1194 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1195 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1197 raise ValueError(self
.record
.etype
)
1200 vector
= bool(spec
[0])
1201 spec_span
= spec
.__class
__
1202 if self
.record
.etype
is _SVEType
.EXTRA3
:
1203 spec_span
= tuple(map(str, spec_span
[1, 2]))
1205 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1206 spec_span
= tuple(map(str, spec_span
[1,]))
1207 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1210 spec_span
= (spec_span
+ ("{0}",))
1212 spec_span
= (("{0}",) + spec_span
)
1214 raise ValueError(self
.record
.etype
)
1216 vector_shift
= (2 + (5 - value
.bits
))
1217 scalar_shift
= value
.bits
1218 spec_shift
= (5 - value
.bits
)
1220 bits
= (len(span
) + len(spec_span
))
1221 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1222 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1224 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1225 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1227 value
= ((spec
<< scalar_shift
) | value
)
1228 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1230 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1231 origin_value
=origin_value
, origin_span
=origin_span
)
1233 return (vector
, value
, span
)
1236 def extra_reg(self
):
1237 return _SVExtraReg(self
.name
)
1240 def extra_idx(self
):
1242 _SVExtraReg
.RSp
: _SVExtraReg
.RS
,
1243 _SVExtraReg
.RTp
: _SVExtraReg
.RT
,
1244 _SVExtraReg
.FRAp
: _SVExtraReg
.FRA
,
1245 _SVExtraReg
.FRBp
: _SVExtraReg
.FRB
,
1246 _SVExtraReg
.FRSp
: _SVExtraReg
.FRS
,
1247 _SVExtraReg
.FRTp
: _SVExtraReg
.FRT
,
1250 for key
in frozenset({
1251 "in1", "in2", "in3", "cr_in", "cr_in2",
1252 "out", "out2", "cr_out",
1254 extra_reg
= self
.record
.svp64
.extra_reg(key
=key
)
1255 if pairs
.get(extra_reg
, extra_reg
) is pairs
.get(self
.extra_reg
, self
.extra_reg
):
1256 return self
.record
.extra_idx(key
=key
)
1258 return _SVExtra
.NONE
1260 def remap(self
, value
, vector
):
1261 raise NotImplementedError()
1263 def assemble(self
, value
, insn
, prefix
):
1266 if isinstance(value
, str):
1267 value
= value
.lower()
1268 if value
.startswith("%"):
1270 if value
.startswith("*"):
1271 if not isinstance(insn
, SVP64Instruction
):
1272 raise ValueError(value
)
1275 if value
.startswith(prefix
):
1276 value
= value
[len(prefix
):]
1277 value
= int(value
, 0)
1279 if isinstance(insn
, SVP64Instruction
):
1280 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1282 extra_idx
= self
.extra_idx
1283 if extra_idx
is _SVExtra
.NONE
:
1284 raise ValueError(self
.record
)
1286 if self
.record
.etype
is _SVEType
.EXTRA3
:
1287 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1288 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1289 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1291 raise ValueError(self
.record
.etype
)
1293 return super().assemble(value
=value
, insn
=insn
)
1295 def disassemble(self
, insn
,
1296 style
=Style
.NORMAL
, prefix
="", indent
=""):
1297 (vector
, value
, span
) = self
.spec(insn
=insn
)
1299 if style
>= Style
.VERBOSE
:
1300 mode
= "vector" if vector
else "scalar"
1301 yield f
"{indent}{self.name} ({mode})"
1302 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1303 yield f
"{indent}{indent}{', '.join(span)}"
1304 if isinstance(insn
, SVP64Instruction
):
1305 extra_idx
= self
.extra_idx
1306 if self
.record
.etype
is _SVEType
.NONE
:
1307 yield f
"{indent}{indent}extra[none]"
1309 etype
= repr(self
.record
.etype
).lower()
1310 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1312 vector
= "*" if vector
else ""
1313 yield f
"{vector}{prefix}{int(value)}"
1316 class SimpleRegisterOperand(ExtendableOperand
):
1317 def remap(self
, value
, vector
):
1319 extra
= (value
& 0b11)
1320 value
= (value
>> 2)
1322 extra
= (value
>> 5)
1323 value
= (value
& 0b11111)
1325 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1326 # (and shrink to a single bit if ok)
1327 if self
.record
.etype
is _SVEType
.EXTRA2
:
1329 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1330 assert (extra
& 0b01) == 0, \
1331 ("vector field %s cannot fit into EXTRA2" % value
)
1332 extra
= (0b10 |
(extra
>> 1))
1334 # range is r0-r63 in increments of 1
1335 assert (extra
>> 1) == 0, \
1336 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1338 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1340 # EXTRA3 vector bit needs marking
1343 raise ValueError(self
.record
.etype
)
1345 return (value
, extra
)
1348 class GPROperand(SimpleRegisterOperand
):
1349 def assemble(self
, insn
, value
):
1350 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1352 def disassemble(self
, insn
,
1353 style
=Style
.NORMAL
, indent
=""):
1354 prefix
= "" if (style
<= Style
.SHORT
) else "r"
1355 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1356 style
=style
, indent
=indent
)
1359 class GPRPairOperand(GPROperand
):
1363 class FPROperand(SimpleRegisterOperand
):
1364 def assemble(self
, insn
, value
):
1365 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1367 def disassemble(self
, insn
,
1368 style
=Style
.NORMAL
, indent
=""):
1369 prefix
= "" if (style
<= Style
.SHORT
) else "f"
1370 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1371 style
=style
, indent
=indent
)
1374 class RedirectedOperand(DynamicOperand
):
1375 def __init__(self
, record
, name
, target
):
1376 self
.__target
= target
1377 return super().__init
__(record
=record
, name
=name
)
1381 print(f
"{self.record.name}: {self.name} => {self.__target}", file=_sys
.stderr
)
1382 return self
.record
.fields
[self
.__target
]
1385 class FMAOperandFRB(RedirectedOperand
, FPROperand
):
1386 def __init__(self
, record
, name
):
1387 return super().__init
__(record
=record
, name
=name
, target
="FRC")
1390 class FMAOperandFRC(RedirectedOperand
, FPROperand
):
1391 def __init__(self
, record
, name
):
1392 return super().__init
__(record
=record
, name
=name
, target
="FRB")
1395 class FPRPairOperand(FPROperand
):
1399 class ConditionRegisterFieldOperand(ExtendableOperand
):
1400 def pattern(name_pattern
):
1401 (name
, pattern
) = name_pattern
1402 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1411 CR
= r
"(?:CR|cr)([0-9]+)"
1413 BIT
= rf
"({'|'.join(CONDS.keys())})"
1414 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1415 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1416 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1417 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1418 XCR
= fr
"{CR}\.{BIT}"
1419 PATTERNS
= tuple(map(pattern
, (
1424 ("BIT+CR", (LBIT
+ CR
)),
1425 ("CR+BIT", (CR
+ RBIT
)),
1426 ("BIT+CR*N", (LBIT
+ CRN
)),
1427 ("CR*N+BIT", (CRN
+ RBIT
)),
1428 ("BIT+N*CR", (LBIT
+ NCR
)),
1429 ("N*CR+BIT", (NCR
+ RBIT
)),
1432 def remap(self
, value
, vector
, regtype
):
1433 if regtype
is _RegType
.CR_5BIT
:
1434 subvalue
= (value
& 0b11)
1438 extra
= (value
& 0b1111)
1441 extra
= (value
>> 3)
1444 if self
.record
.etype
is _SVEType
.EXTRA2
:
1446 assert (extra
& 0b111) == 0, \
1447 "vector CR cannot fit into EXTRA2"
1448 extra
= (0b10 |
(extra
>> 3))
1450 assert (extra
>> 1) == 0, \
1451 "scalar CR cannot fit into EXTRA2"
1453 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1455 assert (extra
& 0b11) == 0, \
1456 "vector CR cannot fit into EXTRA3"
1457 extra
= (0b100 |
(extra
>> 2))
1459 assert (extra
>> 2) == 0, \
1460 "scalar CR cannot fit into EXTRA3"
1463 if regtype
is _RegType
.CR_5BIT
:
1464 value
= ((value
<< 2) | subvalue
)
1466 return (value
, extra
)
1468 def assemble(self
, insn
, value
):
1469 if isinstance(value
, str):
1472 if value
.startswith("*"):
1473 if not isinstance(insn
, SVP64Instruction
):
1474 raise ValueError(value
)
1478 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1479 match
= pattern
.match(value
)
1480 if match
is not None:
1481 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1482 values
= match
.groups()
1483 match
= dict(zip(keys
, values
))
1484 CR
= int(match
["CR"])
1488 N
= int(match
.get("N", "1"))
1489 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1490 value
= ((CR
* N
) + BIT
)
1497 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1499 def disassemble(self
, insn
,
1500 style
=Style
.NORMAL
, prefix
="", indent
=""):
1501 (vector
, value
, span
) = self
.spec(insn
=insn
)
1503 if style
>= Style
.VERBOSE
:
1504 mode
= "vector" if vector
else "scalar"
1505 yield f
"{indent}{self.name} ({mode})"
1506 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1507 yield f
"{indent}{indent}{', '.join(span)}"
1508 if isinstance(insn
, SVP64Instruction
):
1509 extra_idx
= self
.extra_idx
1510 if self
.record
.etype
is _SVEType
.NONE
:
1511 yield f
"{indent}{indent}extra[none]"
1513 etype
= repr(self
.record
.etype
).lower()
1514 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1516 vector
= "*" if vector
else ""
1517 CR
= int(value
>> 2)
1519 cond
= ("lt", "gt", "eq", "so")[CC
]
1520 if style
>= Style
.NORMAL
:
1522 if isinstance(insn
, SVP64Instruction
):
1523 yield f
"{vector}cr{CR}.{cond}"
1525 yield f
"4*cr{CR}+{cond}"
1529 yield f
"{vector}{prefix}{int(value)}"
1532 class CR3Operand(ConditionRegisterFieldOperand
):
1533 def remap(self
, value
, vector
):
1534 return super().remap(value
=value
, vector
=vector
,
1535 regtype
=_RegType
.CR_3BIT
)
1538 class CR5Operand(ConditionRegisterFieldOperand
):
1539 def remap(self
, value
, vector
):
1540 return super().remap(value
=value
, vector
=vector
,
1541 regtype
=_RegType
.CR_5BIT
)
1543 def sv_spec_enter(self
, value
, span
):
1544 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1545 return (value
, span
)
1547 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1548 value
= _selectconcat(value
, origin_value
[3:5])
1550 return (value
, span
)
1553 class EXTSOperand(SignedOperand
):
1554 field
: str # real name to report
1555 nz
: int = 0 # number of zeros
1556 fmt
: str = "d" # integer formatter
1558 def __init__(self
, record
, name
, field
, nz
=0, fmt
="d"):
1559 self
.__field
= field
1562 return super().__init
__(record
=record
, name
=name
)
1578 return self
.record
.fields
[self
.field
]
1580 def assemble(self
, insn
, value
):
1582 if isinstance(value
, str):
1583 value
= int(value
, 0)
1584 insn
[span
] = (value
>> self
.nz
)
1586 def disassemble(self
, insn
,
1587 style
=Style
.NORMAL
, indent
=""):
1589 value
= insn
[span
].to_signed_int()
1590 sign
= "-" if (value
< 0) else ""
1591 value
= (abs(value
) << self
.nz
)
1593 if style
>= Style
.VERBOSE
:
1594 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1595 zeros
= ("0" * self
.nz
)
1596 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1597 yield f
"{indent * 1}{hint}"
1598 yield f
"{indent * 2}{self.field}"
1599 yield f
"{indent * 3}{sign}{value:{self.fmt}}"
1600 yield f
"{indent * 3}{', '.join(span)}"
1602 yield f
"{sign}{value:{self.fmt}}"
1605 class TargetAddrOperand(EXTSOperand
):
1606 def __init__(self
, record
, name
, field
):
1607 return super().__init
__(record
=record
, name
=name
, field
=field
, nz
=2, fmt
="#x")
1610 class TargetAddrOperandLI(TargetAddrOperand
):
1611 def __init__(self
, record
, name
):
1612 return super().__init
__(record
=record
, name
=name
, field
="LI")
1615 class TargetAddrOperandBD(TargetAddrOperand
):
1616 def __init__(self
, record
, name
):
1617 return super().__init
__(record
=record
, name
=name
, field
="BD")
1620 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1621 def __init__(self
, record
, name
):
1622 return super().__init
__(record
=record
, name
=name
, field
="DS", nz
=2)
1625 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1626 def __init__(self
, record
, name
):
1627 return super().__init
__(record
=record
, name
=name
, field
="DQ", nz
=4)
1630 class DOperandDX(SignedOperand
):
1633 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1634 operands
= map(cls
, ("d0", "d1", "d2"))
1635 spans
= map(lambda operand
: operand
.span
, operands
)
1636 return sum(spans
, tuple())
1638 def disassemble(self
, insn
,
1639 style
=Style
.NORMAL
, indent
=""):
1641 value
= insn
[span
].to_signed_int()
1642 sign
= "-" if (value
< 0) else ""
1645 if style
>= Style
.VERBOSE
:
1652 for (subname
, subspan
) in mapping
.items():
1653 operand
= DynamicOperand(name
=subname
)
1655 span
= map(str, span
)
1656 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1657 yield f
"{indent}{indent}{indent}{sign}{value}"
1658 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1660 yield f
"{sign}{value}"
1663 class Instruction(_Mapping
):
1665 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1666 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1667 raise ValueError(bits
)
1669 if isinstance(value
, bytes
):
1670 if ((len(value
) * 8) != bits
):
1671 raise ValueError(f
"bit length mismatch")
1672 value
= int.from_bytes(value
, byteorder
=byteorder
)
1674 if isinstance(value
, int):
1675 value
= _SelectableInt(value
=value
, bits
=bits
)
1676 elif isinstance(value
, Instruction
):
1677 value
= value
.storage
1679 if not isinstance(value
, _SelectableInt
):
1680 raise ValueError(value
)
1683 if len(value
) != bits
:
1684 raise ValueError(value
)
1686 value
= _SelectableInt(value
=value
, bits
=bits
)
1688 return cls(storage
=value
)
1691 return hash(int(self
))
1693 def __getitem__(self
, key
):
1694 return self
.storage
.__getitem
__(key
)
1696 def __setitem__(self
, key
, value
):
1697 return self
.storage
.__setitem
__(key
, value
)
1699 def bytes(self
, byteorder
="little"):
1700 nr_bytes
= (len(self
.__class
__) // 8)
1701 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1704 def record(cls
, db
, entry
):
1707 raise KeyError(entry
)
1711 def operands(cls
, record
):
1712 yield from record
.operands
1715 def static_operands(cls
, record
):
1716 return filter(lambda operand
: isinstance(operand
, StaticOperand
),
1717 cls
.operands(record
=record
))
1720 def dynamic_operands(cls
, record
):
1721 return filter(lambda operand
: isinstance(operand
, DynamicOperand
),
1722 cls
.operands(record
=record
))
1724 def spec(self
, record
, prefix
):
1725 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1726 self
.spec_dynamic_operands(record
=record
)))
1728 static_operands
= []
1729 for (name
, value
) in self
.spec_static_operands(record
=record
):
1730 static_operands
.append(f
"{name}={value}")
1733 if dynamic_operands
:
1735 operands
+= ",".join(dynamic_operands
)
1738 operands
+= " ".join(static_operands
)
1740 return f
"{prefix}{record.name}{operands}"
1742 def spec_static_operands(self
, record
):
1743 for operand
in self
.static_operands(record
=record
):
1744 if not isinstance(operand
, (POStaticOperand
, XOStaticOperand
)):
1745 yield (operand
.name
, operand
.value
)
1747 def spec_dynamic_operands(self
, record
, style
=Style
.NORMAL
):
1751 for operand
in self
.dynamic_operands(record
=record
):
1753 value
= " ".join(operand
.disassemble(insn
=self
,
1754 style
=min(style
, Style
.NORMAL
)))
1756 name
= f
"{imm_name}({name})"
1757 value
= f
"{imm_value}({value})"
1759 if isinstance(operand
, ImmediateOperand
):
1767 def assemble(cls
, record
, arguments
=None):
1768 if arguments
is None:
1771 insn
= cls
.integer(value
=0)
1773 for operand
in cls
.static_operands(record
=record
):
1774 operand
.assemble(insn
=insn
)
1776 arguments
= Arguments(record
=record
,
1777 arguments
=arguments
, operands
=cls
.dynamic_operands(record
=record
))
1778 for (value
, operand
) in arguments
:
1779 operand
.assemble(insn
=insn
, value
=value
)
1783 def disassemble(self
, record
,
1785 style
=Style
.NORMAL
):
1786 raise NotImplementedError()
1789 class WordInstruction(Instruction
):
1790 _
: _Field
= range(0, 32)
1791 PO
: _Field
= range(0, 6)
1794 def integer(cls
, value
, byteorder
="little"):
1795 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1800 for idx
in range(32):
1801 bit
= int(self
[idx
])
1803 return "".join(map(str, bits
))
1805 def disassemble(self
, record
,
1807 style
=Style
.NORMAL
):
1808 if style
<= Style
.SHORT
:
1811 blob
= self
.bytes(byteorder
=byteorder
)
1812 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1816 yield f
"{blob}.long 0x{int(self):08x}"
1820 if style
is Style
.LEGACY
:
1822 for operand
in self
.dynamic_operands(record
=record
):
1823 if isinstance(operand
, (GPRPairOperand
, FPRPairOperand
)):
1826 if style
is Style
.LEGACY
and (paired
or record
.ppc
.unofficial
):
1827 yield f
"{blob}.long 0x{int(self):08x}"
1829 operands
= tuple(map(_operator
.itemgetter(1),
1830 self
.spec_dynamic_operands(record
=record
, style
=style
)))
1832 operands
= ",".join(operands
)
1833 yield f
"{blob}{record.name} {operands}"
1835 yield f
"{blob}{record.name}"
1837 if style
>= Style
.VERBOSE
:
1839 binary
= self
.binary
1840 spec
= self
.spec(record
=record
, prefix
="")
1841 yield f
"{indent}spec"
1842 yield f
"{indent}{indent}{spec}"
1843 yield f
"{indent}pcode"
1844 for stmt
in record
.mdwn
.pcode
:
1845 yield f
"{indent}{indent}{stmt}"
1846 yield f
"{indent}binary"
1847 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1848 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1849 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1850 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1851 yield f
"{indent}opcodes"
1852 for opcode
in record
.opcodes
:
1853 yield f
"{indent}{indent}{opcode!r}"
1854 for operand
in self
.operands(record
=record
):
1855 yield from operand
.disassemble(insn
=self
,
1856 style
=style
, indent
=indent
)
1860 class PrefixedInstruction(Instruction
):
1861 class Prefix(WordInstruction
.remap(range(0, 32))):
1864 class Suffix(WordInstruction
.remap(range(32, 64))):
1867 _
: _Field
= range(64)
1873 def integer(cls
, value
, byteorder
="little"):
1874 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
1877 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
1878 def transform(value
):
1879 return WordInstruction
.integer(value
=value
,
1880 byteorder
=byteorder
)[0:32]
1882 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
1883 value
= _selectconcat(prefix
, suffix
)
1885 return super().integer(bits
=64, value
=value
)
1888 class Mode(_Mapping
):
1889 _
: _Field
= range(0, 5)
1890 sel
: _Field
= (0, 1)
1893 class Extra(_Mapping
):
1894 _
: _Field
= range(0, 9)
1897 class Extra2(Extra
):
1898 idx0
: _Field
= range(0, 2)
1899 idx1
: _Field
= range(2, 4)
1900 idx2
: _Field
= range(4, 6)
1901 idx3
: _Field
= range(6, 8)
1903 def __getitem__(self
, key
):
1909 _SVExtra
.Idx0
: self
.idx0
,
1910 _SVExtra
.Idx1
: self
.idx1
,
1911 _SVExtra
.Idx2
: self
.idx2
,
1912 _SVExtra
.Idx3
: self
.idx3
,
1915 def __setitem__(self
, key
, value
):
1916 self
[key
].assign(value
)
1919 class Extra3(Extra
):
1920 idx0
: _Field
= range(0, 3)
1921 idx1
: _Field
= range(3, 6)
1922 idx2
: _Field
= range(6, 9)
1924 def __getitem__(self
, key
):
1929 _SVExtra
.Idx0
: self
.idx0
,
1930 _SVExtra
.Idx1
: self
.idx1
,
1931 _SVExtra
.Idx2
: self
.idx2
,
1934 def __setitem__(self
, key
, value
):
1935 self
[key
].assign(value
)
1938 class BaseRM(_Mapping
):
1939 _
: _Field
= range(24)
1940 mmode
: _Field
= (0,)
1941 mask
: _Field
= range(1, 4)
1942 elwidth
: _Field
= range(4, 6)
1943 ewsrc
: _Field
= range(6, 8)
1944 subvl
: _Field
= range(8, 10)
1945 mode
: Mode
.remap(range(19, 24))
1946 smask
: _Field
= range(16, 19)
1947 extra
: Extra
.remap(range(10, 19))
1948 extra2
: Extra2
.remap(range(10, 19))
1949 extra3
: Extra3
.remap(range(10, 19))
1951 def specifiers(self
, record
):
1952 subvl
= int(self
.subvl
)
1960 def disassemble(self
, style
=Style
.NORMAL
):
1961 if style
>= Style
.VERBOSE
:
1963 for (name
, span
) in self
.traverse(path
="RM"):
1964 value
= self
.storage
[span
]
1966 yield f
"{indent}{int(value):0{value.bits}b}"
1967 yield f
"{indent}{', '.join(map(str, span))}"
1970 class FFPRRc1BaseRM(BaseRM
):
1971 def specifiers(self
, record
, mode
):
1972 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
1973 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
1974 mask
= int(_selectconcat(CR
, inv
))
1975 predicate
= PredicateBaseRM
.predicate(True, mask
)
1976 yield f
"{mode}={predicate}"
1978 yield from super().specifiers(record
=record
)
1981 class FFPRRc0BaseRM(BaseRM
):
1982 def specifiers(self
, record
, mode
):
1984 inv
= "~" if self
.inv
else ""
1985 yield f
"{mode}={inv}RC1"
1987 yield from super().specifiers(record
=record
)
1990 class SatBaseRM(BaseRM
):
1991 def specifiers(self
, record
):
1997 yield from super().specifiers(record
=record
)
2000 class ZZBaseRM(BaseRM
):
2001 def specifiers(self
, record
):
2005 yield from super().specifiers(record
=record
)
2008 class ZZCombinedBaseRM(BaseRM
):
2009 def specifiers(self
, record
):
2010 if self
.sz
and self
.dz
:
2017 yield from super().specifiers(record
=record
)
2020 class DZBaseRM(BaseRM
):
2021 def specifiers(self
, record
):
2025 yield from super().specifiers(record
=record
)
2028 class SZBaseRM(BaseRM
):
2029 def specifiers(self
, record
):
2033 yield from super().specifiers(record
=record
)
2036 class MRBaseRM(BaseRM
):
2037 def specifiers(self
, record
):
2043 yield from super().specifiers(record
=record
)
2046 class ElsBaseRM(BaseRM
):
2047 def specifiers(self
, record
):
2051 yield from super().specifiers(record
=record
)
2054 class WidthBaseRM(BaseRM
):
2056 def width(FP
, width
):
2065 width
= ("fp" + width
)
2068 def specifiers(self
, record
):
2069 # elwidths: use "w=" if same otherwise dw/sw
2070 # FIXME this should consider FP instructions
2072 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
2073 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2082 yield from super().specifiers(record
=record
)
2085 class PredicateBaseRM(BaseRM
):
2087 def predicate(CR
, mask
):
2090 (False, 0b001): "1<<r3",
2091 (False, 0b010): "r3",
2092 (False, 0b011): "~r3",
2093 (False, 0b100): "r10",
2094 (False, 0b101): "~r10",
2095 (False, 0b110): "r30",
2096 (False, 0b111): "~r30",
2098 (True, 0b000): "lt",
2099 (True, 0b001): "ge",
2100 (True, 0b010): "gt",
2101 (True, 0b011): "le",
2102 (True, 0b100): "eq",
2103 (True, 0b101): "ne",
2104 (True, 0b110): "so",
2105 (True, 0b111): "ns",
2108 def specifiers(self
, record
):
2109 # predication - single and twin
2110 # use "m=" if same otherwise sm/dm
2111 CR
= (int(self
.mmode
) == 1)
2112 mask
= int(self
.mask
)
2113 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
2114 if record
.svp64
.ptype
is _SVPType
.P2
:
2115 smask
= int(self
.smask
)
2116 sm
= PredicateBaseRM
.predicate(CR
, smask
)
2125 yield from super().specifiers(record
=record
)
2128 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
2132 class SEABaseRM(BaseRM
):
2133 def specifiers(self
, record
):
2137 yield from super().specifiers(record
=record
)
2140 class VLiBaseRM(BaseRM
):
2141 def specifiers(self
, record
):
2145 yield from super().specifiers(record
=record
)
2148 class NormalBaseRM(PredicateWidthBaseRM
):
2151 https://libre-soc.org/openpower/sv/normal/
2156 class NormalSimpleRM(ZZCombinedBaseRM
, NormalBaseRM
):
2157 """normal: simple mode"""
2161 def specifiers(self
, record
):
2162 yield from super().specifiers(record
=record
)
2165 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
2166 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
2170 class NormalFFRc1RM(FFPRRc1BaseRM
, NormalBaseRM
):
2171 """normal: Rc=1: ffirst CR sel"""
2173 CR
: BaseRM
.mode
[3, 4]
2175 def specifiers(self
, record
):
2176 yield from super().specifiers(record
=record
, mode
="ff")
2179 class NormalFFRc0RM(FFPRRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
2180 """normal: Rc=0: ffirst z/nonz"""
2185 def specifiers(self
, record
):
2186 yield from super().specifiers(record
=record
, mode
="ff")
2189 class NormalSatRM(SatBaseRM
, ZZCombinedBaseRM
, NormalBaseRM
):
2190 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2196 class NormalPRRc1RM(FFPRRc1BaseRM
, NormalBaseRM
):
2197 """normal: Rc=1: pred-result CR sel"""
2199 CR
: BaseRM
.mode
[3, 4]
2201 def specifiers(self
, record
):
2202 yield from super().specifiers(record
=record
, mode
="pr")
2205 class NormalPRRc0RM(FFPRRc0BaseRM
, ZZBaseRM
, NormalBaseRM
):
2206 """normal: Rc=0: pred-result z/nonz"""
2213 def specifiers(self
, record
):
2214 yield from super().specifiers(record
=record
, mode
="pr")
2217 class NormalRM(NormalBaseRM
):
2218 simple
: NormalSimpleRM
2220 ffrc1
: NormalFFRc1RM
2221 ffrc0
: NormalFFRc0RM
2223 prrc1
: NormalPRRc1RM
2224 prrc0
: NormalPRRc0RM
2227 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2229 LD/ST Immediate mode
2230 https://libre-soc.org/openpower/sv/ldst/
2235 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2236 """ld/st immediate: simple mode"""
2243 class LDSTImmPostRM(LDSTImmBaseRM
):
2244 """ld/st immediate: postinc mode (and load-fault)"""
2245 pi
: BaseRM
.mode
[3] # Post-Increment Mode
2246 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2248 def specifiers(self
, record
):
2255 class LDSTImmFFRc1RM(FFPRRc1BaseRM
, LDSTImmBaseRM
):
2256 """ld/st immediate: Rc=1: ffirst CR sel"""
2258 CR
: BaseRM
.mode
[3, 4]
2260 def specifiers(self
, record
):
2261 yield from super().specifiers(record
=record
, mode
="ff")
2264 class LDSTImmFFRc0RM(FFPRRc0BaseRM
, ElsBaseRM
, LDSTImmBaseRM
):
2265 """ld/st immediate: Rc=0: ffirst z/nonz"""
2270 def specifiers(self
, record
):
2271 yield from super().specifiers(record
=record
, mode
="ff")
2274 class LDSTImmSatRM(ElsBaseRM
, SatBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2275 """ld/st immediate: sat mode: N=0/1 u/s"""
2283 class LDSTImmPRRc1RM(FFPRRc1BaseRM
, LDSTImmBaseRM
):
2284 """ld/st immediate: Rc=1: pred-result CR sel"""
2286 CR
: BaseRM
.mode
[3, 4]
2288 def specifiers(self
, record
):
2289 yield from super().specifiers(record
=record
, mode
="pr")
2292 class LDSTImmPRRc0RM(FFPRRc0BaseRM
, ElsBaseRM
, LDSTImmBaseRM
):
2293 """ld/st immediate: Rc=0: pred-result z/nonz"""
2298 def specifiers(self
, record
):
2299 yield from super().specifiers(record
=record
, mode
="pr")
2302 class LDSTImmRM(LDSTImmBaseRM
):
2303 simple
: LDSTImmSimpleRM
2305 ffrc1
: LDSTImmFFRc1RM
2306 ffrc0
: LDSTImmFFRc0RM
2308 prrc1
: LDSTImmPRRc1RM
2309 prrc0
: LDSTImmPRRc0RM
2312 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2315 https://libre-soc.org/openpower/sv/ldst/
2320 class LDSTIdxSimpleRM(SEABaseRM
, ZZCombinedBaseRM
, LDSTIdxBaseRM
):
2321 """ld/st index: simple mode"""
2327 class LDSTIdxStrideRM(SEABaseRM
, ZZCombinedBaseRM
, LDSTIdxBaseRM
):
2328 """ld/st index: strided (scalar only source)"""
2333 def specifiers(self
, record
):
2336 yield from super().specifiers(record
=record
)
2339 class LDSTIdxSatRM(SatBaseRM
, ZZCombinedBaseRM
, LDSTIdxBaseRM
):
2340 """ld/st index: sat mode: N=0/1 u/s"""
2346 class LDSTIdxPRRc1RM(LDSTIdxBaseRM
):
2347 """ld/st index: Rc=1: pred-result CR sel"""
2349 CR
: BaseRM
.mode
[3, 4]
2351 def specifiers(self
, record
):
2352 yield from super().specifiers(record
=record
, mode
="pr")
2355 class LDSTIdxPRRc0RM(FFPRRc0BaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2356 """ld/st index: Rc=0: pred-result z/nonz"""
2363 def specifiers(self
, record
):
2364 yield from super().specifiers(record
=record
, mode
="pr")
2367 class LDSTIdxRM(LDSTIdxBaseRM
):
2368 simple
: LDSTIdxSimpleRM
2369 stride
: LDSTIdxStrideRM
2371 prrc1
: LDSTIdxPRRc1RM
2372 prrc0
: LDSTIdxPRRc0RM
2376 class CROpBaseRM(BaseRM
):
2379 https://libre-soc.org/openpower/sv/cr_ops/
2384 class CROpSimpleRM(PredicateBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2385 """crop: simple mode"""
2390 def specifiers(self
, record
):
2392 yield "rg" # simple CR Mode reports /rg
2394 yield from super().specifiers(record
=record
)
2397 class CROpMRRM(MRBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2398 """crop: scalar reduce mode (mapreduce), SUBVL=1"""
2404 class CROpFF3RM(FFPRRc0BaseRM
, PredicateBaseRM
, VLiBaseRM
, DZBaseRM
, SZBaseRM
, CROpBaseRM
):
2405 """crop: ffirst 3-bit mode"""
2412 def specifiers(self
, record
):
2413 yield from super().specifiers(record
=record
, mode
="ff")
2416 # FIXME: almost everything in this class contradicts the specs.
2417 # However, this is the direct translation of the pysvp64asm code.
2418 # Please revisit this code; there is an inactive sketch below.
2419 class CROpFF5RM(FFPRRc1BaseRM
, PredicateBaseRM
, VLiBaseRM
, CROpBaseRM
):
2420 """cr_op: ffirst 5-bit mode"""
2427 def specifiers(self
, record
):
2428 yield from super().specifiers(record
=record
, mode
="ff")
2431 class CROpRM(CROpBaseRM
):
2432 simple
: CROpSimpleRM
2438 # ********************
2440 # https://libre-soc.org/openpower/sv/branches/
2441 class BranchBaseRM(BaseRM
):
2451 def specifiers(self
, record
):
2463 raise ValueError(self
.sz
)
2475 # Branch modes lack source mask.
2476 # Therefore a custom code is needed.
2477 CR
= (int(self
.mmode
) == 1)
2478 mask
= int(self
.mask
)
2479 m
= PredicateBaseRM
.predicate(CR
, mask
)
2483 yield from super().specifiers(record
=record
)
2486 class BranchSimpleRM(BranchBaseRM
):
2487 """branch: simple mode"""
2491 class BranchVLSRM(BranchBaseRM
):
2492 """branch: VLSET mode"""
2496 def specifiers(self
, record
):
2502 }[int(self
.VSb
), int(self
.VLi
)]
2504 yield from super().specifiers(record
=record
)
2507 class BranchCTRRM(BranchBaseRM
):
2508 """branch: CTR-test mode"""
2511 def specifiers(self
, record
):
2517 yield from super().specifiers(record
=record
)
2520 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2521 """branch: CTR-test+VLSET mode"""
2525 class BranchRM(BranchBaseRM
):
2526 simple
: BranchSimpleRM
2529 ctrvls
: BranchCTRVLSRM
2540 @_dataclasses.dataclass(eq
=True, frozen
=True)
2545 def match(cls
, desc
, record
):
2546 raise NotImplementedError()
2548 def validate(self
, others
):
2551 def assemble(self
, insn
):
2552 raise NotImplementedError()
2555 @_dataclasses.dataclass(eq
=True, frozen
=True)
2556 class SpecifierWidth(Specifier
):
2560 def match(cls
, desc
, record
, etalon
):
2561 (mode
, _
, value
) = desc
.partition("=")
2563 value
= value
.strip()
2566 width
= _SVP64Width(value
)
2568 return cls(record
=record
, width
=width
)
2571 @_dataclasses.dataclass(eq
=True, frozen
=True)
2572 class SpecifierW(SpecifierWidth
):
2574 def match(cls
, desc
, record
):
2575 return super().match(desc
=desc
, record
=record
, etalon
="w")
2577 def assemble(self
, insn
):
2578 selector
= insn
.select(record
=self
.record
)
2579 selector
.ewsrc
= self
.width
.value
2580 selector
.elwidth
= self
.width
.value
2583 @_dataclasses.dataclass(eq
=True, frozen
=True)
2584 class SpecifierSW(SpecifierWidth
):
2586 def match(cls
, desc
, record
):
2587 return super().match(desc
=desc
, record
=record
, etalon
="sw")
2589 def assemble(self
, insn
):
2590 selector
= insn
.select(record
=self
.record
)
2591 selector
.ewsrc
= self
.width
.value
2594 @_dataclasses.dataclass(eq
=True, frozen
=True)
2595 class SpecifierDW(SpecifierWidth
):
2597 def match(cls
, desc
, record
):
2598 return super().match(desc
=desc
, record
=record
, etalon
="dw")
2600 def assemble(self
, insn
):
2601 selector
= insn
.select(record
=self
.record
)
2602 selector
.elwidth
= self
.width
.value
2605 @_dataclasses.dataclass(eq
=True, frozen
=True)
2606 class SpecifierSubVL(Specifier
):
2610 def match(cls
, desc
, record
):
2612 value
= _SVP64SubVL(desc
)
2616 return cls(record
=record
, value
=value
)
2618 def assemble(self
, insn
):
2619 selector
= insn
.select(record
=self
.record
)
2620 selector
.subvl
= int(self
.value
.value
)
2623 @_dataclasses.dataclass(eq
=True, frozen
=True)
2624 class SpecifierPredicate(Specifier
):
2629 def match(cls
, desc
, record
, mode_match
, pred_match
):
2630 (mode
, _
, pred
) = desc
.partition("=")
2633 if not mode_match(mode
):
2636 pred
= _SVP64Pred(pred
.strip())
2637 if not pred_match(pred
):
2638 raise ValueError(pred
)
2640 return cls(record
=record
, mode
=mode
, pred
=pred
)
2643 @_dataclasses.dataclass(eq
=True, frozen
=True)
2644 class SpecifierFFPR(SpecifierPredicate
):
2646 def match(cls
, desc
, record
, mode
):
2647 return super().match(desc
=desc
, record
=record
,
2648 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2649 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2654 def validate(self
, others
):
2655 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2656 if self
.mode
== "pr":
2657 raise ValueError("crop: 'pr' mode not supported")
2659 def assemble(self
, insn
):
2660 selector
= insn
.select(record
=self
.record
)
2661 if selector
.mode
.sel
!= 0:
2662 raise ValueError("cannot override mode")
2663 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2664 selector
.mode
.sel
= 0b10
2665 # HACK: please finally provide correct logic for CRs.
2666 if self
.pred
in (_SVP64Pred
.RC1
, _SVP64Pred
.RC1_N
):
2667 selector
.mode
[2] = (self
.pred
is _SVP64Pred
.RC1_N
)
2669 selector
.mode
[2] = self
.pred
.inv
2670 selector
.mode
[3, 4] = self
.pred
.state
2672 selector
.mode
.sel
= 0b01 if self
.mode
== "ff" else 0b11
2673 selector
.inv
= self
.pred
.inv
2675 selector
.CR
= self
.pred
.state
2677 selector
.RC1
= self
.pred
.state
2680 @_dataclasses.dataclass(eq
=True, frozen
=True)
2681 class SpecifierFF(SpecifierFFPR
):
2683 def match(cls
, desc
, record
):
2684 return super().match(desc
=desc
, record
=record
, mode
="ff")
2687 @_dataclasses.dataclass(eq
=True, frozen
=True)
2688 class SpecifierPR(SpecifierFFPR
):
2690 def match(cls
, desc
, record
):
2691 return super().match(desc
=desc
, record
=record
, mode
="pr")
2694 @_dataclasses.dataclass(eq
=True, frozen
=True)
2695 class SpecifierMask(SpecifierPredicate
):
2697 def match(cls
, desc
, record
, mode
):
2698 return super().match(desc
=desc
, record
=record
,
2699 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2700 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2705 def assemble(self
, insn
):
2706 raise NotImplementedError()
2709 @_dataclasses.dataclass(eq
=True, frozen
=True)
2710 class SpecifierM(SpecifierMask
):
2712 def match(cls
, desc
, record
):
2713 return super().match(desc
=desc
, record
=record
, mode
="m")
2715 def validate(self
, others
):
2717 if isinstance(spec
, SpecifierSM
):
2718 raise ValueError("source-mask and predicate mask conflict")
2719 elif isinstance(spec
, SpecifierDM
):
2720 raise ValueError("dest-mask and predicate mask conflict")
2722 def assemble(self
, insn
):
2723 selector
= insn
.select(record
=self
.record
)
2724 selector
.mask
= int(self
.pred
)
2725 if ((self
.record
.ptype
is _SVPType
.P2
) and
2726 (self
.record
.svp64
.mode
is not _SVMode
.BRANCH
)):
2727 selector
.smask
= int(self
.pred
)
2728 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2731 @_dataclasses.dataclass(eq
=True, frozen
=True)
2732 class SpecifierSM(SpecifierMask
):
2734 def match(cls
, desc
, record
):
2735 return super().match(desc
=desc
, record
=record
, mode
="sm")
2737 def validate(self
, others
):
2738 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2739 raise ValueError("source-mask on non-twin predicate")
2741 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2744 if isinstance(spec
, SpecifierDM
):
2748 raise ValueError("missing dest-mask in CR twin predication")
2749 if self
.pred
.mode
!= twin
.pred
.mode
:
2750 raise ValueError(f
"predicate masks mismatch: {self.pred!r} vs {twin.pred!r}")
2752 def assemble(self
, insn
):
2753 selector
= insn
.select(record
=self
.record
)
2754 selector
.smask
= int(self
.pred
)
2755 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2758 @_dataclasses.dataclass(eq
=True, frozen
=True)
2759 class SpecifierDM(SpecifierMask
):
2761 def match(cls
, desc
, record
):
2762 return super().match(desc
=desc
, record
=record
, mode
="dm")
2764 def validate(self
, others
):
2765 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2766 raise ValueError("dest-mask on non-twin predicate")
2768 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2771 if isinstance(spec
, SpecifierSM
):
2775 raise ValueError("missing source-mask in CR twin predication")
2776 if self
.pred
.mode
!= twin
.pred
.mode
:
2777 raise ValueError(f
"predicate masks mismatch: {self.pred!r} vs {twin.pred!r}")
2779 def assemble(self
, insn
):
2780 selector
= insn
.select(record
=self
.record
)
2781 selector
.mask
= int(self
.pred
)
2782 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2785 @_dataclasses.dataclass(eq
=True, frozen
=True)
2786 class SpecifierZZ(Specifier
):
2788 def match(cls
, desc
, record
):
2792 return cls(record
=record
)
2794 def validate(self
, others
):
2796 # Since zz takes precedence (overrides) sz and dz,
2797 # treat them as mutually exclusive.
2798 if isinstance(spec
, (SpecifierSZ
, SpecifierDZ
)):
2799 raise ValueError("mutually exclusive predicate masks")
2801 def assemble(self
, insn
):
2802 selector
= insn
.select(record
=self
.record
)
2803 if hasattr(selector
, "zz"): # this should be done in a different way
2810 @_dataclasses.dataclass(eq
=True, frozen
=True)
2811 class SpecifierXZ(Specifier
):
2813 hint
: str = _dataclasses
.field(repr=False)
2816 def match(cls
, desc
, record
, etalon
, hint
):
2820 return cls(desc
=desc
, record
=record
, hint
=hint
)
2822 def validate(self
, others
):
2823 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2824 raise ValueError(f
"{self.hint} on non-twin predicate")
2826 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2829 if isinstance(spec
, SpecifierXZ
):
2833 raise ValueError(f
"missing {self.hint} in CR twin predication")
2834 if self
.pred
!= twin
.pred
:
2835 raise ValueError(f
"predicate masks mismatch: {self.pred!r} vs {twin.pred!r}")
2837 def assemble(self
, insn
):
2838 selector
= insn
.select(record
=self
.record
)
2839 setattr(selector
, self
.desc
, 1)
2842 @_dataclasses.dataclass(eq
=True, frozen
=True)
2843 class SpecifierSZ(SpecifierXZ
):
2845 def match(cls
, desc
, record
):
2846 return super().match(desc
=desc
, record
=record
,
2847 etalon
="sz", hint
="source-mask")
2849 def validate(self
, others
):
2851 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2852 if isinstance(spec
, SpecifierFF
):
2853 raise ValueError("source-zero not allowed in ff mode")
2854 elif isinstance(spec
, SpecifierPR
):
2855 raise ValueError("source-zero not allowed in pr mode")
2858 @_dataclasses.dataclass(eq
=True, frozen
=True)
2859 class SpecifierDZ(SpecifierXZ
):
2861 def match(cls
, desc
, record
):
2862 return super().match(desc
=desc
, record
=record
,
2863 etalon
="dz", hint
="dest-mask")
2865 def validate(self
, others
):
2867 if ((self
.record
.svp64
.mode
is not _SVMode
.CROP
) and
2868 isinstance(spec
, (SpecifierFF
, SpecifierPR
)) and
2869 (spec
.pred
.mode
is _SVP64PredMode
.RC1
)):
2870 mode
= "ff" if isinstance(spec
, SpecifierFF
) else "pr"
2871 raise ValueError(f
"dest-zero not allowed in {mode} mode BO")
2874 @_dataclasses.dataclass(eq
=True, frozen
=True)
2875 class SpecifierEls(Specifier
):
2877 def match(cls
, desc
, record
):
2881 if record
.svp64
.mode
not in (_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
):
2882 raise ValueError("els is only valid in ld/st modes")
2884 return cls(record
=record
)
2886 def assemble(self
, insn
):
2887 if self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
: # stride mode
2888 insn
.prefix
.rm
.mode
[0] = 0
2889 insn
.prefix
.rm
.mode
[1] = 1
2891 selector
= insn
.select(record
=self
.record
)
2892 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
: # stride mode
2897 @_dataclasses.dataclass(eq
=True, frozen
=True)
2898 class SpecifierSEA(Specifier
):
2900 def match(cls
, desc
, record
):
2904 return cls(record
=record
)
2906 def validate(self
, others
):
2907 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
:
2908 raise ValueError("sea is only valid in ld/st modes")
2911 if isinstance(spec
, SpecifierFF
):
2912 raise ValueError(f
"sea cannot be used in ff mode")
2914 def assemble(self
, insn
):
2915 selector
= insn
.select(record
=self
.record
)
2916 if selector
.mode
.sel
not in (0b00, 0b01):
2917 raise ValueError("sea is only valid for normal and els modes")
2921 @_dataclasses.dataclass(eq
=True, frozen
=True)
2922 class SpecifierSat(Specifier
):
2927 def match(cls
, desc
, record
, etalon
, sign
):
2931 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
):
2932 raise ValueError("only normal, ld/st imm and ld/st idx modes supported")
2934 return cls(record
=record
, desc
=desc
, sign
=sign
)
2936 def assemble(self
, insn
):
2937 selector
= insn
.select(record
=self
.record
)
2938 selector
.mode
[0] = 0b1
2939 selector
.mode
[1] = 0b0
2940 selector
.N
= int(self
.sign
)
2943 @_dataclasses.dataclass(eq
=True, frozen
=True)
2944 class SpecifierSatS(SpecifierSat
):
2946 def match(cls
, desc
, record
):
2947 return super().match(desc
=desc
, record
=record
,
2948 etalon
="sats", sign
=True)
2951 @_dataclasses.dataclass(eq
=True, frozen
=True)
2952 class SpecifierSatU(SpecifierSat
):
2954 def match(cls
, desc
, record
):
2955 return super().match(desc
=desc
, record
=record
,
2956 etalon
="satu", sign
=False)
2959 @_dataclasses.dataclass(eq
=True, frozen
=True)
2960 class SpecifierMapReduce(Specifier
):
2964 def match(cls
, record
, RG
):
2965 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2966 raise ValueError("only normal and crop modes supported")
2968 return cls(record
=record
, RG
=RG
)
2970 def assemble(self
, insn
):
2971 selector
= insn
.select(record
=self
.record
)
2972 if self
.record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2973 raise ValueError("only normal and crop modes supported")
2974 selector
.mode
[0] = 0
2975 selector
.mode
[1] = 0
2976 selector
.mode
[2] = 1
2977 selector
.RG
= self
.RG
2980 @_dataclasses.dataclass(eq
=True, frozen
=True)
2981 class SpecifierMR(SpecifierMapReduce
):
2983 def match(cls
, desc
, record
):
2987 return super().match(record
=record
, RG
=False)
2990 @_dataclasses.dataclass(eq
=True, frozen
=True)
2991 class SpecifierMRR(SpecifierMapReduce
):
2993 def match(cls
, desc
, record
):
2997 return super().match(record
=record
, RG
=True)
3000 @_dataclasses.dataclass(eq
=True, frozen
=True)
3001 class SpecifierBranch(Specifier
):
3003 def match(cls
, desc
, record
, etalon
):
3007 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3008 raise ValueError("only branch modes supported")
3010 return cls(record
=record
)
3013 @_dataclasses.dataclass(eq
=True, frozen
=True)
3014 class SpecifierAll(SpecifierBranch
):
3016 def match(cls
, desc
, record
):
3017 return super().match(desc
=desc
, record
=record
, etalon
="all")
3019 def assemble(self
, insn
):
3020 selector
= insn
.select(record
=self
.record
)
3024 @_dataclasses.dataclass(eq
=True, frozen
=True)
3025 class SpecifierSNZ(Specifier
):
3027 def match(cls
, desc
, record
):
3031 if record
.svp64
.mode
not in (_SVMode
.BRANCH
, _SVMode
.CROP
):
3032 raise ValueError("only branch and crop modes supported")
3034 return cls(record
=record
)
3036 def assemble(self
, insn
):
3037 selector
= insn
.select(record
=self
.record
)
3038 if self
.record
.svp64
.mode
in (_SVMode
.CROP
, _SVMode
.BRANCH
):
3040 if self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3043 raise ValueError("only branch and crop modes supported")
3046 @_dataclasses.dataclass(eq
=True, frozen
=True)
3047 class SpecifierSL(SpecifierBranch
):
3049 def match(cls
, desc
, record
):
3050 return super().match(desc
=desc
, record
=record
, etalon
="sl")
3052 def assemble(self
, insn
):
3053 selector
= insn
.select(record
=self
.record
)
3057 @_dataclasses.dataclass(eq
=True, frozen
=True)
3058 class SpecifierSLu(SpecifierBranch
):
3060 def match(cls
, desc
, record
):
3061 return super().match(desc
=desc
, record
=record
, etalon
="slu")
3063 def assemble(self
, insn
):
3064 selector
= insn
.select(record
=self
.record
)
3068 @_dataclasses.dataclass(eq
=True, frozen
=True)
3069 class SpecifierLRu(SpecifierBranch
):
3071 def match(cls
, desc
, record
):
3072 return super().match(desc
=desc
, record
=record
, etalon
="lru")
3074 def assemble(self
, insn
):
3075 selector
= insn
.select(record
=self
.record
)
3079 @_dataclasses.dataclass(eq
=True, frozen
=True)
3080 class SpecifierVSXX(SpecifierBranch
):
3085 def match(cls
, desc
, record
, etalon
, VSb
, VLi
):
3089 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3090 raise ValueError("only branch modes supported")
3092 return cls(record
=record
, VSb
=VSb
, VLi
=VLi
)
3094 def assemble(self
, insn
):
3095 selector
= insn
.select(record
=self
.record
)
3097 selector
.VSb
= int(self
.VSb
)
3098 selector
.VLi
= int(self
.VLi
)
3101 @_dataclasses.dataclass(eq
=True, frozen
=True)
3102 class SpecifierVS(SpecifierVSXX
):
3104 def match(cls
, desc
, record
):
3105 return super().match(desc
=desc
, record
=record
,
3106 etalon
="vs", VSb
=False, VLi
=False)
3109 @_dataclasses.dataclass(eq
=True, frozen
=True)
3110 class SpecifierVSi(SpecifierVSXX
):
3112 def match(cls
, desc
, record
):
3113 return super().match(desc
=desc
, record
=record
,
3114 etalon
="vsi", VSb
=False, VLi
=True)
3117 @_dataclasses.dataclass(eq
=True, frozen
=True)
3118 class SpecifierVSb(SpecifierVSXX
):
3120 def match(cls
, desc
, record
):
3121 return super().match(desc
=desc
, record
=record
,
3122 etalon
="vsb", VSb
=True, VLi
=False)
3125 @_dataclasses.dataclass(eq
=True, frozen
=True)
3126 class SpecifierVSbi(SpecifierVSXX
):
3128 def match(cls
, desc
, record
):
3129 return super().match(desc
=desc
, record
=record
,
3130 etalon
="vsbi", VSb
=True, VLi
=True)
3133 @_dataclasses.dataclass(eq
=True, frozen
=True)
3134 class SpecifierCTX(Specifier
):
3138 def match(cls
, desc
, record
, etalon
, CTi
):
3142 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3143 raise ValueError("only branch modes supported")
3145 return cls(record
=record
, CTi
=CTi
)
3147 def assemble(self
, insn
):
3148 selector
= insn
.select(record
=self
.record
)
3150 selector
.CTi
= int(self
.CTi
)
3153 @_dataclasses.dataclass(eq
=True, frozen
=True)
3154 class SpecifierCTR(SpecifierCTX
):
3156 def match(cls
, desc
, record
):
3157 return super().match(desc
=desc
, record
=record
,
3158 etalon
="ctr", CTi
=False)
3161 @_dataclasses.dataclass(eq
=True, frozen
=True)
3162 class SpecifierCTi(SpecifierCTX
):
3164 def match(cls
, desc
, record
):
3165 return super().match(desc
=desc
, record
=record
,
3166 etalon
="cti", CTi
=True)
3169 @_dataclasses.dataclass(eq
=True, frozen
=True)
3170 class SpecifierPI(Specifier
):
3172 def match(cls
, desc
, record
):
3176 if record
.svp64
.mode
is not _SVMode
.LDST_IMM
:
3177 raise ValueError("only ld/st imm mode supported")
3179 return cls(record
=record
)
3181 def assemble(self
, insn
):
3182 selector
= insn
.select(record
=self
.record
)
3183 selector
.mode
[0] = 0b0
3184 selector
.mode
[1] = 0b0
3185 selector
.mode
[2] = 0b1
3189 @_dataclasses.dataclass(eq
=True, frozen
=True)
3190 class SpecifierLF(Specifier
):
3192 def match(cls
, desc
, record
):
3196 if record
.svp64
.mode
is not _SVMode
.LDST_IMM
:
3197 raise ValueError("only ld/st imm mode supported")
3199 return cls(record
=record
)
3201 def assemble(self
, insn
):
3202 selector
= insn
.select(record
=self
.record
)
3203 selector
.mode
[2] = 1
3207 @_dataclasses.dataclass(eq
=True, frozen
=True)
3208 class SpecifierVLi(Specifier
):
3210 def match(cls
, desc
, record
):
3214 return cls(record
=record
)
3216 def validate(self
, others
):
3218 if isinstance(spec
, SpecifierFF
):
3221 raise ValueError("VLi only allowed in failfirst")
3223 def assemble(self
, insn
):
3224 selector
= insn
.select(record
=self
.record
)
3228 class Specifiers(tuple):
3264 def __new__(cls
, items
, record
):
3265 def transform(item
):
3266 for spec_cls
in cls
.SPECS
:
3267 spec
= spec_cls
.match(item
, record
=record
)
3268 if spec
is not None:
3270 raise ValueError(item
)
3272 # TODO: remove this hack
3273 items
= dict.fromkeys(items
)
3277 items
= tuple(items
)
3279 specs
= tuple(map(transform
, items
))
3280 for (index
, spec
) in enumerate(specs
):
3281 head
= specs
[:index
]
3282 tail
= specs
[index
+ 1:]
3283 spec
.validate(others
=(head
+ tail
))
3285 return super().__new
__(cls
, specs
)
3288 class SVP64OperandMeta(type):
3289 class SVP64NonZeroOperand(NonZeroOperand
):
3290 def assemble(self
, insn
, value
):
3291 if isinstance(value
, str):
3292 value
= int(value
, 0)
3293 if not isinstance(value
, int):
3294 raise ValueError("non-integer operand")
3296 # FIXME: this is really weird
3297 if self
.record
.name
in ("svstep", "svstep."):
3298 value
+= 1 # compensation
3300 return super().assemble(value
=value
, insn
=insn
)
3302 class SVP64XOStaticOperand(SpanStaticOperand
):
3303 def __init__(self
, record
, value
, span
):
3304 return super().__init
__(record
=record
, name
="XO", value
=value
, span
=span
)
3307 NonZeroOperand
: SVP64NonZeroOperand
,
3308 XOStaticOperand
: SVP64XOStaticOperand
,
3311 def __new__(metacls
, name
, bases
, ns
):
3313 for (index
, base_cls
) in enumerate(bases
):
3314 bases
[index
] = metacls
.__TRANSFORM
.get(base_cls
, base_cls
)
3316 bases
= tuple(bases
)
3318 return super().__new
__(metacls
, name
, bases
, ns
)
3321 class SVP64Operand(Operand
, metaclass
=SVP64OperandMeta
):
3324 return tuple(map(lambda bit
: (bit
+ 32), super().span
))
3328 def __init__(self
, insn
, record
):
3330 self
.__record
= record
3331 return super().__init
__()
3334 return self
.rm
.__doc
__
3337 return repr(self
.rm
)
3345 return self
.__record
3349 rm
= getattr(self
.insn
.prefix
.rm
, self
.record
.svp64
.mode
.name
.lower())
3351 # The idea behind these tables is that they are now literally
3352 # in identical format to insndb.csv and minor_xx.csv and can
3353 # be done precisely as that. The only thing to watch out for
3354 # is the insertion of Rc=1 as a "mask/value" bit and likewise
3355 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
3358 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
3359 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3360 # mode Rc mask Rc member
3362 (0b000000, 0b111000, "simple"), # simple (no Rc)
3363 (0b001000, 0b111000, "mr"), # mapreduce (no Rc)
3364 (0b010001, 0b110001, "ffrc1"), # ffirst, Rc=1
3365 (0b010000, 0b110001, "ffrc0"), # ffirst, Rc=0
3366 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3367 (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
3368 (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
3370 search
= ((int(self
.insn
.prefix
.rm
.normal
.mode
) << 1) | self
.record
.Rc
)
3372 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
3373 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3374 # mode Rc mask Rc member
3375 # ironically/coincidentally this table is identical to NORMAL
3376 # mode except reserved in place of mr
3378 (0b000000, 0b111000, "simple"), # simple (no Rc)
3379 (0b001000, 0b111000, "post"), # post (no Rc)
3380 (0b010001, 0b110001, "ffrc1"), # ffirst, Rc=1
3381 (0b010000, 0b110001, "ffrc0"), # ffirst, Rc=0
3382 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3383 (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
3384 (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
3386 search
= ((int(self
.insn
.prefix
.rm
.ldst_imm
.mode
) << 1) | self
.record
.Rc
)
3388 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
3389 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3390 # mode Rc mask Rc member
3392 (0b000000, 0b110000, "simple"), # simple (no Rc)
3393 (0b010000, 0b110000, "stride"), # strided, (no Rc)
3394 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3395 (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
3396 (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
3398 search
= ((int(self
.insn
.prefix
.rm
.ldst_idx
.mode
) << 1) | self
.record
.Rc
)
3400 elif self
.record
.svp64
.mode
is _SVMode
.CROP
:
3401 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
3402 # mode 3b mask 3b member
3404 (0b000000, 0b111000, "simple"), # simple
3405 (0b001000, 0b111000, "mr"), # mapreduce
3406 (0b100001, 0b100001, "ff3"), # ffirst, 3-bit CR
3407 (0b100000, 0b100000, "ff5"), # ffirst, 5-bit CR
3409 search
= ((int(self
.insn
.prefix
.rm
.crop
.mode
) << 1) |
int(self
.record
.svp64
.extra_CR_3bit
))
3411 elif self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3415 (0b00, 0b11, "simple"), # simple
3416 (0b01, 0b11, "vls"), # VLset
3417 (0b10, 0b11, "ctr"), # CTR mode
3418 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
3420 # slightly weird: doesn't have a 5-bit "mode" field like others
3421 search
= int(self
.insn
.prefix
.rm
.branch
.mode
.sel
)
3424 if table
is not None:
3425 for (value
, mask
, field
) in table
:
3426 if ((value
& mask
) == (search
& mask
)):
3427 return getattr(rm
, field
)
3431 def __getattr__(self
, key
):
3432 if key
.startswith(f
"_{self.__class__.__name__}__"):
3433 return super().__getattribute
__(key
)
3435 return getattr(self
.rm
, key
)
3437 def __setattr__(self
, key
, value
):
3438 if key
.startswith(f
"_{self.__class__.__name__}__"):
3439 return super().__setattr
__(key
, value
)
3442 if not hasattr(rm
, key
):
3443 raise AttributeError(key
)
3445 return setattr(rm
, key
, value
)
3448 class SVP64Instruction(PrefixedInstruction
):
3449 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
3450 class Prefix(PrefixedInstruction
.Prefix
):
3452 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
3456 def select(self
, record
):
3457 return RMSelector(insn
=self
, record
=record
)
3462 for idx
in range(64):
3463 bit
= int(self
[idx
])
3465 return "".join(map(str, bits
))
3468 def assemble(cls
, record
, arguments
=None, specifiers
=None):
3469 insn
= super().assemble(record
=record
, arguments
=arguments
)
3471 specifiers
= Specifiers(items
=specifiers
, record
=record
)
3472 for specifier
in specifiers
:
3473 specifier
.assemble(insn
=insn
)
3475 insn
.prefix
.PO
= 0x1
3476 insn
.prefix
.id = 0x3
3480 def disassemble(self
, record
,
3482 style
=Style
.NORMAL
):
3484 if style
<= Style
.SHORT
:
3487 blob
= insn
.bytes(byteorder
=byteorder
)
3488 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
3491 blob_prefix
= blob(self
.prefix
)
3492 blob_suffix
= blob(self
.suffix
)
3494 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3495 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
3498 assert record
.svp64
is not None
3500 name
= f
"sv.{record.name}"
3502 rm
= self
.select(record
=record
)
3504 # convert specifiers to /x/y/z (sorted lexicographically)
3505 specifiers
= sorted(rm
.specifiers(record
=record
))
3506 if specifiers
: # if any add one extra to get the extra "/"
3507 specifiers
= ([""] + specifiers
)
3508 specifiers
= "/".join(specifiers
)
3510 # convert operands to " ,x,y,z"
3511 operands
= tuple(map(_operator
.itemgetter(1),
3512 self
.spec_dynamic_operands(record
=record
, style
=style
)))
3513 operands
= ",".join(operands
)
3514 if len(operands
) > 0: # if any separate with a space
3515 operands
= (" " + operands
)
3517 if style
<= Style
.LEGACY
:
3518 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3519 suffix
= WordInstruction
.integer(value
=int(self
.suffix
))
3520 yield from suffix
.disassemble(record
=record
,
3521 byteorder
=byteorder
, style
=style
)
3523 yield f
"{blob_prefix}{name}{specifiers}{operands}"
3525 yield f
"{blob_suffix}"
3527 if style
>= Style
.VERBOSE
:
3529 binary
= self
.binary
3530 spec
= self
.spec(record
=record
, prefix
="sv.")
3532 yield f
"{indent}spec"
3533 yield f
"{indent}{indent}{spec}"
3534 yield f
"{indent}pcode"
3535 for stmt
in record
.mdwn
.pcode
:
3536 yield f
"{indent}{indent}{stmt}"
3537 yield f
"{indent}binary"
3538 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
3539 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
3540 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
3541 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
3542 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
3543 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
3544 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
3545 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
3546 yield f
"{indent}opcodes"
3547 for opcode
in record
.opcodes
:
3548 yield f
"{indent}{indent}{opcode!r}"
3549 for operand
in self
.operands(record
=record
):
3550 yield from operand
.disassemble(insn
=self
,
3551 style
=style
, indent
=indent
)
3553 yield f
"{indent}{indent}{str(rm)}"
3554 for line
in rm
.disassemble(style
=style
):
3555 yield f
"{indent}{indent}{line}"
3559 def operands(cls
, record
):
3560 for operand
in super().operands(record
=record
):
3561 parent
= operand
.__class
__
3562 name
= f
"SVP64{parent.__name__}"
3563 bases
= (SVP64Operand
, parent
)
3564 child
= type(name
, bases
, {})
3565 yield child(**dict(operand
))
3568 def parse(stream
, factory
):
3570 return ("TODO" not in frozenset(entry
.values()))
3572 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
3573 entries
= _csv
.DictReader(lines
)
3574 entries
= filter(match
, entries
)
3575 return tuple(map(factory
, entries
))
3578 class MarkdownDatabase
:
3581 for (name
, desc
) in _ISA():
3584 (dynamic
, *static
) = desc
.regs
3585 operands
.extend(dynamic
)
3586 operands
.extend(static
)
3587 pcode
= PCode(iterable
=desc
.pcode
)
3588 operands
= Operands(insn
=name
, operands
=operands
)
3589 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
3591 self
.__db
= dict(sorted(db
.items()))
3593 return super().__init
__()
3596 yield from self
.__db
.items()
3598 def __contains__(self
, key
):
3599 return self
.__db
.__contains
__(key
)
3601 def __getitem__(self
, key
):
3602 return self
.__db
.__getitem
__(key
)
3605 class FieldsDatabase
:
3608 df
= _DecodeFields()
3610 for (form
, fields
) in df
.instrs
.items():
3611 if form
in {"DQE", "TX"}:
3615 db
[_Form
[form
]] = Fields(fields
)
3619 return super().__init
__()
3621 def __getitem__(self
, key
):
3622 return self
.__db
.__getitem
__(key
)
3626 def __init__(self
, root
, mdwndb
):
3627 # The code below groups the instructions by name:section.
3628 # There can be multiple names for the same instruction.
3629 # The point is to capture different opcodes for the same instruction.
3631 records
= _collections
.defaultdict(set)
3632 path
= (root
/ "insndb.csv")
3633 with
open(path
, "r", encoding
="UTF-8") as stream
:
3634 for section
in sorted(parse(stream
, Section
.CSV
)):
3635 path
= (root
/ section
.path
)
3637 section
.Mode
.INTEGER
: IntegerOpcode
,
3638 section
.Mode
.PATTERN
: PatternOpcode
,
3640 factory
= _functools
.partial(
3641 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
3642 with
open(path
, "r", encoding
="UTF-8") as stream
:
3643 for insn
in parse(stream
, factory
):
3644 for name
in insn
.names
:
3645 records
[name
].add(insn
)
3646 sections
[name
] = section
3648 items
= sorted(records
.items())
3650 for (name
, multirecord
) in items
:
3651 records
[name
] = PPCMultiRecord(sorted(multirecord
))
3653 def exact_match(name
):
3654 record
= records
.get(name
)
3660 if not name
.endswith("l"):
3662 alias
= exact_match(name
[:-1])
3665 record
= records
[alias
]
3666 if "lk" not in record
.flags
:
3667 raise ValueError(record
)
3671 if not name
.endswith("a"):
3673 alias
= LK_match(name
[:-1])
3676 record
= records
[alias
]
3677 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
3678 raise ValueError(record
)
3679 if "AA" not in mdwndb
[name
].operands
:
3680 raise ValueError(record
)
3684 if not name
.endswith("."):
3686 alias
= exact_match(name
[:-1])
3689 record
= records
[alias
]
3690 if record
.Rc
is _RCOE
.NONE
:
3691 raise ValueError(record
)
3695 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
3696 for (name
, _
) in mdwndb
:
3697 if name
.startswith("sv."):
3700 for match
in matches
:
3702 if alias
is not None:
3706 section
= sections
[alias
]
3707 record
= records
[alias
]
3708 db
[name
] = (section
, record
)
3710 self
.__db
= dict(sorted(db
.items()))
3712 return super().__init
__()
3714 @_functools.lru_cache(maxsize
=512, typed
=False)
3715 def __getitem__(self
, key
):
3716 return self
.__db
.get(key
, (None, None))
3719 class SVP64Database
:
3720 def __init__(self
, root
, ppcdb
):
3722 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
3723 for (prefix
, _
, names
) in _os
.walk(root
):
3724 prefix
= _pathlib
.Path(prefix
)
3725 for name
in filter(lambda name
: pattern
.match(name
), names
):
3726 path
= (prefix
/ _pathlib
.Path(name
))
3727 with
open(path
, "r", encoding
="UTF-8") as stream
:
3728 db
.update(parse(stream
, SVP64Record
.CSV
))
3729 db
= {record
.name
:record
for record
in db
}
3731 self
.__db
= dict(sorted(db
.items()))
3732 self
.__ppcdb
= ppcdb
3734 return super().__init
__()
3736 def __getitem__(self
, key
):
3737 (_
, record
) = self
.__ppcdb
[key
]
3741 for name
in record
.names
:
3742 record
= self
.__db
.get(name
, None)
3743 if record
is not None:
3750 def __init__(self
, root
):
3751 root
= _pathlib
.Path(root
)
3752 mdwndb
= MarkdownDatabase()
3753 fieldsdb
= FieldsDatabase()
3754 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
3755 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
3759 opcodes
= _collections
.defaultdict(
3760 lambda: _collections
.defaultdict(set))
3762 for (name
, mdwn
) in mdwndb
:
3763 if name
.startswith("sv."):
3765 (section
, ppc
) = ppcdb
[name
]
3768 svp64
= svp64db
[name
]
3769 fields
= fieldsdb
[ppc
.form
]
3770 record
= Record(name
=name
,
3771 section
=section
, ppc
=ppc
, svp64
=svp64
,
3772 mdwn
=mdwn
, fields
=fields
)
3774 names
[record
.name
] = record
3775 opcodes
[section
][record
.PO
].add(record
)
3777 self
.__db
= sorted(db
)
3778 self
.__names
= dict(sorted(names
.items()))
3779 self
.__opcodes
= dict(sorted(opcodes
.items()))
3781 return super().__init
__()
3784 return repr(self
.__db
)
3787 yield from self
.__db
3789 @_functools.lru_cache(maxsize
=None)
3790 def __contains__(self
, key
):
3791 return self
.__getitem
__(key
) is not None
3793 @_functools.lru_cache(maxsize
=None)
3794 def __getitem__(self
, key
):
3795 if isinstance(key
, SVP64Instruction
):
3798 if isinstance(key
, Instruction
):
3801 sections
= sorted(self
.__opcodes
)
3802 for section
in sections
:
3803 group
= self
.__opcodes
[section
]
3804 for record
in group
[PO
]:
3805 if record
.match(key
=key
):
3810 elif isinstance(key
, str):
3811 return self
.__names
.get(key
)
3813 raise ValueError("instruction or name expected")