1 import collections
as _collections
2 import contextlib
as _contextlib
4 import dataclasses
as _dataclasses
6 import functools
as _functools
7 import inspect
as _inspect
9 import operator
as _operator
10 import pathlib
as _pathlib
12 import types
as _types
13 import typing
as _typing
16 from functools
import cached_property
18 from cached_property
import cached_property
20 from openpower
.decoder
.power_enums
import (
21 Function
as _Function
,
28 CRIn2Sel
as _CRIn2Sel
,
29 CROutSel
as _CROutSel
,
31 LDSTMode
as _LDSTMode
,
36 SVMaskSrc
as _SVMaskSrc
,
43 SVP64SubVL
as _SVP64SubVL
,
44 SVP64Pred
as _SVP64Pred
,
45 SVP64PredMode
as _SVP64PredMode
,
46 SVP64Width
as _SVP64Width
,
48 from openpower
.decoder
.selectable_int
import (
49 SelectableInt
as _SelectableInt
,
50 selectconcat
as _selectconcat
,
52 from openpower
.decoder
.power_fields
import (
55 DecodeFields
as _DecodeFields
,
57 from openpower
.decoder
.pseudo
.pagereader
import ISA
as _ISA
61 def __init__(self
, walk
):
63 return super().__init
__()
65 def __get__(self
, instance
, owner
):
69 return _functools
.partial(self
.__walk
, entity
)
74 def walk(clsself
, match
=None):
78 class String(Node
, str):
82 class Path(Node
, type(_pathlib
.Path())):
86 class DataclassMeta(type):
87 def __new__(metacls
, name
, bases
, ns
):
88 cls
= super().__new
__(metacls
, name
, bases
, ns
)
89 return _dataclasses
.dataclass(cls
, eq
=True, frozen
=True)
92 class Dataclass(metaclass
=DataclassMeta
):
94 def walk(clsself
, match
=None):
96 match
= lambda subnode
: True
98 def field_type(field
):
101 def field_value(field
):
102 return getattr(clsself
, field
.name
)
104 field
= (field_type
if isinstance(clsself
, type) else field_value
)
106 yield from filter(match
, map(field
, _dataclasses
.fields(clsself
)))
110 @_contextlib.contextmanager
111 def __call__(self
, node
):
115 def walk(root
, match
=None):
116 nodes
= _collections
.deque([root
])
118 node
= nodes
.popleft()
119 nodes
.extend(node
.walk(match
=match
))
123 def visit(visitor
, node
):
124 with
visitor(node
=node
):
125 if hasattr(node
, "walk"):
126 for subnode
in node
.walk():
127 visit(visitor
=visitor
, node
=subnode
)
130 @_functools.total_ordering
131 class Style(_enum
.Enum
):
132 LEGACY
= _enum
.auto()
134 NORMAL
= _enum
.auto()
135 VERBOSE
= _enum
.auto()
137 def __lt__(self
, other
):
138 if not isinstance(other
, self
.__class
__):
139 return NotImplemented
140 return (self
.value
< other
.value
)
143 @_functools.total_ordering
144 class Priority(_enum
.Enum
):
150 def _missing_(cls
, value
):
151 if isinstance(value
, str):
152 value
= value
.upper()
156 return super()._missing
_(value
)
158 def __lt__(self
, other
):
159 if not isinstance(other
, self
.__class
__):
160 return NotImplemented
162 # NOTE: the order is inversed, LOW < NORMAL < HIGH
163 return (self
.value
> other
.value
)
166 def dataclass(cls
, record
, keymap
=None, typemap
=None):
170 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
172 def transform(key_value
):
173 (key
, value
) = key_value
174 key
= keymap
.get(key
, key
)
175 hook
= typemap
.get(key
, lambda value
: value
)
176 if hook
is bool and value
in ("", "0"):
182 record
= dict(map(transform
, record
.items()))
183 for key
in frozenset(record
.keys()):
184 if record
[key
] == "":
190 @_functools.total_ordering
191 class Opcode(Dataclass
):
193 def __new__(cls
, value
):
194 if isinstance(value
, str):
195 value
= int(value
, 0)
196 if not isinstance(value
, int):
197 raise ValueError(value
)
199 if value
.bit_length() > 64:
200 raise ValueError(value
)
202 return super().__new
__(cls
, value
)
205 return self
.__repr
__()
208 return f
"{self:0{self.bit_length()}b}"
210 def bit_length(self
):
211 if super().bit_length() > 32:
215 class Value(Integer
):
224 def __lt__(self
, other
):
225 if not isinstance(other
, Opcode
):
226 return NotImplemented
227 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
230 return (self
.value
& self
.mask
)
233 return int(self
).__index
__()
236 def pattern(value
, mask
, bit_length
):
237 for bit
in range(bit_length
):
238 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
240 elif (value
& (1 << (bit_length
- bit
- 1))):
245 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
247 def match(self
, key
):
248 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
251 @_functools.total_ordering
252 class IntegerOpcode(Opcode
):
253 def __init__(self
, value
):
254 if value
.startswith("0b"):
255 mask
= int(("1" * len(value
[2:])), 2)
259 value
= Opcode
.Value(value
)
260 mask
= Opcode
.Mask(mask
)
262 return super().__init
__(value
=value
, mask
=mask
)
265 @_functools.total_ordering
266 class PatternOpcode(Opcode
):
267 def __init__(self
, pattern
):
268 if not isinstance(pattern
, str):
269 raise ValueError(pattern
)
271 (value
, mask
) = (0, 0)
272 for symbol
in pattern
:
273 if symbol
not in {"0", "1", "-"}:
274 raise ValueError(pattern
)
275 value |
= (symbol
== "1")
276 mask |
= (symbol
!= "-")
282 value
= Opcode
.Value(value
)
283 mask
= Opcode
.Mask(mask
)
285 return super().__init
__(value
=value
, mask
=mask
)
288 class PPCRecord(Dataclass
):
289 class FlagsMeta(type):
304 class Flags(tuple, metaclass
=FlagsMeta
):
305 def __new__(cls
, flags
=frozenset()):
306 flags
= frozenset(flags
)
307 diff
= (flags
- frozenset(cls
))
309 raise ValueError(flags
)
310 return super().__new
__(cls
, sorted(flags
))
314 flags
: Flags
= Flags()
315 comment2
: String
= String()
316 function
: _Function
= _Function
.NONE
317 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
318 in1
: _In1Sel
= _In1Sel
.NONE
319 in2
: _In2Sel
= _In2Sel
.NONE
320 in3
: _In3Sel
= _In3Sel
.NONE
321 out
: _OutSel
= _OutSel
.NONE
322 cr_in
: _CRInSel
= _CRInSel
.NONE
323 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
324 cr_out
: _CROutSel
= _CROutSel
.NONE
325 cry_in
: _CryIn
= _CryIn
.ZERO
326 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
327 upd
: _LDSTMode
= _LDSTMode
.NONE
328 Rc
: _RCOE
= _RCOE
.NONE
329 form
: _Form
= _Form
.NONE
330 conditions
: String
= String()
331 unofficial
: bool = False
335 "internal op": "intop",
339 "ldst len": "ldst_len",
341 "CONDITIONS": "conditions",
344 def __lt__(self
, other
):
345 if not isinstance(other
, self
.__class
__):
346 return NotImplemented
347 lhs
= (self
.opcode
, self
.comment
)
348 rhs
= (other
.opcode
, other
.comment
)
352 def CSV(cls
, record
, opcode_cls
):
353 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
354 typemap
["opcode"] = opcode_cls
356 if record
["CR in"] == "BA_BB":
357 record
["cr_in"] = "BA"
358 record
["cr_in2"] = "BB"
362 for flag
in frozenset(PPCRecord
.Flags
):
363 if bool(record
.pop(flag
, "")):
365 record
["flags"] = PPCRecord
.Flags(flags
)
367 return dataclass(cls
, record
,
368 keymap
=PPCRecord
.__KEYMAP
,
373 return frozenset(self
.comment
.split("=")[-1].split("/"))
376 class PPCMultiRecord(tuple):
377 def __getattr__(self
, attr
):
380 raise AttributeError(attr
)
381 return getattr(self
[0], attr
)
384 class SVP64Record(Dataclass
):
385 class ExtraMap(tuple):
387 @_dataclasses.dataclass(eq
=True, frozen
=True)
389 seltype
: _SelType
= _SelType
.NONE
390 reg
: _Reg
= _Reg
.NONE
393 return f
"{self.seltype.value}:{self.reg.name}"
395 def __new__(cls
, value
="0"):
396 if isinstance(value
, str):
397 def transform(value
):
398 (seltype
, reg
) = value
.split(":")
399 seltype
= _SelType(seltype
)
401 return cls
.Entry(seltype
=seltype
, reg
=reg
)
406 value
= map(transform
, value
.split(";"))
408 return super().__new
__(cls
, value
)
411 return repr(list(self
))
413 def __new__(cls
, value
=tuple()):
417 return super().__new
__(cls
, map(cls
.Extra
, value
))
420 return repr({index
:self
[index
] for index
in range(0, 4)})
423 ptype
: _SVPType
= _SVPType
.NONE
424 etype
: _SVEType
= _SVEType
.NONE
425 msrc
: _SVMaskSrc
= _SVMaskSrc
.NO
# MASK_SRC is active
426 in1
: _In1Sel
= _In1Sel
.NONE
427 in2
: _In2Sel
= _In2Sel
.NONE
428 in3
: _In3Sel
= _In3Sel
.NONE
429 out
: _OutSel
= _OutSel
.NONE
430 out2
: _OutSel
= _OutSel
.NONE
431 cr_in
: _CRInSel
= _CRInSel
.NONE
432 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
433 cr_out
: _CROutSel
= _CROutSel
.NONE
434 extra
: ExtraMap
= ExtraMap()
435 conditions
: String
= String()
436 mode
: _SVMode
= _SVMode
.NORMAL
440 "CONDITIONS": "conditions",
449 def CSV(cls
, record
):
450 record
["insn"] = record
["insn"].split("=")[-1]
452 for key
in frozenset({
453 "in1", "in2", "in3", "CR in",
454 "out", "out2", "CR out",
460 if record
["CR in"] == "BA_BB":
461 record
["cr_in"] = "BA"
462 record
["cr_in2"] = "BB"
466 for idx
in range(0, 4):
467 extra
.append(record
.pop(f
"{idx}"))
469 record
["extra"] = cls
.ExtraMap(extra
)
471 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
476 "in1", "in2", "in3", "cr_in", "cr_in2",
477 "out", "out2", "cr_out",
492 for index
in range(0, 4):
493 for entry
in self
.extra
[index
]:
494 extras
[entry
.seltype
][entry
.reg
] = idxmap
[index
]
496 for (seltype
, regs
) in extras
.items():
497 idx
= regs
.get(reg
, _SVExtra
.NONE
)
498 if idx
is not _SVExtra
.NONE
:
499 yield (reg
, seltype
, idx
)
506 # has the word "in", it is a SelType.SRC "out" -> DST
507 # in1/2/3 and CR in are SRC, and must match only against "s:NN"
508 # out/out1 and CR out are DST, and must match only against "d:NN"
509 keytype
= _SelType
.SRC
if ("in" in key
) else _SelType
.DST
510 sel
= sels
[key
] = getattr(self
, key
)
511 reg
= regs
[key
] = _Reg(sel
)
512 seltypes
[key
] = _SelType
.NONE
513 idxs
[key
] = _SVExtra
.NONE
514 for (reg
, seltype
, idx
) in extra(reg
.alias
):
515 if keytype
!= seltype
: # only check SRC-to-SRC and DST-to-DST
517 if idx
!= idxs
[key
] and idxs
[key
] is not _SVExtra
.NONE
:
518 raise ValueError(idx
)
521 seltypes
[key
] = seltype
523 if sels
["cr_in"] is _CRInSel
.BA_BB
:
524 sels
["cr_in"] = _CRIn2Sel
.BA
525 sels
["cr_in2"] = _CRIn2Sel
.BB
526 idxs
["cr_in2"] = idxs
["cr_in"]
527 for key
in ("cr_in", "cr_in2"):
528 regs
[key
] = _Reg(sels
[key
])
529 seltype
[key
] = _SelType
.SRC
536 "seltype": seltypes
[key
],
540 return _types
.MappingProxyType(records
)
542 extra_idx_in1
= property(lambda self
: self
.extras
["in1"]["idx"])
543 extra_idx_in2
= property(lambda self
: self
.extras
["in2"]["idx"])
544 extra_idx_in3
= property(lambda self
: self
.extras
["in3"]["idx"])
545 extra_idx_out
= property(lambda self
: self
.extras
["out"]["idx"])
546 extra_idx_out2
= property(lambda self
: self
.extras
["out2"]["idx"])
547 extra_idx_cr_in
= property(lambda self
: self
.extras
["cr_in"]["idx"])
548 extra_idx_cr_in2
= property(lambda self
: self
.extras
["cr_in2"]["idx"])
549 extra_idx_cr_out
= property(lambda self
: self
.extras
["cr_out"]["idx"])
554 for idx
in range(0, 4):
555 for entry
in self
.extra
[idx
]:
556 if entry
.seltype
is _SelType
.DST
:
557 if extra
is not None:
558 raise ValueError(self
.svp64
)
562 if _RegType(extra
.reg
) not in (_RegType
.CR_3BIT
, _RegType
.CR_5BIT
):
563 raise ValueError(self
.svp64
)
568 def extra_CR_3bit(self
):
569 return (_RegType(self
.extra_CR
.reg
) is _RegType
.CR_3BIT
)
573 def __init__(self
, value
=(0, 32)):
574 if isinstance(value
, str):
575 (start
, end
) = map(int, value
.split(":"))
578 if start
< 0 or end
< 0 or start
>= end
:
579 raise ValueError(value
)
584 return super().__init
__()
587 return (self
.__end
- self
.__start
+ 1)
590 return f
"[{self.__start}:{self.__end}]"
593 yield from range(self
.start
, (self
.end
+ 1))
595 def __reversed__(self
):
596 return tuple(reversed(tuple(self
)))
607 class Section(Dataclass
):
608 class Mode(_enum
.Enum
):
609 INTEGER
= _enum
.auto()
610 PATTERN
= _enum
.auto()
613 def _missing_(cls
, value
):
614 if isinstance(value
, str):
615 return cls
[value
.upper()]
616 return super()._missing
_(value
)
619 def __new__(cls
, value
=None):
620 if isinstance(value
, str):
621 if value
.upper() == "NONE":
624 value
= int(value
, 0)
628 return super().__new
__(cls
, value
)
634 return (bin(self
) if self
else "None")
640 opcode
: IntegerOpcode
= None
641 priority
: Priority
= Priority
.NORMAL
643 def __lt__(self
, other
):
644 if not isinstance(other
, self
.__class
__):
645 return NotImplemented
646 return (self
.priority
< other
.priority
)
649 def CSV(cls
, record
):
650 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
651 if record
["opcode"] == "NONE":
652 typemap
["opcode"] = lambda _
: None
654 return dataclass(cls
, record
, typemap
=typemap
)
658 def __init__(self
, items
):
659 if isinstance(items
, dict):
660 items
= items
.items()
663 (name
, bitrange
) = item
664 return (name
, tuple(bitrange
.values()))
666 self
.__mapping
= dict(map(transform
, items
))
668 return super().__init
__()
671 return repr(self
.__mapping
)
674 yield from self
.__mapping
.items()
676 def __contains__(self
, key
):
677 return self
.__mapping
.__contains
__(key
)
679 def __getitem__(self
, key
):
680 return self
.__mapping
.get(key
, None)
695 def __init__(self
, insn
, operands
):
697 "b": {"target_addr": TargetAddrOperandLI
},
698 "ba": {"target_addr": TargetAddrOperandLI
},
699 "bl": {"target_addr": TargetAddrOperandLI
},
700 "bla": {"target_addr": TargetAddrOperandLI
},
701 "bc": {"target_addr": TargetAddrOperandBD
},
702 "bca": {"target_addr": TargetAddrOperandBD
},
703 "bcl": {"target_addr": TargetAddrOperandBD
},
704 "bcla": {"target_addr": TargetAddrOperandBD
},
705 "addpcis": {"D": DOperandDX
},
706 "fishmv": {"D": DOperandDX
},
707 "fmvis": {"D": DOperandDX
},
710 "SVi": NonZeroOperand
,
711 "SVd": NonZeroOperand
,
712 "SVxd": NonZeroOperand
,
713 "SVyd": NonZeroOperand
,
714 "SVzd": NonZeroOperand
,
716 "D": SignedImmediateOperand
,
720 "SIM": SignedOperand
,
721 "SVD": SignedOperand
,
722 "SVDS": SignedOperand
,
723 "RSp": GPRPairOperand
,
724 "RTp": GPRPairOperand
,
725 "FRAp": FPRPairOperand
,
726 "FRBp": FPRPairOperand
,
727 "FRSp": FPRPairOperand
,
728 "FRTp": FPRPairOperand
,
730 custom_immediates
= {
736 for operand
in operands
:
740 (name
, value
) = operand
.split("=")
741 mapping
[name
] = (StaticOperand
, {
747 if name
.endswith(")"):
748 name
= name
.replace("(", " ").replace(")", "")
749 (imm_name
, _
, name
) = name
.partition(" ")
753 if imm_name
is not None:
754 imm_cls
= custom_immediates
.get(imm_name
, ImmediateOperand
)
756 if insn
in custom_insns
and name
in custom_insns
[insn
]:
757 cls
= custom_insns
[insn
][name
]
758 elif name
in custom_fields
:
759 cls
= custom_fields
[name
]
760 elif name
in _Reg
.__members
__:
762 if reg
in self
.__class
__.__GPR
_PAIRS
:
764 elif reg
in self
.__class
__.__FPR
_PAIRS
:
767 regtype
= _RegType
[name
]
768 if regtype
is _RegType
.GPR
:
770 elif regtype
is _RegType
.FPR
:
772 elif regtype
is _RegType
.CR_3BIT
:
774 elif regtype
is _RegType
.CR_5BIT
:
777 if imm_name
is not None:
778 mapping
[imm_name
] = (imm_cls
, {"name": imm_name
})
779 mapping
[name
] = (cls
, {"name": name
})
783 for (name
, (cls
, kwargs
)) in mapping
.items():
784 kwargs
= dict(kwargs
)
785 kwargs
["name"] = name
786 if issubclass(cls
, StaticOperand
):
787 static
.append((cls
, kwargs
))
788 elif issubclass(cls
, DynamicOperand
):
789 dynamic
.append((cls
, kwargs
))
791 raise ValueError(name
)
793 self
.__mapping
= mapping
794 self
.__static
= tuple(static
)
795 self
.__dynamic
= tuple(dynamic
)
797 return super().__init
__()
800 for (_
, items
) in self
.__mapping
.items():
801 (cls
, kwargs
) = items
805 return self
.__mapping
.__repr
__()
807 def __contains__(self
, key
):
808 return self
.__mapping
.__contains
__(key
)
810 def __getitem__(self
, key
):
811 return self
.__mapping
.__getitem
__(key
)
819 return self
.__dynamic
822 class Arguments(tuple):
823 def __new__(cls
, record
, arguments
, operands
):
824 operands
= iter(tuple(operands
))
825 arguments
= iter(tuple(arguments
))
830 operand
= next(operands
)
831 except StopIteration:
835 argument
= next(arguments
)
836 except StopIteration:
837 raise ValueError("operands count mismatch")
839 if isinstance(operand
, ImmediateOperand
):
840 argument
= argument
.replace("(", " ").replace(")", "")
841 (imm_argument
, _
, argument
) = argument
.partition(" ")
843 (imm_operand
, operand
) = (operand
, next(operands
))
844 except StopIteration:
845 raise ValueError("operands count mismatch")
846 items
.append((imm_argument
, imm_operand
))
847 items
.append((argument
, operand
))
851 except StopIteration:
854 raise ValueError("operands count mismatch")
856 return super().__new
__(cls
, items
)
860 def __init__(self
, iterable
):
861 self
.__pcode
= tuple(iterable
)
862 return super().__init
__()
865 yield from self
.__pcode
868 return self
.__pcode
.__repr
__()
871 class MarkdownRecord(Dataclass
):
876 class Extra(Dataclass
):
879 _In1Sel
, _In2Sel
, _In3Sel
, _CRInSel
, _CRIn2Sel
,
887 @_functools.total_ordering
888 class Record(Dataclass
):
894 svp64
: SVP64Record
= None
898 if self
.svp64
is not None:
899 return self
.svp64
.extras
901 return _types
.MappingProxyType({})
905 return self
.mdwn
.pcode
907 def __lt__(self
, other
):
908 if not isinstance(other
, Record
):
909 return NotImplemented
910 lhs
= (min(self
.opcodes
), self
.name
)
911 rhs
= (min(other
.opcodes
), other
.name
)
916 return (self
.static_operands
+ self
.dynamic_operands
)
919 def static_operands(self
):
921 operands
.append(POStaticOperand(record
=self
, value
=self
.PO
))
923 operands
.append(XOStaticOperand(
925 value
=ppc
.opcode
.value
,
926 span
=self
.section
.bitsel
,
928 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
929 operands
.append(cls(record
=self
, **kwargs
))
930 return tuple(operands
)
933 def dynamic_operands(self
):
935 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
936 operands
.append(cls(record
=self
, **kwargs
))
937 return tuple(operands
)
942 return int("".join(str(int(mapping
[bit
])) \
943 for bit
in sorted(mapping
)), 2)
945 def PO_XO(value
, mask
, opcode
, bits
):
948 for (src
, dst
) in enumerate(reversed(bits
)):
949 value
[dst
] = ((opcode
.value
& (1 << src
)) != 0)
950 mask
[dst
] = ((opcode
.mask
& (1 << src
)) != 0)
953 def PO(value
, mask
, opcode
, bits
):
954 return PO_XO(value
=value
, mask
=mask
, opcode
=opcode
, bits
=bits
)
956 def XO(value
, mask
, opcode
, bits
):
957 (value
, mask
) = PO_XO(value
=value
, mask
=mask
,
958 opcode
=opcode
, bits
=bits
)
959 for (op_cls
, op_kwargs
) in self
.mdwn
.operands
.static
:
960 operand
= op_cls(record
=self
, **op_kwargs
)
961 for (src
, dst
) in enumerate(reversed(operand
.span
)):
962 value
[dst
] = ((operand
.value
& (1 << src
)) != 0)
967 value
= {bit
:False for bit
in range(32)}
968 mask
= {bit
:False for bit
in range(32)}
969 if self
.section
.opcode
is not None:
970 (value
, mask
) = PO(value
=value
, mask
=mask
,
971 opcode
=self
.section
.opcode
, bits
=range(0, 6))
973 pairs
.append(XO(value
=value
, mask
=mask
,
974 opcode
=ppc
.opcode
, bits
=self
.section
.bitsel
))
977 for (value
, mask
) in pairs
:
978 value
= Opcode
.Value(binary(value
))
979 mask
= Opcode
.Mask(binary(mask
))
980 result
.append(Opcode(value
=value
, mask
=mask
))
986 opcode
= self
.section
.opcode
988 opcode
= self
.ppc
[0].opcode
989 if isinstance(opcode
, PatternOpcode
):
990 value
= int(opcode
.value
)
991 bits
= opcode
.value
.bit_length()
992 return int(_SelectableInt(value
=value
, bits
=bits
)[0:6])
994 return int(opcode
.value
)
998 return tuple(ppc
.opcode
for ppc
in self
.ppc
)
1000 def match(self
, key
):
1001 for opcode
in self
.opcodes
:
1002 if opcode
.match(key
):
1009 return self
.svp64
.mode
1029 if self
.svp64
is None:
1035 return self
.ppc
.cr_in
1039 return self
.ppc
.cr_in2
1043 return self
.ppc
.cr_out
1045 ptype
= property(lambda self
: self
.svp64
.ptype
)
1046 etype
= property(lambda self
: self
.svp64
.etype
)
1048 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
1049 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
1050 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
1051 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
1052 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
1053 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
1054 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
1055 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
1057 def __contains__(self
, key
):
1058 return self
.mdwn
.operands
.__contains
__(key
)
1060 def __getitem__(self
, key
):
1061 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
1062 return cls(record
=self
, **kwargs
)
1066 if "Rc" not in self
:
1068 return self
["Rc"].value
1072 def __init__(self
, record
, name
):
1073 self
.__record
= record
1077 yield ("record", self
.record
)
1078 yield ("name", self
.__name
)
1081 return f
"{self.__class__.__name__}({self.name})"
1089 return self
.__record
1093 return self
.record
.fields
[self
.name
]
1095 def assemble(self
, insn
):
1096 raise NotImplementedError()
1098 def disassemble(self
, insn
,
1099 style
=Style
.NORMAL
, indent
=""):
1100 raise NotImplementedError()
1103 class DynamicOperand(Operand
):
1104 def assemble(self
, insn
, value
):
1106 if isinstance(value
, str):
1107 value
= int(value
, 0)
1109 raise ValueError("signed operands not allowed")
1112 def disassemble(self
, insn
,
1113 style
=Style
.NORMAL
, indent
=""):
1117 if style
>= Style
.VERBOSE
:
1118 span
= map(str, span
)
1119 yield f
"{indent}{self.name}"
1120 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1121 yield f
"{indent}{indent}{', '.join(span)}"
1123 yield str(int(value
))
1126 class SignedOperand(DynamicOperand
):
1127 def assemble(self
, insn
, value
):
1128 if isinstance(value
, str):
1129 value
= int(value
, 0)
1130 return super().assemble(value
=value
, insn
=insn
)
1132 def assemble(self
, insn
, value
):
1134 if isinstance(value
, str):
1135 value
= int(value
, 0)
1138 def disassemble(self
, insn
,
1139 style
=Style
.NORMAL
, indent
=""):
1141 value
= insn
[span
].to_signed_int()
1142 sign
= "-" if (value
< 0) else ""
1145 if style
>= Style
.VERBOSE
:
1146 span
= map(str, span
)
1147 yield f
"{indent}{self.name}"
1148 yield f
"{indent}{indent}{sign}{value}"
1149 yield f
"{indent}{indent}{', '.join(span)}"
1151 yield f
"{sign}{value}"
1154 class StaticOperand(Operand
):
1155 def __init__(self
, record
, name
, value
):
1156 self
.__value
= value
1157 return super().__init
__(record
=record
, name
=name
)
1160 yield ("value", self
.__value
)
1161 yield from super().__iter
__()
1164 return f
"{self.__class__.__name__}({self.name}, value={self.value})"
1170 def assemble(self
, insn
):
1171 insn
[self
.span
] = self
.value
1173 def disassemble(self
, insn
,
1174 style
=Style
.NORMAL
, indent
=""):
1178 if style
>= Style
.VERBOSE
:
1179 span
= map(str, span
)
1180 yield f
"{indent}{self.name}"
1181 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1182 yield f
"{indent}{indent}{', '.join(span)}"
1184 yield str(int(value
))
1187 class SpanStaticOperand(StaticOperand
):
1188 def __init__(self
, record
, name
, value
, span
):
1189 self
.__span
= tuple(span
)
1190 return super().__init
__(record
=record
, name
=name
, value
=value
)
1193 yield ("span", self
.__span
)
1194 yield from super().__iter
__()
1201 class POStaticOperand(SpanStaticOperand
):
1202 def __init__(self
, record
, value
):
1203 return super().__init
__(record
=record
, name
="PO",
1204 value
=value
, span
=range(0, 6))
1207 for (key
, value
) in super().__iter
__():
1208 if key
not in {"name", "span"}:
1212 class XOStaticOperand(SpanStaticOperand
):
1213 def __init__(self
, record
, value
, span
):
1214 bits
= record
.section
.bitsel
1215 value
= _SelectableInt(value
=value
, bits
=len(bits
))
1216 span
= dict(zip(bits
, range(len(bits
))))
1217 span_rev
= {value
:key
for (key
, value
) in span
.items()}
1219 # This part is tricky: we cannot use record.operands,
1220 # as this code is called by record.static_operands method.
1221 for (cls
, kwargs
) in record
.mdwn
.operands
:
1222 operand
= cls(record
=record
, **kwargs
)
1223 for idx
in operand
.span
:
1224 rev
= span
.pop(idx
, None)
1226 span_rev
.pop(rev
, None)
1228 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1229 span
= tuple(span
.keys())
1231 return super().__init
__(record
=record
, name
="XO",
1232 value
=value
, span
=span
)
1235 for (key
, value
) in super().__iter
__():
1236 if key
not in {"name"}:
1240 class ImmediateOperand(DynamicOperand
):
1244 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1248 class NonZeroOperand(DynamicOperand
):
1249 def assemble(self
, insn
, value
):
1250 if isinstance(value
, str):
1251 value
= int(value
, 0)
1252 if not isinstance(value
, int):
1253 raise ValueError("non-integer operand")
1255 raise ValueError("non-zero operand")
1257 return super().assemble(value
=value
, insn
=insn
)
1259 def disassemble(self
, insn
,
1260 style
=Style
.NORMAL
, indent
=""):
1264 if style
>= Style
.VERBOSE
:
1265 span
= map(str, span
)
1266 yield f
"{indent}{self.name}"
1267 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1268 yield f
"{indent}{indent}{', '.join(span)}"
1270 yield str(int(value
) + 1)
1273 class ExtendableOperand(DynamicOperand
):
1274 def sv_spec_enter(self
, value
, span
):
1275 return (value
, span
)
1277 def sv_spec(self
, insn
):
1281 span
= tuple(map(str, span
))
1283 if isinstance(insn
, SVP64Instruction
):
1284 (origin_value
, origin_span
) = (value
, span
)
1285 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1287 for extra_idx
in self
.extra_idx
:
1288 if self
.record
.etype
is _SVEType
.EXTRA3
:
1289 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1290 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1291 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1293 raise ValueError(self
.record
.etype
)
1296 vector
= bool(spec
[0])
1297 spec_span
= spec
.__class
__
1298 if self
.record
.etype
is _SVEType
.EXTRA3
:
1299 spec_span
= tuple(map(str, spec_span
[1, 2]))
1301 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1302 spec_span
= tuple(map(str, spec_span
[1,]))
1303 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1306 spec_span
= (spec_span
+ ("{0}",))
1308 spec_span
= (("{0}",) + spec_span
)
1310 raise ValueError(self
.record
.etype
)
1312 vector_shift
= (2 + (5 - value
.bits
))
1313 scalar_shift
= value
.bits
1314 spec_shift
= (5 - value
.bits
)
1316 bits
= (len(span
) + len(spec_span
))
1317 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1318 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1320 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1321 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1323 value
= ((spec
<< scalar_shift
) | value
)
1324 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1326 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1327 origin_value
=origin_value
, origin_span
=origin_span
)
1329 return (vector
, value
, span
)
1331 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1332 return (value
, span
)
1335 def extra_idx(self
):
1336 for (key
, record
) in self
.record
.svp64
.extras
.items():
1337 if record
["reg"].alias
is self
.extra_reg
.alias
:
1341 def extra_reg(self
):
1342 return _Reg(self
.name
)
1344 def remap(self
, value
, vector
):
1345 raise NotImplementedError()
1347 def assemble(self
, value
, insn
, prefix
):
1350 if isinstance(value
, str):
1351 value
= value
.lower()
1352 if value
.startswith("%"):
1354 if value
.startswith("*"):
1355 if not isinstance(insn
, SVP64Instruction
):
1356 raise ValueError(value
)
1359 if value
.startswith(prefix
):
1360 if (self
.extra_reg
.or_zero
and (value
== f
"{prefix}0")):
1361 raise ValueError(value
)
1362 value
= value
[len(prefix
):]
1363 value
= int(value
, 0)
1365 if isinstance(insn
, SVP64Instruction
):
1366 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1368 for extra_idx
in self
.extra_idx
:
1369 if self
.record
.etype
is _SVEType
.EXTRA3
:
1370 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1371 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1372 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1374 raise ValueError(self
.record
.etype
)
1376 return super().assemble(value
=value
, insn
=insn
)
1378 def disassemble(self
, insn
,
1379 style
=Style
.NORMAL
, prefix
="", indent
=""):
1380 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1382 if (self
.extra_reg
.or_zero
and (value
== 0)):
1385 if style
>= Style
.VERBOSE
:
1386 mode
= "vector" if vector
else "scalar"
1387 yield f
"{indent}{self.name} ({mode})"
1388 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1389 yield f
"{indent}{indent}{', '.join(span)}"
1390 if isinstance(insn
, SVP64Instruction
):
1391 for extra_idx
in frozenset(self
.extra_idx
):
1392 if self
.record
.etype
is _SVEType
.NONE
:
1393 yield f
"{indent}{indent}extra[none]"
1395 etype
= repr(self
.record
.etype
).lower()
1396 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1398 vector
= "*" if vector
else ""
1399 yield f
"{vector}{prefix}{int(value)}"
1402 class SimpleRegisterOperand(ExtendableOperand
):
1403 def remap(self
, value
, vector
):
1405 extra
= (value
& 0b11)
1406 value
= (value
>> 2)
1408 extra
= (value
>> 5)
1409 value
= (value
& 0b11111)
1411 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1412 # (and shrink to a single bit if ok)
1413 if self
.record
.etype
is _SVEType
.EXTRA2
:
1415 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1416 assert (extra
& 0b01) == 0, \
1417 ("vector field %s cannot fit into EXTRA2" % value
)
1418 extra
= (0b10 |
(extra
>> 1))
1420 # range is r0-r63 in increments of 1
1421 assert (extra
>> 1) == 0, \
1422 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1424 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1426 # EXTRA3 vector bit needs marking
1429 raise ValueError(self
.record
.etype
)
1431 return (value
, extra
)
1434 class GPROperand(SimpleRegisterOperand
):
1435 def assemble(self
, insn
, value
):
1436 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1438 def disassemble(self
, insn
,
1439 style
=Style
.NORMAL
, indent
=""):
1440 prefix
= "" if (style
<= Style
.SHORT
) else "r"
1441 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1442 style
=style
, indent
=indent
)
1445 class GPRPairOperand(GPROperand
):
1449 class FPROperand(SimpleRegisterOperand
):
1450 def assemble(self
, insn
, value
):
1451 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1453 def disassemble(self
, insn
,
1454 style
=Style
.NORMAL
, indent
=""):
1455 prefix
= "" if (style
<= Style
.SHORT
) else "f"
1456 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1457 style
=style
, indent
=indent
)
1460 class FPRPairOperand(FPROperand
):
1464 class ConditionRegisterFieldOperand(ExtendableOperand
):
1465 def pattern(name_pattern
):
1466 (name
, pattern
) = name_pattern
1467 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1476 CR
= r
"(?:CR|cr)([0-9]+)"
1478 BIT
= rf
"({'|'.join(CONDS.keys())})"
1479 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1480 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1481 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1482 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1483 XCR
= fr
"{CR}\.{BIT}"
1484 PATTERNS
= tuple(map(pattern
, (
1489 ("BIT+CR", (LBIT
+ CR
)),
1490 ("CR+BIT", (CR
+ RBIT
)),
1491 ("BIT+CR*N", (LBIT
+ CRN
)),
1492 ("CR*N+BIT", (CRN
+ RBIT
)),
1493 ("BIT+N*CR", (LBIT
+ NCR
)),
1494 ("N*CR+BIT", (NCR
+ RBIT
)),
1497 def remap(self
, value
, vector
, regtype
):
1498 if regtype
is _RegType
.CR_5BIT
:
1499 subvalue
= (value
& 0b11)
1503 extra
= (value
& 0b1111)
1506 extra
= (value
>> 3)
1509 if self
.record
.etype
is _SVEType
.EXTRA2
:
1511 assert (extra
& 0b111) == 0, \
1512 "vector CR cannot fit into EXTRA2"
1513 extra
= (0b10 |
(extra
>> 3))
1515 assert (extra
>> 1) == 0, \
1516 "scalar CR cannot fit into EXTRA2"
1518 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1520 assert (extra
& 0b11) == 0, \
1521 "vector CR cannot fit into EXTRA3"
1522 extra
= (0b100 |
(extra
>> 2))
1524 assert (extra
>> 2) == 0, \
1525 "scalar CR cannot fit into EXTRA3"
1528 if regtype
is _RegType
.CR_5BIT
:
1529 value
= ((value
<< 2) | subvalue
)
1531 return (value
, extra
)
1533 def assemble(self
, insn
, value
):
1534 if isinstance(value
, str):
1537 if value
.startswith("*"):
1538 if not isinstance(insn
, SVP64Instruction
):
1539 raise ValueError(value
)
1543 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1544 match
= pattern
.match(value
)
1545 if match
is not None:
1546 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1547 values
= match
.groups()
1548 match
= dict(zip(keys
, values
))
1549 CR
= int(match
["CR"])
1553 N
= int(match
.get("N", "1"))
1554 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1555 value
= ((CR
* N
) + BIT
)
1562 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1564 def disassemble(self
, insn
,
1565 style
=Style
.NORMAL
, prefix
="", indent
=""):
1566 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1568 if style
>= Style
.VERBOSE
:
1569 mode
= "vector" if vector
else "scalar"
1570 yield f
"{indent}{self.name} ({mode})"
1571 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1572 yield f
"{indent}{indent}{', '.join(span)}"
1573 if isinstance(insn
, SVP64Instruction
):
1574 for extra_idx
in frozenset(self
.extra_idx
):
1575 if self
.record
.etype
is _SVEType
.NONE
:
1576 yield f
"{indent}{indent}extra[none]"
1578 etype
= repr(self
.record
.etype
).lower()
1579 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1581 vector
= "*" if vector
else ""
1582 CR
= int(value
>> 2)
1584 cond
= ("lt", "gt", "eq", "so")[CC
]
1585 if style
>= Style
.NORMAL
:
1587 if isinstance(insn
, SVP64Instruction
):
1588 yield f
"{vector}cr{CR}.{cond}"
1590 yield f
"4*cr{CR}+{cond}"
1594 yield f
"{vector}{prefix}{int(value)}"
1597 class CR3Operand(ConditionRegisterFieldOperand
):
1598 def remap(self
, value
, vector
):
1599 return super().remap(value
=value
, vector
=vector
,
1600 regtype
=_RegType
.CR_3BIT
)
1603 class CR5Operand(ConditionRegisterFieldOperand
):
1604 def remap(self
, value
, vector
):
1605 return super().remap(value
=value
, vector
=vector
,
1606 regtype
=_RegType
.CR_5BIT
)
1608 def sv_spec_enter(self
, value
, span
):
1609 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1610 return (value
, span
)
1612 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1613 value
= _selectconcat(value
, origin_value
[3:5])
1615 return (value
, span
)
1618 class EXTSOperand(SignedOperand
):
1619 field
: str # real name to report
1620 nz
: int = 0 # number of zeros
1621 fmt
: str = "d" # integer formatter
1623 def __init__(self
, record
, name
, field
, nz
=0, fmt
="d"):
1624 self
.__field
= field
1627 return super().__init
__(record
=record
, name
=name
)
1643 return self
.record
.fields
[self
.field
]
1645 def assemble(self
, insn
, value
):
1647 if isinstance(value
, str):
1648 value
= int(value
, 0)
1649 insn
[span
] = (value
>> self
.nz
)
1651 def disassemble(self
, insn
,
1652 style
=Style
.NORMAL
, indent
=""):
1654 value
= insn
[span
].to_signed_int()
1655 sign
= "-" if (value
< 0) else ""
1656 value
= (abs(value
) << self
.nz
)
1658 if style
>= Style
.VERBOSE
:
1659 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1660 zeros
= ("0" * self
.nz
)
1661 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1662 yield f
"{indent * 1}{hint}"
1663 yield f
"{indent * 2}{self.field}"
1664 yield f
"{indent * 3}{sign}{value:{self.fmt}}"
1665 yield f
"{indent * 3}{', '.join(span)}"
1667 yield f
"{sign}{value:{self.fmt}}"
1670 class TargetAddrOperand(EXTSOperand
):
1671 def __init__(self
, record
, name
, field
):
1672 return super().__init
__(record
=record
, name
=name
, field
=field
,
1676 class TargetAddrOperandLI(TargetAddrOperand
):
1677 def __init__(self
, record
, name
):
1678 return super().__init
__(record
=record
, name
=name
, field
="LI")
1681 class TargetAddrOperandBD(TargetAddrOperand
):
1682 def __init__(self
, record
, name
):
1683 return super().__init
__(record
=record
, name
=name
, field
="BD")
1686 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1687 def __init__(self
, record
, name
):
1688 return super().__init
__(record
=record
, name
=name
, field
="DS", nz
=2)
1691 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1692 def __init__(self
, record
, name
):
1693 return super().__init
__(record
=record
, name
=name
, field
="DQ", nz
=4)
1696 class DOperandDX(SignedOperand
):
1699 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1700 operands
= map(cls
, ("d0", "d1", "d2"))
1701 spans
= map(lambda operand
: operand
.span
, operands
)
1702 return sum(spans
, tuple())
1704 def disassemble(self
, insn
,
1705 style
=Style
.NORMAL
, indent
=""):
1707 value
= insn
[span
].to_signed_int()
1708 sign
= "-" if (value
< 0) else ""
1711 if style
>= Style
.VERBOSE
:
1718 for (subname
, subspan
) in mapping
.items():
1719 operand
= DynamicOperand(name
=subname
)
1721 span
= map(str, span
)
1722 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1723 yield f
"{indent}{indent}{indent}{sign}{value}"
1724 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1726 yield f
"{sign}{value}"
1729 class Instruction(_Mapping
):
1731 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1732 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1733 raise ValueError(bits
)
1735 if isinstance(value
, bytes
):
1736 if ((len(value
) * 8) != bits
):
1737 raise ValueError(f
"bit length mismatch")
1738 value
= int.from_bytes(value
, byteorder
=byteorder
)
1740 if isinstance(value
, int):
1741 value
= _SelectableInt(value
=value
, bits
=bits
)
1742 elif isinstance(value
, Instruction
):
1743 value
= value
.storage
1745 if not isinstance(value
, _SelectableInt
):
1746 raise ValueError(value
)
1749 if len(value
) != bits
:
1750 raise ValueError(value
)
1752 value
= _SelectableInt(value
=value
, bits
=bits
)
1754 return cls(storage
=value
)
1757 return hash(int(self
))
1759 def __getitem__(self
, key
):
1760 return self
.storage
.__getitem
__(key
)
1762 def __setitem__(self
, key
, value
):
1763 return self
.storage
.__setitem
__(key
, value
)
1765 def bytes(self
, byteorder
="little"):
1766 nr_bytes
= (len(self
.__class
__) // 8)
1767 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1770 def record(cls
, db
, entry
):
1773 raise KeyError(entry
)
1777 def operands(cls
, record
):
1778 yield from record
.operands
1781 def static_operands(cls
, record
):
1782 return filter(lambda operand
: isinstance(operand
, StaticOperand
),
1783 cls
.operands(record
=record
))
1786 def dynamic_operands(cls
, record
):
1787 return filter(lambda operand
: isinstance(operand
, DynamicOperand
),
1788 cls
.operands(record
=record
))
1790 def spec(self
, record
, prefix
):
1791 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1792 self
.spec_dynamic_operands(record
=record
)))
1794 static_operands
= []
1795 for (name
, value
) in self
.spec_static_operands(record
=record
):
1796 static_operands
.append(f
"{name}={value}")
1799 if dynamic_operands
:
1801 operands
+= ",".join(dynamic_operands
)
1804 operands
+= " ".join(static_operands
)
1806 return f
"{prefix}{record.name}{operands}"
1808 def spec_static_operands(self
, record
):
1809 for operand
in self
.static_operands(record
=record
):
1810 if not isinstance(operand
, (POStaticOperand
, XOStaticOperand
)):
1811 yield (operand
.name
, operand
.value
)
1813 def spec_dynamic_operands(self
, record
, style
=Style
.NORMAL
):
1817 for operand
in self
.dynamic_operands(record
=record
):
1819 value
= " ".join(operand
.disassemble(insn
=self
,
1820 style
=min(style
, Style
.NORMAL
)))
1822 name
= f
"{imm_name}({name})"
1823 value
= f
"{imm_value}({value})"
1825 if isinstance(operand
, ImmediateOperand
):
1833 def assemble(cls
, record
, arguments
=None):
1834 if arguments
is None:
1837 insn
= cls
.integer(value
=0)
1839 for operand
in cls
.static_operands(record
=record
):
1840 operand
.assemble(insn
=insn
)
1842 arguments
= Arguments(record
=record
,
1843 arguments
=arguments
, operands
=cls
.dynamic_operands(record
=record
))
1844 for (value
, operand
) in arguments
:
1845 operand
.assemble(insn
=insn
, value
=value
)
1849 def disassemble(self
, record
,
1851 style
=Style
.NORMAL
):
1852 raise NotImplementedError()
1855 class WordInstruction(Instruction
):
1856 _
: _Field
= range(0, 32)
1857 PO
: _Field
= range(0, 6)
1860 def integer(cls
, value
, byteorder
="little"):
1861 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1866 for idx
in range(32):
1867 bit
= int(self
[idx
])
1869 return "".join(map(str, bits
))
1871 def disassemble(self
, record
,
1873 style
=Style
.NORMAL
):
1874 if style
<= Style
.SHORT
:
1877 blob
= self
.bytes(byteorder
=byteorder
)
1878 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1882 yield f
"{blob}.long 0x{int(self):08x}"
1885 # awful temporary hack: workaround for ld-update
1886 # https://bugs.libre-soc.org/show_bug.cgi?id=1056#c2
1887 # XXX TODO must check that *EXTENDED* RA != extended-RT
1888 if (record
.svp64
is not None and
1889 record
.mode
== _SVMode
.LDST_IMM
and
1890 'u' in record
.name
):
1891 yield f
"{blob}.long 0x{int(self):08x}"
1895 if style
is Style
.LEGACY
:
1897 for operand
in self
.dynamic_operands(record
=record
):
1898 if isinstance(operand
, (GPRPairOperand
, FPRPairOperand
)):
1901 if style
is Style
.LEGACY
and (paired
or record
.ppc
.unofficial
):
1902 yield f
"{blob}.long 0x{int(self):08x}"
1904 operands
= tuple(map(_operator
.itemgetter(1),
1905 self
.spec_dynamic_operands(record
=record
, style
=style
)))
1907 operands
= ",".join(operands
)
1908 yield f
"{blob}{record.name} {operands}"
1910 yield f
"{blob}{record.name}"
1912 if style
>= Style
.VERBOSE
:
1914 binary
= self
.binary
1915 spec
= self
.spec(record
=record
, prefix
="")
1916 yield f
"{indent}spec"
1917 yield f
"{indent}{indent}{spec}"
1918 yield f
"{indent}pcode"
1919 for stmt
in record
.mdwn
.pcode
:
1920 yield f
"{indent}{indent}{stmt}"
1921 yield f
"{indent}binary"
1922 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1923 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1924 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1925 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1926 yield f
"{indent}opcodes"
1927 for opcode
in record
.opcodes
:
1928 yield f
"{indent}{indent}{opcode!r}"
1929 for operand
in self
.operands(record
=record
):
1930 yield from operand
.disassemble(insn
=self
,
1931 style
=style
, indent
=indent
)
1935 class PrefixedInstruction(Instruction
):
1936 class Prefix(WordInstruction
.remap(range(0, 32))):
1939 class Suffix(WordInstruction
.remap(range(32, 64))):
1942 _
: _Field
= range(64)
1948 def integer(cls
, value
, byteorder
="little"):
1949 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
1952 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
1953 def transform(value
):
1954 return WordInstruction
.integer(value
=value
,
1955 byteorder
=byteorder
)[0:32]
1957 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
1958 value
= _selectconcat(prefix
, suffix
)
1960 return super().integer(bits
=64, value
=value
)
1963 class Mode(_Mapping
):
1964 _
: _Field
= range(0, 5)
1965 sel
: _Field
= (0, 1)
1968 class ExtraRM(_Mapping
):
1969 _
: _Field
= range(0, 9)
1972 class Extra2RM(ExtraRM
):
1973 idx0
: _Field
= range(0, 2)
1974 idx1
: _Field
= range(2, 4)
1975 idx2
: _Field
= range(4, 6)
1976 idx3
: _Field
= range(6, 8)
1978 def __getitem__(self
, key
):
1984 _SVExtra
.Idx0
: self
.idx0
,
1985 _SVExtra
.Idx1
: self
.idx1
,
1986 _SVExtra
.Idx2
: self
.idx2
,
1987 _SVExtra
.Idx3
: self
.idx3
,
1990 def __setitem__(self
, key
, value
):
1991 self
[key
].assign(value
)
1994 class Extra3RM(ExtraRM
):
1995 idx0
: _Field
= range(0, 3)
1996 idx1
: _Field
= range(3, 6)
1997 idx2
: _Field
= range(6, 9)
1999 def __getitem__(self
, key
):
2004 _SVExtra
.Idx0
: self
.idx0
,
2005 _SVExtra
.Idx1
: self
.idx1
,
2006 _SVExtra
.Idx2
: self
.idx2
,
2009 def __setitem__(self
, key
, value
):
2010 self
[key
].assign(value
)
2013 class BaseRM(_Mapping
):
2014 _
: _Field
= range(24)
2015 mmode
: _Field
= (0,)
2016 mask
: _Field
= range(1, 4)
2017 elwidth
: _Field
= range(4, 6)
2018 ewsrc
: _Field
= range(6, 8)
2019 subvl
: _Field
= range(8, 10)
2020 mode
: Mode
.remap(range(19, 24))
2021 smask_extra322
: _Field
= (6,7,18,) # LDST_IDX is EXTRA332
2022 smask
: _Field
= range(16, 19) # everything else use this
2023 extra
: ExtraRM
.remap(range(10, 19))
2024 extra2
: Extra2RM
.remap(range(10, 19))
2025 extra3
: Extra3RM
.remap(range(10, 19))
2026 # XXX extra332 = (extra3[0], extra3[1], extra2[3])
2028 def specifiers(self
, record
):
2029 subvl
= int(self
.subvl
)
2037 def disassemble(self
, style
=Style
.NORMAL
):
2038 if style
>= Style
.VERBOSE
:
2040 for (name
, span
) in self
.traverse(path
="RM"):
2041 value
= self
.storage
[span
]
2043 yield f
"{indent}{int(value):0{value.bits}b}"
2044 yield f
"{indent}{', '.join(map(str, span))}"
2047 class FFRc1BaseRM(BaseRM
):
2048 def specifiers(self
, record
, mode
):
2049 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
2050 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
2051 mask
= int(_selectconcat(CR
, inv
))
2052 predicate
= PredicateBaseRM
.predicate(True, mask
)
2053 yield f
"{mode}={predicate}"
2055 yield from super().specifiers(record
=record
)
2058 class FFRc0BaseRM(BaseRM
):
2059 def specifiers(self
, record
, mode
):
2061 inv
= "~" if self
.inv
else ""
2062 yield f
"{mode}={inv}RC1"
2064 yield from super().specifiers(record
=record
)
2067 class SatBaseRM(BaseRM
):
2068 def specifiers(self
, record
):
2074 yield from super().specifiers(record
=record
)
2077 class ZZBaseRM(BaseRM
):
2078 def specifiers(self
, record
):
2082 yield from super().specifiers(record
=record
)
2085 class ZZCombinedBaseRM(BaseRM
):
2086 def specifiers(self
, record
):
2087 if self
.sz
and self
.dz
:
2094 yield from super().specifiers(record
=record
)
2097 class DZBaseRM(BaseRM
):
2098 def specifiers(self
, record
):
2102 yield from super().specifiers(record
=record
)
2105 class SZBaseRM(BaseRM
):
2106 def specifiers(self
, record
):
2110 yield from super().specifiers(record
=record
)
2113 class MRBaseRM(BaseRM
):
2114 def specifiers(self
, record
):
2120 yield from super().specifiers(record
=record
)
2123 class ElsBaseRM(BaseRM
):
2124 def specifiers(self
, record
):
2128 yield from super().specifiers(record
=record
)
2131 class WidthBaseRM(BaseRM
):
2133 def width(FP
, width
):
2142 width
= ("fp" + width
)
2145 def specifiers(self
, record
):
2146 # elwidths: use "w=" if same otherwise dw/sw
2147 # FIXME this should consider FP instructions
2149 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
2150 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2151 if record
.svp64
.mode
is _SVMode
.CROP
:
2155 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2164 yield from super().specifiers(record
=record
)
2167 class PredicateBaseRM(BaseRM
):
2169 def predicate(CR
, mask
):
2172 (False, 0b001): "1<<r3",
2173 (False, 0b010): "r3",
2174 (False, 0b011): "~r3",
2175 (False, 0b100): "r10",
2176 (False, 0b101): "~r10",
2177 (False, 0b110): "r30",
2178 (False, 0b111): "~r30",
2180 (True, 0b000): "lt",
2181 (True, 0b001): "ge",
2182 (True, 0b010): "gt",
2183 (True, 0b011): "le",
2184 (True, 0b100): "eq",
2185 (True, 0b101): "ne",
2186 (True, 0b110): "so",
2187 (True, 0b111): "ns",
2190 def specifiers(self
, record
):
2191 # predication - single and twin
2192 # use "m=" if same otherwise sm/dm
2193 CR
= (int(self
.mmode
) == 1)
2194 mask
= int(self
.mask
)
2195 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
2196 if record
.svp64
.ptype
is _SVPType
.P2
:
2197 # LDST_IDX smask moving to extra322 but not straight away (False)
2198 if False and record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2199 smask
= int(self
.smask_extra332
)
2201 smask
= int(self
.smask
)
2202 sm
= PredicateBaseRM
.predicate(CR
, smask
)
2211 yield from super().specifiers(record
=record
)
2214 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
2218 class SEABaseRM(BaseRM
):
2219 def specifiers(self
, record
):
2223 yield from super().specifiers(record
=record
)
2226 class VLiBaseRM(BaseRM
):
2227 def specifiers(self
, record
):
2231 yield from super().specifiers(record
=record
)
2234 class NormalBaseRM(PredicateWidthBaseRM
):
2237 https://libre-soc.org/openpower/sv/normal/
2242 class NormalSimpleRM(ZZCombinedBaseRM
, NormalBaseRM
):
2243 """normal: simple mode"""
2247 def specifiers(self
, record
):
2248 yield from super().specifiers(record
=record
)
2251 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
2252 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
2256 class NormalFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, NormalBaseRM
):
2257 """normal: Rc=1: ffirst CR sel"""
2260 CR
: BaseRM
.mode
[3, 4]
2262 def specifiers(self
, record
):
2263 yield from super().specifiers(record
=record
, mode
="ff")
2266 class NormalFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
2267 """normal: Rc=0: ffirst z/nonz"""
2272 def specifiers(self
, record
):
2273 yield from super().specifiers(record
=record
, mode
="ff")
2276 class NormalSatRM(SatBaseRM
, ZZCombinedBaseRM
, NormalBaseRM
):
2277 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2283 class NormalRM(NormalBaseRM
):
2284 simple
: NormalSimpleRM
2286 ffrc1
: NormalFFRc1RM
2287 ffrc0
: NormalFFRc0RM
2291 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2293 LD/ST Immediate mode
2294 https://libre-soc.org/openpower/sv/ldst/
2299 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2300 """ld/st immediate: simple mode"""
2301 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2302 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2308 def specifiers(self
, record
):
2314 yield from super().specifiers(record
=record
)
2317 class LDSTFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2318 """ld/st immediate&indexed: Rc=1: ffirst CR sel"""
2321 CR
: BaseRM
.mode
[3, 4]
2323 def specifiers(self
, record
):
2324 yield from super().specifiers(record
=record
, mode
="ff")
2327 class LDSTFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2328 """ld/st immediate&indexed: Rc=0: ffirst z/nonz"""
2333 def specifiers(self
, record
):
2334 yield from super().specifiers(record
=record
, mode
="ff")
2337 class LDSTImmRM(LDSTImmBaseRM
):
2338 simple
: LDSTImmSimpleRM
2343 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2346 https://libre-soc.org/openpower/sv/ldst/
2351 class LDSTIdxSimpleRM(SEABaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2352 """ld/st index: simple mode (includes element-strided and Signed-EA)"""
2353 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2360 def specifiers(self
, record
):
2366 yield from super().specifiers(record
=record
)
2369 class LDSTIdxRM(LDSTIdxBaseRM
):
2370 simple
: LDSTIdxSimpleRM
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)"""
2404 class CROpFF5RM(FFRc0BaseRM
, PredicateBaseRM
, VLiBaseRM
, DZBaseRM
,
2405 SZBaseRM
, CROpBaseRM
):
2406 """crop: ffirst 5-bit mode"""
2413 def specifiers(self
, record
):
2414 yield from super().specifiers(record
=record
, mode
="ff")
2417 # FIXME: almost everything in this class contradicts the specs (it doesn't)
2418 # The modes however are swapped: 5-bit is 3-bit, 3-bit is 5-bit
2419 class CROpFF3RM(FFRc1BaseRM
, PredicateBaseRM
, VLiBaseRM
, ZZBaseRM
, CROpBaseRM
):
2420 """cr_op: ffirst 3-bit mode"""
2426 def specifiers(self
, record
):
2427 yield from super().specifiers(record
=record
, mode
="ff")
2430 class CROpRM(CROpBaseRM
):
2431 simple
: CROpSimpleRM
2437 # ********************
2439 # https://libre-soc.org/openpower/sv/branches/
2440 class BranchBaseRM(BaseRM
):
2450 def specifiers(self
, record
):
2462 raise ValueError(self
.sz
)
2474 # Branch modes lack source mask.
2475 # Therefore a custom code is needed.
2476 CR
= (int(self
.mmode
) == 1)
2477 mask
= int(self
.mask
)
2478 m
= PredicateBaseRM
.predicate(CR
, mask
)
2482 yield from super().specifiers(record
=record
)
2485 class BranchSimpleRM(BranchBaseRM
):
2486 """branch: simple mode"""
2490 class BranchVLSRM(BranchBaseRM
):
2491 """branch: VLSET mode"""
2495 def specifiers(self
, record
):
2501 }[int(self
.VSb
), int(self
.VLi
)]
2503 yield from super().specifiers(record
=record
)
2506 class BranchCTRRM(BranchBaseRM
):
2507 """branch: CTR-test mode"""
2510 def specifiers(self
, record
):
2516 yield from super().specifiers(record
=record
)
2519 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2520 """branch: CTR-test+VLSET mode"""
2524 class BranchRM(BranchBaseRM
):
2525 simple
: BranchSimpleRM
2528 ctrvls
: BranchCTRVLSRM
2539 @_dataclasses.dataclass(eq
=True, frozen
=True)
2544 def match(cls
, desc
, record
):
2545 raise NotImplementedError()
2547 def validate(self
, others
):
2550 def assemble(self
, insn
):
2551 raise NotImplementedError()
2554 @_dataclasses.dataclass(eq
=True, frozen
=True)
2555 class SpecifierWidth(Specifier
):
2559 def match(cls
, desc
, record
, etalon
):
2560 (mode
, _
, value
) = desc
.partition("=")
2562 value
= value
.strip()
2565 width
= _SVP64Width(value
)
2567 return cls(record
=record
, width
=width
)
2570 @_dataclasses.dataclass(eq
=True, frozen
=True)
2571 class SpecifierW(SpecifierWidth
):
2573 def match(cls
, desc
, record
):
2574 return super().match(desc
=desc
, record
=record
, etalon
="w")
2576 def assemble(self
, insn
):
2577 selector
= insn
.select(record
=self
.record
)
2578 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
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 if record
.svp64
.mode
is _SVMode
.CROP
:
2589 return super().match(desc
=desc
, record
=record
, etalon
="sw")
2591 def assemble(self
, insn
):
2592 selector
= insn
.select(record
=self
.record
)
2593 selector
.ewsrc
= self
.width
.value
2596 @_dataclasses.dataclass(eq
=True, frozen
=True)
2597 class SpecifierDW(SpecifierWidth
):
2599 def match(cls
, desc
, record
):
2600 return super().match(desc
=desc
, record
=record
, etalon
="dw")
2602 def assemble(self
, insn
):
2603 selector
= insn
.select(record
=self
.record
)
2604 selector
.elwidth
= self
.width
.value
2607 @_dataclasses.dataclass(eq
=True, frozen
=True)
2608 class SpecifierSubVL(Specifier
):
2612 def match(cls
, desc
, record
):
2614 value
= _SVP64SubVL(desc
)
2618 return cls(record
=record
, value
=value
)
2620 def assemble(self
, insn
):
2621 selector
= insn
.select(record
=self
.record
)
2622 selector
.subvl
= int(self
.value
.value
)
2625 @_dataclasses.dataclass(eq
=True, frozen
=True)
2626 class SpecifierPredicate(Specifier
):
2631 def match(cls
, desc
, record
, mode_match
, pred_match
):
2632 (mode
, _
, pred
) = desc
.partition("=")
2635 if not mode_match(mode
):
2638 pred
= _SVP64Pred(pred
.strip())
2639 if not pred_match(pred
):
2640 raise ValueError(pred
)
2642 return cls(record
=record
, mode
=mode
, pred
=pred
)
2645 @_dataclasses.dataclass(eq
=True, frozen
=True)
2646 class SpecifierFF(SpecifierPredicate
):
2648 def match(cls
, desc
, record
):
2649 return super().match(desc
=desc
, record
=record
,
2650 mode_match
=lambda mode_arg
: mode_arg
== "ff",
2651 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2656 def assemble(self
, insn
):
2657 selector
= insn
.select(record
=self
.record
)
2658 if selector
.mode
.sel
!= 0:
2659 raise ValueError("cannot override mode")
2660 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2661 selector
.mode
.sel
= 0b01
2662 # HACK: please finally provide correct logic for CRs.
2663 if self
.pred
in (_SVP64Pred
.RC1
, _SVP64Pred
.RC1_N
):
2664 selector
.mode
[2] = (self
.pred
is _SVP64Pred
.RC1_N
)
2666 selector
.mode
[2] = self
.pred
.inv
2667 selector
.mode
[3, 4] = self
.pred
.state
2669 selector
.mode
.sel
= 0b01 if self
.mode
== "ff" else 0b11
2670 selector
.inv
= self
.pred
.inv
2672 selector
.CR
= self
.pred
.state
2674 selector
.RC1
= self
.pred
.state
2677 @_dataclasses.dataclass(eq
=True, frozen
=True)
2678 class SpecifierMask(SpecifierPredicate
):
2680 def match(cls
, desc
, record
, mode
):
2681 return super().match(desc
=desc
, record
=record
,
2682 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2683 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2688 def assemble(self
, insn
):
2689 raise NotImplementedError()
2692 @_dataclasses.dataclass(eq
=True, frozen
=True)
2693 class SpecifierM(SpecifierMask
):
2695 def match(cls
, desc
, record
):
2696 return super().match(desc
=desc
, record
=record
, mode
="m")
2698 def validate(self
, others
):
2700 if isinstance(spec
, SpecifierSM
):
2701 raise ValueError("source-mask and predicate mask conflict")
2702 elif isinstance(spec
, SpecifierDM
):
2703 raise ValueError("dest-mask and predicate mask conflict")
2705 def assemble(self
, insn
):
2706 selector
= insn
.select(record
=self
.record
)
2707 selector
.mask
= int(self
.pred
)
2708 if ((self
.record
.ptype
is _SVPType
.P2
) and
2709 (self
.record
.svp64
.mode
is not _SVMode
.BRANCH
)):
2710 selector
.smask
= int(self
.pred
)
2711 # LDST_IDX smask moving to extra322 but not straight away (False)
2712 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2713 selector
.smask_extra332
= int(self
.pred
)
2715 selector
.smask
= int(self
.pred
)
2717 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2720 @_dataclasses.dataclass(eq
=True, frozen
=True)
2721 class SpecifierSM(SpecifierMask
):
2723 def match(cls
, desc
, record
):
2724 return super().match(desc
=desc
, record
=record
, mode
="sm")
2726 def validate(self
, others
):
2727 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2728 raise ValueError("source-mask on non-twin predicate")
2730 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2733 if isinstance(spec
, SpecifierDM
):
2737 raise ValueError("missing dest-mask in CR twin predication")
2738 if self
.pred
.mode
!= twin
.pred
.mode
:
2739 raise ValueError(f
"predicate masks mismatch: "
2740 f
"{self.pred!r} vs {twin.pred!r}")
2742 def assemble(self
, insn
):
2743 selector
= insn
.select(record
=self
.record
)
2744 # LDST_IDX smask moving to extra322 but not straight away (False)
2745 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2746 selector
.smask_extra332
= int(self
.pred
)
2748 selector
.smask
= int(self
.pred
)
2749 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2752 @_dataclasses.dataclass(eq
=True, frozen
=True)
2753 class SpecifierDM(SpecifierMask
):
2755 def match(cls
, desc
, record
):
2756 return super().match(desc
=desc
, record
=record
, mode
="dm")
2758 def validate(self
, others
):
2759 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2760 raise ValueError("dest-mask on non-twin predicate")
2762 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2765 if isinstance(spec
, SpecifierSM
):
2769 raise ValueError("missing source-mask in CR twin predication")
2770 if self
.pred
.mode
!= twin
.pred
.mode
:
2771 raise ValueError(f
"predicate masks mismatch: "
2772 f
"{self.pred!r} vs {twin.pred!r}")
2774 def assemble(self
, insn
):
2775 selector
= insn
.select(record
=self
.record
)
2776 selector
.mask
= int(self
.pred
)
2777 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2780 @_dataclasses.dataclass(eq
=True, frozen
=True)
2781 class SpecifierZZ(Specifier
):
2783 def match(cls
, desc
, record
):
2787 return cls(record
=record
)
2789 def validate(self
, others
):
2791 # Since zz takes precedence (overrides) sz and dz,
2792 # treat them as mutually exclusive.
2793 if isinstance(spec
, (SpecifierSZ
, SpecifierDZ
)):
2794 raise ValueError("mutually exclusive predicate masks")
2796 def assemble(self
, insn
):
2797 selector
= insn
.select(record
=self
.record
)
2798 if hasattr(selector
, "zz"): # this should be done in a different way
2805 @_dataclasses.dataclass(eq
=True, frozen
=True)
2806 class SpecifierXZ(Specifier
):
2808 hint
: str = _dataclasses
.field(repr=False)
2811 def match(cls
, desc
, record
, etalon
, hint
):
2815 return cls(desc
=desc
, record
=record
, hint
=hint
)
2817 def validate(self
, others
):
2818 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2819 raise ValueError(f
"{self.hint} on non-twin predicate")
2821 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2824 if isinstance(spec
, SpecifierXZ
):
2828 raise ValueError(f
"missing {self.hint} in CR twin predication")
2829 if self
.pred
!= twin
.pred
:
2830 raise ValueError(f
"predicate masks mismatch: "
2831 f
"{self.pred!r} vs {twin.pred!r}")
2833 def assemble(self
, insn
):
2834 selector
= insn
.select(record
=self
.record
)
2835 setattr(selector
, self
.desc
, 1)
2838 @_dataclasses.dataclass(eq
=True, frozen
=True)
2839 class SpecifierSZ(SpecifierXZ
):
2841 def match(cls
, desc
, record
):
2842 return super().match(desc
=desc
, record
=record
,
2843 etalon
="sz", hint
="source-mask")
2845 def validate(self
, others
):
2847 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2848 if isinstance(spec
, SpecifierFF
):
2849 raise ValueError("source-zero not allowed in ff mode")
2852 @_dataclasses.dataclass(eq
=True, frozen
=True)
2853 class SpecifierDZ(SpecifierXZ
):
2855 def match(cls
, desc
, record
):
2856 return super().match(desc
=desc
, record
=record
,
2857 etalon
="dz", hint
="dest-mask")
2859 def validate(self
, others
):
2861 if ((self
.record
.svp64
.mode
is not _SVMode
.CROP
) and
2862 isinstance(spec
, SpecifierFF
) and
2863 (spec
.pred
.mode
is _SVP64PredMode
.RC1
)):
2864 raise ValueError(f
"dest-zero not allowed in ff mode BO")
2867 @_dataclasses.dataclass(eq
=True, frozen
=True)
2868 class SpecifierEls(Specifier
):
2870 def match(cls
, desc
, record
):
2874 if record
.svp64
.mode
not in (_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
):
2875 raise ValueError("els is only valid in ld/st modes, not "
2876 "%s" % str(self
.record
.svp64
.mode
))
2878 return cls(record
=record
)
2880 def assemble(self
, insn
):
2881 if self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
: # stride mode
2882 insn
.prefix
.rm
.mode
[1] = 0
2884 selector
= insn
.select(record
=self
.record
)
2889 @_dataclasses.dataclass(eq
=True, frozen
=True)
2890 class SpecifierSEA(Specifier
):
2892 def match(cls
, desc
, record
):
2896 return cls(record
=record
)
2898 def validate(self
, others
):
2899 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
:
2900 raise ValueError("sea is only valid in ld/st modes, not "
2901 "%s" % str(self
.record
.svp64
.mode
))
2904 if isinstance(spec
, SpecifierFF
):
2905 raise ValueError(f
"sea cannot be used in ff mode")
2907 def assemble(self
, insn
):
2908 selector
= insn
.select(record
=self
.record
)
2909 if selector
.mode
.sel
not in (0b10, 0b00):
2910 raise ValueError("sea is only valid for normal and els modes, "
2911 "not %d" % int(selector
.mode
.sel
))
2915 @_dataclasses.dataclass(eq
=True, frozen
=True)
2916 class SpecifierSat(Specifier
):
2921 def match(cls
, desc
, record
, etalon
, sign
):
2925 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.LDST_IMM
,
2927 raise ValueError("only normal, ld/st imm and "
2928 "ld/st idx modes supported")
2930 return cls(record
=record
, desc
=desc
, sign
=sign
)
2932 def assemble(self
, insn
):
2933 selector
= insn
.select(record
=self
.record
)
2934 selector
.mode
[0] = 0b1
2935 selector
.mode
[1] = 0b0
2936 selector
.N
= int(self
.sign
)
2939 @_dataclasses.dataclass(eq
=True, frozen
=True)
2940 class SpecifierSatS(SpecifierSat
):
2942 def match(cls
, desc
, record
):
2943 return super().match(desc
=desc
, record
=record
,
2944 etalon
="sats", sign
=True)
2947 @_dataclasses.dataclass(eq
=True, frozen
=True)
2948 class SpecifierSatU(SpecifierSat
):
2950 def match(cls
, desc
, record
):
2951 return super().match(desc
=desc
, record
=record
,
2952 etalon
="satu", sign
=False)
2955 @_dataclasses.dataclass(eq
=True, frozen
=True)
2956 class SpecifierMapReduce(Specifier
):
2960 def match(cls
, record
, RG
):
2961 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2962 raise ValueError("only normal and crop modes supported")
2964 return cls(record
=record
, RG
=RG
)
2966 def assemble(self
, insn
):
2967 selector
= insn
.select(record
=self
.record
)
2968 if self
.record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2969 raise ValueError("only normal and crop modes supported")
2970 selector
.mode
[0] = 0
2971 selector
.mode
[1] = 0
2972 selector
.mode
[2] = 1
2973 selector
.RG
= self
.RG
2976 @_dataclasses.dataclass(eq
=True, frozen
=True)
2977 class SpecifierMR(SpecifierMapReduce
):
2979 def match(cls
, desc
, record
):
2983 return super().match(record
=record
, RG
=False)
2986 @_dataclasses.dataclass(eq
=True, frozen
=True)
2987 class SpecifierMRR(SpecifierMapReduce
):
2989 def match(cls
, desc
, record
):
2993 return super().match(record
=record
, RG
=True)
2996 @_dataclasses.dataclass(eq
=True, frozen
=True)
2997 class SpecifierBranch(Specifier
):
2999 def match(cls
, desc
, record
, etalon
):
3003 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3004 raise ValueError("only branch modes supported")
3006 return cls(record
=record
)
3009 @_dataclasses.dataclass(eq
=True, frozen
=True)
3010 class SpecifierAll(SpecifierBranch
):
3012 def match(cls
, desc
, record
):
3013 return super().match(desc
=desc
, record
=record
, etalon
="all")
3015 def assemble(self
, insn
):
3016 selector
= insn
.select(record
=self
.record
)
3020 @_dataclasses.dataclass(eq
=True, frozen
=True)
3021 class SpecifierSNZ(Specifier
):
3023 def match(cls
, desc
, record
):
3027 if record
.svp64
.mode
not in (_SVMode
.BRANCH
, _SVMode
.CROP
):
3028 raise ValueError("only branch and crop modes supported")
3030 return cls(record
=record
)
3032 def assemble(self
, insn
):
3033 selector
= insn
.select(record
=self
.record
)
3034 if self
.record
.svp64
.mode
in (_SVMode
.CROP
, _SVMode
.BRANCH
):
3036 if self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3039 raise ValueError("only branch and crop modes supported")
3042 @_dataclasses.dataclass(eq
=True, frozen
=True)
3043 class SpecifierSL(SpecifierBranch
):
3045 def match(cls
, desc
, record
):
3046 return super().match(desc
=desc
, record
=record
, etalon
="sl")
3048 def assemble(self
, insn
):
3049 selector
= insn
.select(record
=self
.record
)
3053 @_dataclasses.dataclass(eq
=True, frozen
=True)
3054 class SpecifierSLu(SpecifierBranch
):
3056 def match(cls
, desc
, record
):
3057 return super().match(desc
=desc
, record
=record
, etalon
="slu")
3059 def assemble(self
, insn
):
3060 selector
= insn
.select(record
=self
.record
)
3064 @_dataclasses.dataclass(eq
=True, frozen
=True)
3065 class SpecifierLRu(SpecifierBranch
):
3067 def match(cls
, desc
, record
):
3068 return super().match(desc
=desc
, record
=record
, etalon
="lru")
3070 def assemble(self
, insn
):
3071 selector
= insn
.select(record
=self
.record
)
3075 @_dataclasses.dataclass(eq
=True, frozen
=True)
3076 class SpecifierVSXX(SpecifierBranch
):
3081 def match(cls
, desc
, record
, etalon
, VSb
, VLi
):
3085 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3086 raise ValueError("only branch modes supported")
3088 return cls(record
=record
, VSb
=VSb
, VLi
=VLi
)
3090 def assemble(self
, insn
):
3091 selector
= insn
.select(record
=self
.record
)
3093 selector
.VSb
= int(self
.VSb
)
3094 selector
.VLi
= int(self
.VLi
)
3097 @_dataclasses.dataclass(eq
=True, frozen
=True)
3098 class SpecifierVS(SpecifierVSXX
):
3100 def match(cls
, desc
, record
):
3101 return super().match(desc
=desc
, record
=record
,
3102 etalon
="vs", VSb
=False, VLi
=False)
3105 @_dataclasses.dataclass(eq
=True, frozen
=True)
3106 class SpecifierVSi(SpecifierVSXX
):
3108 def match(cls
, desc
, record
):
3109 return super().match(desc
=desc
, record
=record
,
3110 etalon
="vsi", VSb
=False, VLi
=True)
3113 @_dataclasses.dataclass(eq
=True, frozen
=True)
3114 class SpecifierVSb(SpecifierVSXX
):
3116 def match(cls
, desc
, record
):
3117 return super().match(desc
=desc
, record
=record
,
3118 etalon
="vsb", VSb
=True, VLi
=False)
3121 @_dataclasses.dataclass(eq
=True, frozen
=True)
3122 class SpecifierVSbi(SpecifierVSXX
):
3124 def match(cls
, desc
, record
):
3125 return super().match(desc
=desc
, record
=record
,
3126 etalon
="vsbi", VSb
=True, VLi
=True)
3129 @_dataclasses.dataclass(eq
=True, frozen
=True)
3130 class SpecifierCTX(Specifier
):
3134 def match(cls
, desc
, record
, etalon
, CTi
):
3138 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3139 raise ValueError("only branch modes supported")
3141 return cls(record
=record
, CTi
=CTi
)
3143 def assemble(self
, insn
):
3144 selector
= insn
.select(record
=self
.record
)
3146 selector
.CTi
= int(self
.CTi
)
3149 @_dataclasses.dataclass(eq
=True, frozen
=True)
3150 class SpecifierCTR(SpecifierCTX
):
3152 def match(cls
, desc
, record
):
3153 return super().match(desc
=desc
, record
=record
,
3154 etalon
="ctr", CTi
=False)
3157 @_dataclasses.dataclass(eq
=True, frozen
=True)
3158 class SpecifierCTi(SpecifierCTX
):
3160 def match(cls
, desc
, record
):
3161 return super().match(desc
=desc
, record
=record
,
3162 etalon
="cti", CTi
=True)
3165 @_dataclasses.dataclass(eq
=True, frozen
=True)
3166 class SpecifierPI(Specifier
):
3168 def match(cls
, desc
, record
):
3172 if record
.svp64
.mode
not in [_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
]:
3173 raise ValueError("only ld/st imm/idx mode supported")
3175 return cls(record
=record
)
3177 def assemble(self
, insn
):
3178 selector
= insn
.select(record
=self
.record
)
3179 selector
.mode
[2] = 0b1
3183 @_dataclasses.dataclass(eq
=True, frozen
=True)
3184 class SpecifierLF(Specifier
):
3186 def match(cls
, desc
, record
):
3190 if record
.svp64
.mode
is not _SVMode
.LDST_IMM
:
3191 raise ValueError("only ld/st imm mode supported")
3193 return cls(record
=record
)
3195 def assemble(self
, insn
):
3196 selector
= insn
.select(record
=self
.record
)
3197 selector
.mode
[1] = 0
3201 @_dataclasses.dataclass(eq
=True, frozen
=True)
3202 class SpecifierVLi(Specifier
):
3204 def match(cls
, desc
, record
):
3208 return cls(record
=record
)
3210 def validate(self
, others
):
3212 if isinstance(spec
, SpecifierFF
):
3215 raise ValueError("VLi only allowed in failfirst")
3217 def assemble(self
, insn
):
3218 selector
= insn
.select(record
=self
.record
)
3219 selector
.mode
[1] = 1
3223 class Specifiers(tuple):
3258 def __new__(cls
, items
, record
):
3259 def transform(item
):
3260 for spec_cls
in cls
.SPECS
:
3261 spec
= spec_cls
.match(item
, record
=record
)
3262 if spec
is not None:
3264 raise ValueError(item
)
3266 # TODO: remove this hack
3267 items
= dict.fromkeys(items
)
3271 items
= tuple(items
)
3273 specs
= tuple(map(transform
, items
))
3274 for (index
, spec
) in enumerate(specs
):
3275 head
= specs
[:index
]
3276 tail
= specs
[index
+ 1:]
3277 spec
.validate(others
=(head
+ tail
))
3279 return super().__new
__(cls
, specs
)
3282 class SVP64OperandMeta(type):
3283 class SVP64NonZeroOperand(NonZeroOperand
):
3284 def assemble(self
, insn
, value
):
3285 if isinstance(value
, str):
3286 value
= int(value
, 0)
3287 if not isinstance(value
, int):
3288 raise ValueError("non-integer operand")
3290 # FIXME: this is really weird
3291 if self
.record
.name
in ("svstep", "svstep."):
3292 value
+= 1 # compensation
3294 return super().assemble(value
=value
, insn
=insn
)
3296 class SVP64XOStaticOperand(SpanStaticOperand
):
3297 def __init__(self
, record
, value
, span
):
3298 return super().__init
__(record
=record
, name
="XO",
3299 value
=value
, span
=span
)
3302 NonZeroOperand
: SVP64NonZeroOperand
,
3303 XOStaticOperand
: SVP64XOStaticOperand
,
3306 def __new__(metacls
, name
, bases
, ns
):
3308 for (index
, base_cls
) in enumerate(bases
):
3309 bases
[index
] = metacls
.__TRANSFORM
.get(base_cls
, base_cls
)
3311 bases
= tuple(bases
)
3313 return super().__new
__(metacls
, name
, bases
, ns
)
3316 class SVP64Operand(Operand
, metaclass
=SVP64OperandMeta
):
3319 return tuple(map(lambda bit
: (bit
+ 32), super().span
))
3323 def __init__(self
, insn
, record
):
3325 self
.__record
= record
3326 return super().__init
__()
3329 return self
.rm
.__doc
__
3332 return repr(self
.rm
)
3340 return self
.__record
3344 rm
= getattr(self
.insn
.prefix
.rm
, self
.record
.svp64
.mode
.name
.lower())
3346 # The idea behind these tables is that they are now literally
3347 # in identical format to insndb.csv and minor_xx.csv and can
3348 # be done precisely as that. The only thing to watch out for
3349 # is the insertion of Rc=1 as a "mask/value" bit and likewise
3350 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
3353 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
3354 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3355 # mode Rc mask Rc member
3357 (0b000000, 0b111000, "simple"), # simple (no Rc)
3358 (0b001000, 0b111100, "mr"), # mapreduce (no Rc)
3359 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3360 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3361 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3362 (0b001100, 0b111100, "rsvd"), # reserved
3364 mode
= int(self
.insn
.prefix
.rm
.normal
.mode
)
3365 search
= ((mode
<< 1) | self
.record
.Rc
)
3367 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
3368 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3369 # mode Rc mask Rc member
3370 # ironically/coincidentally this table is identical to NORMAL
3371 # mode except reserved in place of mr
3373 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3374 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3375 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3377 search
= ((int(self
.insn
.prefix
.rm
.ldst_imm
.mode
) << 1) |
3380 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
3381 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3382 # mode Rc mask Rc member
3384 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3385 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3386 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3388 search
= ((int(self
.insn
.prefix
.rm
.ldst_idx
.mode
) << 1) |
3391 elif self
.record
.svp64
.mode
is _SVMode
.CROP
:
3392 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
3393 # mode 3b mask 3b member
3395 (0b000000, 0b111000, "simple"), # simple
3396 (0b001000, 0b111000, "mr"), # mapreduce
3397 (0b010001, 0b010001, "ff3"), # ffirst, 3-bit CR
3398 (0b010000, 0b010000, "ff5"), # ffirst, 5-bit CR
3400 search
= ((int(self
.insn
.prefix
.rm
.crop
.mode
) << 1) |
3401 int(self
.record
.svp64
.extra_CR_3bit
))
3403 elif self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3407 (0b00, 0b11, "simple"), # simple
3408 (0b01, 0b11, "vls"), # VLset
3409 (0b10, 0b11, "ctr"), # CTR mode
3410 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
3412 # slightly weird: doesn't have a 5-bit "mode" field like others
3413 search
= int(self
.insn
.prefix
.rm
.branch
.mode
.sel
)
3416 if table
is not None:
3417 for (value
, mask
, field
) in table
:
3418 if field
.startswith("rsvd"):
3420 if ((value
& mask
) == (search
& mask
)):
3421 return getattr(rm
, field
)
3425 def __getattr__(self
, key
):
3426 if key
.startswith(f
"_{self.__class__.__name__}__"):
3427 return super().__getattribute
__(key
)
3429 return getattr(self
.rm
, key
)
3431 def __setattr__(self
, key
, value
):
3432 if key
.startswith(f
"_{self.__class__.__name__}__"):
3433 return super().__setattr
__(key
, value
)
3436 if not hasattr(rm
, key
):
3437 raise AttributeError(key
)
3439 return setattr(rm
, key
, value
)
3442 class SVP64Instruction(PrefixedInstruction
):
3443 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
3444 class Prefix(PrefixedInstruction
.Prefix
):
3446 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
3450 def select(self
, record
):
3451 return RMSelector(insn
=self
, record
=record
)
3456 for idx
in range(64):
3457 bit
= int(self
[idx
])
3459 return "".join(map(str, bits
))
3462 def assemble(cls
, record
, arguments
=None, specifiers
=None):
3463 insn
= super().assemble(record
=record
, arguments
=arguments
)
3465 specifiers
= Specifiers(items
=specifiers
, record
=record
)
3466 for specifier
in specifiers
:
3467 specifier
.assemble(insn
=insn
)
3469 insn
.prefix
.PO
= 0x1
3470 insn
.prefix
.id = 0x3
3474 def disassemble(self
, record
,
3476 style
=Style
.NORMAL
):
3478 if style
<= Style
.SHORT
:
3481 blob
= insn
.bytes(byteorder
=byteorder
)
3482 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
3485 blob_prefix
= blob(self
.prefix
)
3486 blob_suffix
= blob(self
.suffix
)
3488 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3489 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
3492 assert record
.svp64
is not None
3494 name
= f
"sv.{record.name}"
3496 rm
= self
.select(record
=record
)
3498 # convert specifiers to /x/y/z (sorted lexicographically)
3499 specifiers
= sorted(rm
.specifiers(record
=record
))
3500 if specifiers
: # if any add one extra to get the extra "/"
3501 specifiers
= ([""] + specifiers
)
3502 specifiers
= "/".join(specifiers
)
3504 # convert operands to " ,x,y,z"
3505 operands
= tuple(map(_operator
.itemgetter(1),
3506 self
.spec_dynamic_operands(record
=record
, style
=style
)))
3507 operands
= ",".join(operands
)
3508 if len(operands
) > 0: # if any separate with a space
3509 operands
= (" " + operands
)
3511 if style
<= Style
.LEGACY
:
3512 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3513 suffix
= WordInstruction
.integer(value
=int(self
.suffix
))
3514 yield from suffix
.disassemble(record
=record
,
3515 byteorder
=byteorder
, style
=style
)
3517 yield f
"{blob_prefix}{name}{specifiers}{operands}"
3519 yield f
"{blob_suffix}"
3521 if style
>= Style
.VERBOSE
:
3523 binary
= self
.binary
3524 spec
= self
.spec(record
=record
, prefix
="sv.")
3526 yield f
"{indent}spec"
3527 yield f
"{indent}{indent}{spec}"
3528 yield f
"{indent}pcode"
3529 for stmt
in record
.mdwn
.pcode
:
3530 yield f
"{indent}{indent}{stmt}"
3531 yield f
"{indent}binary"
3532 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
3533 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
3534 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
3535 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
3536 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
3537 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
3538 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
3539 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
3540 yield f
"{indent}opcodes"
3541 for opcode
in record
.opcodes
:
3542 yield f
"{indent}{indent}{opcode!r}"
3543 for operand
in self
.operands(record
=record
):
3544 yield from operand
.disassemble(insn
=self
,
3545 style
=style
, indent
=indent
)
3547 yield f
"{indent}{indent}{str(rm)}"
3548 for line
in rm
.disassemble(style
=style
):
3549 yield f
"{indent}{indent}{line}"
3553 def operands(cls
, record
):
3554 for operand
in super().operands(record
=record
):
3555 parent
= operand
.__class
__
3556 name
= f
"SVP64{parent.__name__}"
3557 bases
= (SVP64Operand
, parent
)
3558 child
= type(name
, bases
, {})
3559 yield child(**dict(operand
))
3562 def parse(stream
, factory
):
3564 return ("TODO" not in frozenset(entry
.values()))
3566 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
3567 entries
= _csv
.DictReader(lines
)
3568 entries
= filter(match
, entries
)
3569 return tuple(map(factory
, entries
))
3572 class MarkdownDatabase
:
3575 for (name
, desc
) in _ISA():
3578 (dynamic
, *static
) = desc
.regs
3579 operands
.extend(dynamic
)
3580 operands
.extend(static
)
3581 pcode
= PCode(iterable
=filter(str.strip
, desc
.pcode
))
3582 operands
= Operands(insn
=name
, operands
=operands
)
3583 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
3585 self
.__db
= dict(sorted(db
.items()))
3587 return super().__init
__()
3590 yield from self
.__db
.items()
3592 def __contains__(self
, key
):
3593 return self
.__db
.__contains
__(key
)
3595 def __getitem__(self
, key
):
3596 return self
.__db
.__getitem
__(key
)
3599 class FieldsDatabase
:
3602 df
= _DecodeFields()
3604 for (form
, fields
) in df
.instrs
.items():
3605 if form
in {"DQE", "TX"}:
3609 db
[_Form
[form
]] = Fields(fields
)
3613 return super().__init
__()
3615 def __getitem__(self
, key
):
3616 return self
.__db
.__getitem
__(key
)
3620 def __init__(self
, root
, mdwndb
):
3621 # The code below groups the instructions by name:section.
3622 # There can be multiple names for the same instruction.
3623 # The point is to capture different opcodes for the same instruction.
3625 records
= _collections
.defaultdict(set)
3626 path
= (root
/ "insndb.csv")
3627 with
open(path
, "r", encoding
="UTF-8") as stream
:
3628 for section
in sorted(parse(stream
, Section
.CSV
)):
3629 path
= (root
/ section
.path
)
3631 section
.Mode
.INTEGER
: IntegerOpcode
,
3632 section
.Mode
.PATTERN
: PatternOpcode
,
3634 factory
= _functools
.partial(
3635 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
3636 with
open(path
, "r", encoding
="UTF-8") as stream
:
3637 for insn
in parse(stream
, factory
):
3638 for name
in insn
.names
:
3639 records
[name
].add(insn
)
3640 sections
[name
] = section
3642 items
= sorted(records
.items())
3644 for (name
, multirecord
) in items
:
3645 records
[name
] = PPCMultiRecord(sorted(multirecord
))
3647 def exact_match(name
):
3648 record
= records
.get(name
)
3654 if not name
.endswith("l"):
3656 alias
= exact_match(name
[:-1])
3659 record
= records
[alias
]
3660 if "lk" not in record
.flags
:
3661 raise ValueError(record
)
3665 if not name
.endswith("a"):
3667 alias
= LK_match(name
[:-1])
3670 record
= records
[alias
]
3671 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
3672 raise ValueError(record
)
3673 if "AA" not in mdwndb
[name
].operands
:
3674 raise ValueError(record
)
3678 if not name
.endswith("."):
3680 alias
= exact_match(name
[:-1])
3683 record
= records
[alias
]
3684 if record
.Rc
is _RCOE
.NONE
:
3685 raise ValueError(record
)
3689 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
3690 for (name
, _
) in mdwndb
:
3691 if name
.startswith("sv."):
3694 for match
in matches
:
3696 if alias
is not None:
3700 section
= sections
[alias
]
3701 record
= records
[alias
]
3702 db
[name
] = (section
, record
)
3704 self
.__db
= dict(sorted(db
.items()))
3706 return super().__init
__()
3708 @_functools.lru_cache(maxsize
=512, typed
=False)
3709 def __getitem__(self
, key
):
3710 return self
.__db
.get(key
, (None, None))
3713 class SVP64Database
:
3714 def __init__(self
, root
, ppcdb
):
3716 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
3717 for (prefix
, _
, names
) in _os
.walk(root
):
3718 prefix
= _pathlib
.Path(prefix
)
3719 for name
in filter(lambda name
: pattern
.match(name
), names
):
3720 path
= (prefix
/ _pathlib
.Path(name
))
3721 with
open(path
, "r", encoding
="UTF-8") as stream
:
3722 db
.update(parse(stream
, SVP64Record
.CSV
))
3723 db
= {record
.name
:record
for record
in db
}
3725 self
.__db
= dict(sorted(db
.items()))
3726 self
.__ppcdb
= ppcdb
3728 return super().__init
__()
3730 def __getitem__(self
, key
):
3731 (_
, record
) = self
.__ppcdb
[key
]
3735 for name
in record
.names
:
3736 record
= self
.__db
.get(name
, None)
3737 if record
is not None:
3743 class Records(tuple):
3744 def __new__(cls
, records
):
3745 return super().__new
__(cls
, sorted(records
))
3748 def walk(clsself
, match
=None):
3750 match
= lambda subnode
: True
3752 if isinstance(clsself
, type):
3755 for record
in clsself
:
3760 class Database(Node
):
3761 def __init__(self
, root
):
3762 root
= _pathlib
.Path(root
)
3763 mdwndb
= MarkdownDatabase()
3764 fieldsdb
= FieldsDatabase()
3765 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
3766 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
3770 opcodes
= _collections
.defaultdict(
3771 lambda: _collections
.defaultdict(set))
3773 for (name
, mdwn
) in mdwndb
:
3774 if name
.startswith("sv."):
3776 (section
, ppc
) = ppcdb
[name
]
3779 svp64
= svp64db
[name
]
3780 fields
= fieldsdb
[ppc
.form
]
3781 record
= Record(name
=name
,
3782 section
=section
, ppc
=ppc
, svp64
=svp64
,
3783 mdwn
=mdwn
, fields
=fields
)
3785 names
[record
.name
] = record
3786 opcodes
[section
][record
.PO
].add(record
)
3788 self
.__db
= Records(db
)
3789 self
.__names
= dict(sorted(names
.items()))
3790 self
.__opcodes
= dict(sorted(opcodes
.items()))
3792 return super().__init
__()
3795 def walk(clsself
, match
=None):
3797 match
= lambda subnode
: True
3799 if isinstance(clsself
, type):
3802 if match(clsself
.__db
):
3806 return repr(self
.__db
)
3809 yield from self
.__db
3811 @_functools.lru_cache(maxsize
=None)
3812 def __contains__(self
, key
):
3813 return self
.__getitem
__(key
) is not None
3815 @_functools.lru_cache(maxsize
=None)
3816 def __getitem__(self
, key
):
3817 if isinstance(key
, SVP64Instruction
):
3820 if isinstance(key
, Instruction
):
3823 sections
= sorted(self
.__opcodes
)
3824 for section
in sections
:
3825 group
= self
.__opcodes
[section
]
3826 for record
in group
[PO
]:
3827 if record
.match(key
=key
):
3832 elif isinstance(key
, str):
3833 return self
.__names
.get(key
)
3835 raise ValueError("instruction or name expected")