1 import collections
as _collections
2 import contextlib
as _contextlib
4 import dataclasses
as _dataclasses
6 import functools
as _functools
8 import operator
as _operator
9 import pathlib
as _pathlib
11 import types
as _types
12 import typing
as _typing
15 from functools
import cached_property
17 from cached_property
import cached_property
19 from openpower
.decoder
.power_enums
import (
20 Function
as _Function
,
27 CRIn2Sel
as _CRIn2Sel
,
28 CROutSel
as _CROutSel
,
30 LDSTMode
as _LDSTMode
,
35 SVMaskSrc
as _SVMaskSrc
,
42 SVP64SubVL
as _SVP64SubVL
,
43 SVP64Pred
as _SVP64Pred
,
44 SVP64PredMode
as _SVP64PredMode
,
45 SVP64Width
as _SVP64Width
,
47 from openpower
.decoder
.selectable_int
import (
48 SelectableInt
as _SelectableInt
,
49 selectconcat
as _selectconcat
,
51 from openpower
.decoder
.power_fields
import (
54 DecodeFields
as _DecodeFields
,
56 from openpower
.decoder
.pseudo
.pagereader
import ISA
as _ISA
60 def subnodes(self
, match
=None):
64 class String(Node
, str):
68 @_dataclasses.dataclass(eq
=True, frozen
=True)
70 def subnodes(self
, match
=None):
72 match
= lambda subnode
: True
75 return getattr(self
, field
.name
)
77 yield from filter(match
, map(subnode
, _dataclasses
.fields()))
81 @_contextlib.contextmanager
82 def __call__(self
, node
):
86 def walk(root
, match
=None):
87 nodes
= _collections
.deque([root
])
89 node
= nodes
.popleft()
90 nodes
.extend(node
.subnodes(match
=match
))
94 def visit(visitor
, node
):
95 with
visitor(node
=node
):
96 for subnode
in node
.subnodes():
97 visit(visitor
=visitor
, node
=subnode
)
100 @_functools.total_ordering
101 class Style(_enum
.Enum
):
102 LEGACY
= _enum
.auto()
104 NORMAL
= _enum
.auto()
105 VERBOSE
= _enum
.auto()
107 def __lt__(self
, other
):
108 if not isinstance(other
, self
.__class
__):
109 return NotImplemented
110 return (self
.value
< other
.value
)
113 @_functools.total_ordering
114 class Priority(_enum
.Enum
):
120 def _missing_(cls
, value
):
121 if isinstance(value
, str):
122 value
= value
.upper()
126 return super()._missing
_(value
)
128 def __lt__(self
, other
):
129 if not isinstance(other
, self
.__class
__):
130 return NotImplemented
132 # NOTE: the order is inversed, LOW < NORMAL < HIGH
133 return (self
.value
> other
.value
)
136 def dataclass(cls
, record
, keymap
=None, typemap
=None):
140 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
142 def transform(key_value
):
143 (key
, value
) = key_value
144 key
= keymap
.get(key
, key
)
145 hook
= typemap
.get(key
, lambda value
: value
)
146 if hook
is bool and value
in ("", "0"):
152 record
= dict(map(transform
, record
.items()))
153 for key
in frozenset(record
.keys()):
154 if record
[key
] == "":
160 @_functools.total_ordering
161 @_dataclasses.dataclass(eq
=True, frozen
=True)
164 def __new__(cls
, value
):
165 if isinstance(value
, str):
166 value
= int(value
, 0)
167 if not isinstance(value
, int):
168 raise ValueError(value
)
170 if value
.bit_length() > 64:
171 raise ValueError(value
)
173 return super().__new
__(cls
, value
)
176 return self
.__repr
__()
179 return f
"{self:0{self.bit_length()}b}"
181 def bit_length(self
):
182 if super().bit_length() > 32:
186 class Value(Integer
):
195 def __lt__(self
, other
):
196 if not isinstance(other
, Opcode
):
197 return NotImplemented
198 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
201 return (self
.value
& self
.mask
)
204 return int(self
).__index
__()
207 def pattern(value
, mask
, bit_length
):
208 for bit
in range(bit_length
):
209 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
211 elif (value
& (1 << (bit_length
- bit
- 1))):
216 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
218 def match(self
, key
):
219 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
222 @_functools.total_ordering
223 @_dataclasses.dataclass(eq
=True, frozen
=True)
224 class IntegerOpcode(Opcode
):
225 def __init__(self
, value
):
226 if value
.startswith("0b"):
227 mask
= int(("1" * len(value
[2:])), 2)
231 value
= Opcode
.Value(value
)
232 mask
= Opcode
.Mask(mask
)
234 return super().__init
__(value
=value
, mask
=mask
)
237 @_functools.total_ordering
238 @_dataclasses.dataclass(eq
=True, frozen
=True)
239 class PatternOpcode(Opcode
):
240 def __init__(self
, pattern
):
241 if not isinstance(pattern
, str):
242 raise ValueError(pattern
)
244 (value
, mask
) = (0, 0)
245 for symbol
in pattern
:
246 if symbol
not in {"0", "1", "-"}:
247 raise ValueError(pattern
)
248 value |
= (symbol
== "1")
249 mask |
= (symbol
!= "-")
255 value
= Opcode
.Value(value
)
256 mask
= Opcode
.Mask(mask
)
258 return super().__init
__(value
=value
, mask
=mask
)
261 @_dataclasses.dataclass(eq
=True, frozen
=True)
263 class FlagsMeta(type):
278 class Flags(tuple, metaclass
=FlagsMeta
):
279 def __new__(cls
, flags
=frozenset()):
280 flags
= frozenset(flags
)
281 diff
= (flags
- frozenset(cls
))
283 raise ValueError(flags
)
284 return super().__new
__(cls
, sorted(flags
))
288 flags
: Flags
= Flags()
289 comment2
: String
= String()
290 function
: _Function
= _Function
.NONE
291 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
292 in1
: _In1Sel
= _In1Sel
.NONE
293 in2
: _In2Sel
= _In2Sel
.NONE
294 in3
: _In3Sel
= _In3Sel
.NONE
295 out
: _OutSel
= _OutSel
.NONE
296 cr_in
: _CRInSel
= _CRInSel
.NONE
297 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
298 cr_out
: _CROutSel
= _CROutSel
.NONE
299 cry_in
: _CryIn
= _CryIn
.ZERO
300 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
301 upd
: _LDSTMode
= _LDSTMode
.NONE
302 Rc
: _RCOE
= _RCOE
.NONE
303 form
: _Form
= _Form
.NONE
304 conditions
: String
= String()
305 unofficial
: bool = False
309 "internal op": "intop",
313 "ldst len": "ldst_len",
315 "CONDITIONS": "conditions",
318 def __lt__(self
, other
):
319 if not isinstance(other
, self
.__class
__):
320 return NotImplemented
321 lhs
= (self
.opcode
, self
.comment
)
322 rhs
= (other
.opcode
, other
.comment
)
326 def CSV(cls
, record
, opcode_cls
):
327 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
328 typemap
["opcode"] = opcode_cls
330 if record
["CR in"] == "BA_BB":
331 record
["cr_in"] = "BA"
332 record
["cr_in2"] = "BB"
336 for flag
in frozenset(PPCRecord
.Flags
):
337 if bool(record
.pop(flag
, "")):
339 record
["flags"] = PPCRecord
.Flags(flags
)
341 return dataclass(cls
, record
,
342 keymap
=PPCRecord
.__KEYMAP
,
347 return frozenset(self
.comment
.split("=")[-1].split("/"))
350 class PPCMultiRecord(tuple):
351 def __getattr__(self
, attr
):
354 raise AttributeError(attr
)
355 return getattr(self
[0], attr
)
358 @_dataclasses.dataclass(eq
=True, frozen
=True)
360 class ExtraMap(tuple):
362 @_dataclasses.dataclass(eq
=True, frozen
=True)
364 seltype
: _SelType
= _SelType
.NONE
365 reg
: _Reg
= _Reg
.NONE
368 return f
"{self.seltype.value}:{self.reg.name}"
370 def __new__(cls
, value
="0"):
371 if isinstance(value
, str):
372 def transform(value
):
373 (seltype
, reg
) = value
.split(":")
374 seltype
= _SelType(seltype
)
376 return cls
.Entry(seltype
=seltype
, reg
=reg
)
381 value
= map(transform
, value
.split(";"))
383 return super().__new
__(cls
, value
)
386 return repr(list(self
))
388 def __new__(cls
, value
=tuple()):
392 return super().__new
__(cls
, map(cls
.Extra
, value
))
395 return repr({index
:self
[index
] for index
in range(0, 4)})
398 ptype
: _SVPType
= _SVPType
.NONE
399 etype
: _SVEType
= _SVEType
.NONE
400 msrc
: _SVMaskSrc
= _SVMaskSrc
.NO
# MASK_SRC is active
401 in1
: _In1Sel
= _In1Sel
.NONE
402 in2
: _In2Sel
= _In2Sel
.NONE
403 in3
: _In3Sel
= _In3Sel
.NONE
404 out
: _OutSel
= _OutSel
.NONE
405 out2
: _OutSel
= _OutSel
.NONE
406 cr_in
: _CRInSel
= _CRInSel
.NONE
407 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
408 cr_out
: _CROutSel
= _CROutSel
.NONE
409 extra
: ExtraMap
= ExtraMap()
410 conditions
: String
= String()
411 mode
: _SVMode
= _SVMode
.NORMAL
415 "CONDITIONS": "conditions",
424 def CSV(cls
, record
):
425 record
["insn"] = record
["insn"].split("=")[-1]
427 for key
in frozenset({
428 "in1", "in2", "in3", "CR in",
429 "out", "out2", "CR out",
435 if record
["CR in"] == "BA_BB":
436 record
["cr_in"] = "BA"
437 record
["cr_in2"] = "BB"
441 for idx
in range(0, 4):
442 extra
.append(record
.pop(f
"{idx}"))
444 record
["extra"] = cls
.ExtraMap(extra
)
446 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
451 "in1", "in2", "in3", "cr_in", "cr_in2",
452 "out", "out2", "cr_out",
467 for index
in range(0, 4):
468 for entry
in self
.extra
[index
]:
469 extras
[entry
.seltype
][entry
.reg
] = idxmap
[index
]
471 for (seltype
, regs
) in extras
.items():
472 idx
= regs
.get(reg
, _SVExtra
.NONE
)
473 if idx
is not _SVExtra
.NONE
:
474 yield (reg
, seltype
, idx
)
481 # has the word "in", it is a SelType.SRC "out" -> DST
482 # in1/2/3 and CR in are SRC, and must match only against "s:NN"
483 # out/out1 and CR out are DST, and must match only against "d:NN"
484 keytype
= _SelType
.SRC
if ("in" in key
) else _SelType
.DST
485 sel
= sels
[key
] = getattr(self
, key
)
486 reg
= regs
[key
] = _Reg(sel
)
487 seltypes
[key
] = _SelType
.NONE
488 idxs
[key
] = _SVExtra
.NONE
489 for (reg
, seltype
, idx
) in extra(reg
.alias
):
490 if keytype
!= seltype
: # only check SRC-to-SRC and DST-to-DST
492 if idx
!= idxs
[key
] and idxs
[key
] is not _SVExtra
.NONE
:
493 raise ValueError(idx
)
496 seltypes
[key
] = seltype
498 if sels
["cr_in"] is _CRInSel
.BA_BB
:
499 sels
["cr_in"] = _CRIn2Sel
.BA
500 sels
["cr_in2"] = _CRIn2Sel
.BB
501 idxs
["cr_in2"] = idxs
["cr_in"]
502 for key
in ("cr_in", "cr_in2"):
503 regs
[key
] = _Reg(sels
[key
])
504 seltype
[key
] = _SelType
.SRC
511 "seltype": seltypes
[key
],
515 return _types
.MappingProxyType(records
)
517 extra_idx_in1
= property(lambda self
: self
.extras
["in1"]["idx"])
518 extra_idx_in2
= property(lambda self
: self
.extras
["in2"]["idx"])
519 extra_idx_in3
= property(lambda self
: self
.extras
["in3"]["idx"])
520 extra_idx_out
= property(lambda self
: self
.extras
["out"]["idx"])
521 extra_idx_out2
= property(lambda self
: self
.extras
["out2"]["idx"])
522 extra_idx_cr_in
= property(lambda self
: self
.extras
["cr_in"]["idx"])
523 extra_idx_cr_in2
= property(lambda self
: self
.extras
["cr_in2"]["idx"])
524 extra_idx_cr_out
= property(lambda self
: self
.extras
["cr_out"]["idx"])
529 for idx
in range(0, 4):
530 for entry
in self
.extra
[idx
]:
531 if entry
.seltype
is _SelType
.DST
:
532 if extra
is not None:
533 raise ValueError(self
.svp64
)
537 if _RegType(extra
.reg
) not in (_RegType
.CR_3BIT
, _RegType
.CR_5BIT
):
538 raise ValueError(self
.svp64
)
543 def extra_CR_3bit(self
):
544 return (_RegType(self
.extra_CR
.reg
) is _RegType
.CR_3BIT
)
548 def __init__(self
, value
=(0, 32)):
549 if isinstance(value
, str):
550 (start
, end
) = map(int, value
.split(":"))
553 if start
< 0 or end
< 0 or start
>= end
:
554 raise ValueError(value
)
559 return super().__init
__()
562 return (self
.__end
- self
.__start
+ 1)
565 return f
"[{self.__start}:{self.__end}]"
568 yield from range(self
.start
, (self
.end
+ 1))
570 def __reversed__(self
):
571 return tuple(reversed(tuple(self
)))
582 @_dataclasses.dataclass(eq
=True, frozen
=True)
584 class Mode(_enum
.Enum
):
585 INTEGER
= _enum
.auto()
586 PATTERN
= _enum
.auto()
589 def _missing_(cls
, value
):
590 if isinstance(value
, str):
591 return cls
[value
.upper()]
592 return super()._missing
_(value
)
595 def __new__(cls
, value
=None):
596 if isinstance(value
, str):
597 if value
.upper() == "NONE":
600 value
= int(value
, 0)
604 return super().__new
__(cls
, value
)
610 return (bin(self
) if self
else "None")
616 opcode
: IntegerOpcode
= None
617 priority
: Priority
= Priority
.NORMAL
619 def __lt__(self
, other
):
620 if not isinstance(other
, self
.__class
__):
621 return NotImplemented
622 return (self
.priority
< other
.priority
)
625 def CSV(cls
, record
):
626 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
627 if record
["opcode"] == "NONE":
628 typemap
["opcode"] = lambda _
: None
630 return dataclass(cls
, record
, typemap
=typemap
)
634 def __init__(self
, items
):
635 if isinstance(items
, dict):
636 items
= items
.items()
639 (name
, bitrange
) = item
640 return (name
, tuple(bitrange
.values()))
642 self
.__mapping
= dict(map(transform
, items
))
644 return super().__init
__()
647 return repr(self
.__mapping
)
650 yield from self
.__mapping
.items()
652 def __contains__(self
, key
):
653 return self
.__mapping
.__contains
__(key
)
655 def __getitem__(self
, key
):
656 return self
.__mapping
.get(key
, None)
671 def __init__(self
, insn
, operands
):
673 "b": {"target_addr": TargetAddrOperandLI
},
674 "ba": {"target_addr": TargetAddrOperandLI
},
675 "bl": {"target_addr": TargetAddrOperandLI
},
676 "bla": {"target_addr": TargetAddrOperandLI
},
677 "bc": {"target_addr": TargetAddrOperandBD
},
678 "bca": {"target_addr": TargetAddrOperandBD
},
679 "bcl": {"target_addr": TargetAddrOperandBD
},
680 "bcla": {"target_addr": TargetAddrOperandBD
},
681 "addpcis": {"D": DOperandDX
},
682 "fishmv": {"D": DOperandDX
},
683 "fmvis": {"D": DOperandDX
},
686 "SVi": NonZeroOperand
,
687 "SVd": NonZeroOperand
,
688 "SVxd": NonZeroOperand
,
689 "SVyd": NonZeroOperand
,
690 "SVzd": NonZeroOperand
,
692 "D": SignedImmediateOperand
,
696 "SIM": SignedOperand
,
697 "SVD": SignedOperand
,
698 "SVDS": SignedOperand
,
699 "RSp": GPRPairOperand
,
700 "RTp": GPRPairOperand
,
701 "FRAp": FPRPairOperand
,
702 "FRBp": FPRPairOperand
,
703 "FRSp": FPRPairOperand
,
704 "FRTp": FPRPairOperand
,
706 custom_immediates
= {
712 for operand
in operands
:
716 (name
, value
) = operand
.split("=")
717 mapping
[name
] = (StaticOperand
, {
723 if name
.endswith(")"):
724 name
= name
.replace("(", " ").replace(")", "")
725 (imm_name
, _
, name
) = name
.partition(" ")
729 if imm_name
is not None:
730 imm_cls
= custom_immediates
.get(imm_name
, ImmediateOperand
)
732 if insn
in custom_insns
and name
in custom_insns
[insn
]:
733 cls
= custom_insns
[insn
][name
]
734 elif name
in custom_fields
:
735 cls
= custom_fields
[name
]
736 elif name
in _Reg
.__members
__:
738 if reg
in self
.__class
__.__GPR
_PAIRS
:
740 elif reg
in self
.__class
__.__FPR
_PAIRS
:
743 regtype
= _RegType
[name
]
744 if regtype
is _RegType
.GPR
:
746 elif regtype
is _RegType
.FPR
:
748 elif regtype
is _RegType
.CR_3BIT
:
750 elif regtype
is _RegType
.CR_5BIT
:
753 if imm_name
is not None:
754 mapping
[imm_name
] = (imm_cls
, {"name": imm_name
})
755 mapping
[name
] = (cls
, {"name": name
})
759 for (name
, (cls
, kwargs
)) in mapping
.items():
760 kwargs
= dict(kwargs
)
761 kwargs
["name"] = name
762 if issubclass(cls
, StaticOperand
):
763 static
.append((cls
, kwargs
))
764 elif issubclass(cls
, DynamicOperand
):
765 dynamic
.append((cls
, kwargs
))
767 raise ValueError(name
)
769 self
.__mapping
= mapping
770 self
.__static
= tuple(static
)
771 self
.__dynamic
= tuple(dynamic
)
773 return super().__init
__()
776 for (_
, items
) in self
.__mapping
.items():
777 (cls
, kwargs
) = items
781 return self
.__mapping
.__repr
__()
783 def __contains__(self
, key
):
784 return self
.__mapping
.__contains
__(key
)
786 def __getitem__(self
, key
):
787 return self
.__mapping
.__getitem
__(key
)
795 return self
.__dynamic
798 class Arguments(tuple):
799 def __new__(cls
, record
, arguments
, operands
):
800 operands
= iter(tuple(operands
))
801 arguments
= iter(tuple(arguments
))
806 operand
= next(operands
)
807 except StopIteration:
811 argument
= next(arguments
)
812 except StopIteration:
813 raise ValueError("operands count mismatch")
815 if isinstance(operand
, ImmediateOperand
):
816 argument
= argument
.replace("(", " ").replace(")", "")
817 (imm_argument
, _
, argument
) = argument
.partition(" ")
819 (imm_operand
, operand
) = (operand
, next(operands
))
820 except StopIteration:
821 raise ValueError("operands count mismatch")
822 items
.append((imm_argument
, imm_operand
))
823 items
.append((argument
, operand
))
827 except StopIteration:
830 raise ValueError("operands count mismatch")
832 return super().__new
__(cls
, items
)
836 def __init__(self
, iterable
):
837 self
.__pcode
= tuple(iterable
)
838 return super().__init
__()
841 yield from self
.__pcode
844 return self
.__pcode
.__repr
__()
847 @_dataclasses.dataclass(eq
=True, frozen
=True)
848 class MarkdownRecord
:
853 @_dataclasses.dataclass(eq
=True, frozen
=True)
857 _In1Sel
, _In2Sel
, _In3Sel
, _CRInSel
, _CRIn2Sel
,
865 @_functools.total_ordering
866 @_dataclasses.dataclass(eq
=True, frozen
=True)
873 svp64
: SVP64Record
= None
875 def subnodes(self
, match
=None):
877 for (name
, fields
) in self
.extras
.items():
878 extras
.append(Extra(name
=name
, **fields
))
879 yield from filter(match
, extras
)
883 if self
.svp64
is not None:
884 return self
.svp64
.extras
886 return _types
.MappingProxyType({})
890 return self
.mdwn
.pcode
892 def __lt__(self
, other
):
893 if not isinstance(other
, Record
):
894 return NotImplemented
895 lhs
= (min(self
.opcodes
), self
.name
)
896 rhs
= (min(other
.opcodes
), other
.name
)
901 return (self
.static_operands
+ self
.dynamic_operands
)
904 def static_operands(self
):
906 operands
.append(POStaticOperand(record
=self
, value
=self
.PO
))
908 operands
.append(XOStaticOperand(
910 value
=ppc
.opcode
.value
,
911 span
=self
.section
.bitsel
,
913 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
914 operands
.append(cls(record
=self
, **kwargs
))
915 return tuple(operands
)
918 def dynamic_operands(self
):
920 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
921 operands
.append(cls(record
=self
, **kwargs
))
922 return tuple(operands
)
927 return int("".join(str(int(mapping
[bit
])) \
928 for bit
in sorted(mapping
)), 2)
930 def PO_XO(value
, mask
, opcode
, bits
):
933 for (src
, dst
) in enumerate(reversed(bits
)):
934 value
[dst
] = ((opcode
.value
& (1 << src
)) != 0)
935 mask
[dst
] = ((opcode
.mask
& (1 << src
)) != 0)
938 def PO(value
, mask
, opcode
, bits
):
939 return PO_XO(value
=value
, mask
=mask
, opcode
=opcode
, bits
=bits
)
941 def XO(value
, mask
, opcode
, bits
):
942 (value
, mask
) = PO_XO(value
=value
, mask
=mask
,
943 opcode
=opcode
, bits
=bits
)
944 for (op_cls
, op_kwargs
) in self
.mdwn
.operands
.static
:
945 operand
= op_cls(record
=self
, **op_kwargs
)
946 for (src
, dst
) in enumerate(reversed(operand
.span
)):
947 value
[dst
] = ((operand
.value
& (1 << src
)) != 0)
952 value
= {bit
:False for bit
in range(32)}
953 mask
= {bit
:False for bit
in range(32)}
954 if self
.section
.opcode
is not None:
955 (value
, mask
) = PO(value
=value
, mask
=mask
,
956 opcode
=self
.section
.opcode
, bits
=range(0, 6))
958 pairs
.append(XO(value
=value
, mask
=mask
,
959 opcode
=ppc
.opcode
, bits
=self
.section
.bitsel
))
962 for (value
, mask
) in pairs
:
963 value
= Opcode
.Value(binary(value
))
964 mask
= Opcode
.Mask(binary(mask
))
965 result
.append(Opcode(value
=value
, mask
=mask
))
971 opcode
= self
.section
.opcode
973 opcode
= self
.ppc
[0].opcode
974 if isinstance(opcode
, PatternOpcode
):
975 value
= int(opcode
.value
)
976 bits
= opcode
.value
.bit_length()
977 return int(_SelectableInt(value
=value
, bits
=bits
)[0:6])
979 return int(opcode
.value
)
983 return tuple(ppc
.opcode
for ppc
in self
.ppc
)
985 def match(self
, key
):
986 for opcode
in self
.opcodes
:
987 if opcode
.match(key
):
994 return self
.svp64
.mode
1014 if self
.svp64
is None:
1020 return self
.ppc
.cr_in
1024 return self
.ppc
.cr_in2
1028 return self
.ppc
.cr_out
1030 ptype
= property(lambda self
: self
.svp64
.ptype
)
1031 etype
= property(lambda self
: self
.svp64
.etype
)
1033 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
1034 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
1035 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
1036 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
1037 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
1038 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
1039 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
1040 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
1042 def __contains__(self
, key
):
1043 return self
.mdwn
.operands
.__contains
__(key
)
1045 def __getitem__(self
, key
):
1046 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
1047 return cls(record
=self
, **kwargs
)
1051 if "Rc" not in self
:
1053 return self
["Rc"].value
1057 def __init__(self
, record
, name
):
1058 self
.__record
= record
1062 yield ("record", self
.record
)
1063 yield ("name", self
.__name
)
1066 return f
"{self.__class__.__name__}({self.name})"
1074 return self
.__record
1078 return self
.record
.fields
[self
.name
]
1080 def assemble(self
, insn
):
1081 raise NotImplementedError()
1083 def disassemble(self
, insn
,
1084 style
=Style
.NORMAL
, indent
=""):
1085 raise NotImplementedError()
1088 class DynamicOperand(Operand
):
1089 def assemble(self
, insn
, value
):
1091 if isinstance(value
, str):
1092 value
= int(value
, 0)
1094 raise ValueError("signed operands not allowed")
1097 def disassemble(self
, insn
,
1098 style
=Style
.NORMAL
, indent
=""):
1102 if style
>= Style
.VERBOSE
:
1103 span
= map(str, span
)
1104 yield f
"{indent}{self.name}"
1105 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1106 yield f
"{indent}{indent}{', '.join(span)}"
1108 yield str(int(value
))
1111 class SignedOperand(DynamicOperand
):
1112 def assemble(self
, insn
, value
):
1113 if isinstance(value
, str):
1114 value
= int(value
, 0)
1115 return super().assemble(value
=value
, insn
=insn
)
1117 def assemble(self
, insn
, value
):
1119 if isinstance(value
, str):
1120 value
= int(value
, 0)
1123 def disassemble(self
, insn
,
1124 style
=Style
.NORMAL
, indent
=""):
1126 value
= insn
[span
].to_signed_int()
1127 sign
= "-" if (value
< 0) else ""
1130 if style
>= Style
.VERBOSE
:
1131 span
= map(str, span
)
1132 yield f
"{indent}{self.name}"
1133 yield f
"{indent}{indent}{sign}{value}"
1134 yield f
"{indent}{indent}{', '.join(span)}"
1136 yield f
"{sign}{value}"
1139 class StaticOperand(Operand
):
1140 def __init__(self
, record
, name
, value
):
1141 self
.__value
= value
1142 return super().__init
__(record
=record
, name
=name
)
1145 yield ("value", self
.__value
)
1146 yield from super().__iter
__()
1149 return f
"{self.__class__.__name__}({self.name}, value={self.value})"
1155 def assemble(self
, insn
):
1156 insn
[self
.span
] = self
.value
1158 def disassemble(self
, insn
,
1159 style
=Style
.NORMAL
, indent
=""):
1163 if style
>= Style
.VERBOSE
:
1164 span
= map(str, span
)
1165 yield f
"{indent}{self.name}"
1166 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1167 yield f
"{indent}{indent}{', '.join(span)}"
1169 yield str(int(value
))
1172 class SpanStaticOperand(StaticOperand
):
1173 def __init__(self
, record
, name
, value
, span
):
1174 self
.__span
= tuple(span
)
1175 return super().__init
__(record
=record
, name
=name
, value
=value
)
1178 yield ("span", self
.__span
)
1179 yield from super().__iter
__()
1186 class POStaticOperand(SpanStaticOperand
):
1187 def __init__(self
, record
, value
):
1188 return super().__init
__(record
=record
, name
="PO",
1189 value
=value
, span
=range(0, 6))
1192 for (key
, value
) in super().__iter
__():
1193 if key
not in {"name", "span"}:
1197 class XOStaticOperand(SpanStaticOperand
):
1198 def __init__(self
, record
, value
, span
):
1199 bits
= record
.section
.bitsel
1200 value
= _SelectableInt(value
=value
, bits
=len(bits
))
1201 span
= dict(zip(bits
, range(len(bits
))))
1202 span_rev
= {value
:key
for (key
, value
) in span
.items()}
1204 # This part is tricky: we cannot use record.operands,
1205 # as this code is called by record.static_operands method.
1206 for (cls
, kwargs
) in record
.mdwn
.operands
:
1207 operand
= cls(record
=record
, **kwargs
)
1208 for idx
in operand
.span
:
1209 rev
= span
.pop(idx
, None)
1211 span_rev
.pop(rev
, None)
1213 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1214 span
= tuple(span
.keys())
1216 return super().__init
__(record
=record
, name
="XO",
1217 value
=value
, span
=span
)
1220 for (key
, value
) in super().__iter
__():
1221 if key
not in {"name"}:
1225 class ImmediateOperand(DynamicOperand
):
1229 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1233 class NonZeroOperand(DynamicOperand
):
1234 def assemble(self
, insn
, value
):
1235 if isinstance(value
, str):
1236 value
= int(value
, 0)
1237 if not isinstance(value
, int):
1238 raise ValueError("non-integer operand")
1240 raise ValueError("non-zero operand")
1242 return super().assemble(value
=value
, insn
=insn
)
1244 def disassemble(self
, insn
,
1245 style
=Style
.NORMAL
, indent
=""):
1249 if style
>= Style
.VERBOSE
:
1250 span
= map(str, span
)
1251 yield f
"{indent}{self.name}"
1252 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1253 yield f
"{indent}{indent}{', '.join(span)}"
1255 yield str(int(value
) + 1)
1258 class ExtendableOperand(DynamicOperand
):
1259 def sv_spec_enter(self
, value
, span
):
1260 return (value
, span
)
1262 def sv_spec(self
, insn
):
1266 span
= tuple(map(str, span
))
1268 if isinstance(insn
, SVP64Instruction
):
1269 (origin_value
, origin_span
) = (value
, span
)
1270 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1272 for extra_idx
in self
.extra_idx
:
1273 if self
.record
.etype
is _SVEType
.EXTRA3
:
1274 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1275 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1276 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1278 raise ValueError(self
.record
.etype
)
1281 vector
= bool(spec
[0])
1282 spec_span
= spec
.__class
__
1283 if self
.record
.etype
is _SVEType
.EXTRA3
:
1284 spec_span
= tuple(map(str, spec_span
[1, 2]))
1286 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1287 spec_span
= tuple(map(str, spec_span
[1,]))
1288 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1291 spec_span
= (spec_span
+ ("{0}",))
1293 spec_span
= (("{0}",) + spec_span
)
1295 raise ValueError(self
.record
.etype
)
1297 vector_shift
= (2 + (5 - value
.bits
))
1298 scalar_shift
= value
.bits
1299 spec_shift
= (5 - value
.bits
)
1301 bits
= (len(span
) + len(spec_span
))
1302 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1303 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1305 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1306 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1308 value
= ((spec
<< scalar_shift
) | value
)
1309 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1311 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1312 origin_value
=origin_value
, origin_span
=origin_span
)
1314 return (vector
, value
, span
)
1316 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1317 return (value
, span
)
1320 def extra_idx(self
):
1321 for (key
, record
) in self
.record
.svp64
.extras
.items():
1322 if record
["reg"].alias
is self
.extra_reg
.alias
:
1326 def extra_reg(self
):
1327 return _Reg(self
.name
)
1329 def remap(self
, value
, vector
):
1330 raise NotImplementedError()
1332 def assemble(self
, value
, insn
, prefix
):
1335 if isinstance(value
, str):
1336 value
= value
.lower()
1337 if value
.startswith("%"):
1339 if value
.startswith("*"):
1340 if not isinstance(insn
, SVP64Instruction
):
1341 raise ValueError(value
)
1344 if value
.startswith(prefix
):
1345 if (self
.extra_reg
.or_zero
and (value
== f
"{prefix}0")):
1346 raise ValueError(value
)
1347 value
= value
[len(prefix
):]
1348 value
= int(value
, 0)
1350 if isinstance(insn
, SVP64Instruction
):
1351 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1353 for extra_idx
in self
.extra_idx
:
1354 if self
.record
.etype
is _SVEType
.EXTRA3
:
1355 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1356 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1357 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1359 raise ValueError(self
.record
.etype
)
1361 return super().assemble(value
=value
, insn
=insn
)
1363 def disassemble(self
, insn
,
1364 style
=Style
.NORMAL
, prefix
="", indent
=""):
1365 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1367 if (self
.extra_reg
.or_zero
and (value
== 0)):
1370 if style
>= Style
.VERBOSE
:
1371 mode
= "vector" if vector
else "scalar"
1372 yield f
"{indent}{self.name} ({mode})"
1373 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1374 yield f
"{indent}{indent}{', '.join(span)}"
1375 if isinstance(insn
, SVP64Instruction
):
1376 for extra_idx
in frozenset(self
.extra_idx
):
1377 if self
.record
.etype
is _SVEType
.NONE
:
1378 yield f
"{indent}{indent}extra[none]"
1380 etype
= repr(self
.record
.etype
).lower()
1381 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1383 vector
= "*" if vector
else ""
1384 yield f
"{vector}{prefix}{int(value)}"
1387 class SimpleRegisterOperand(ExtendableOperand
):
1388 def remap(self
, value
, vector
):
1390 extra
= (value
& 0b11)
1391 value
= (value
>> 2)
1393 extra
= (value
>> 5)
1394 value
= (value
& 0b11111)
1396 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1397 # (and shrink to a single bit if ok)
1398 if self
.record
.etype
is _SVEType
.EXTRA2
:
1400 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1401 assert (extra
& 0b01) == 0, \
1402 ("vector field %s cannot fit into EXTRA2" % value
)
1403 extra
= (0b10 |
(extra
>> 1))
1405 # range is r0-r63 in increments of 1
1406 assert (extra
>> 1) == 0, \
1407 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1409 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1411 # EXTRA3 vector bit needs marking
1414 raise ValueError(self
.record
.etype
)
1416 return (value
, extra
)
1419 class GPROperand(SimpleRegisterOperand
):
1420 def assemble(self
, insn
, value
):
1421 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1423 def disassemble(self
, insn
,
1424 style
=Style
.NORMAL
, indent
=""):
1425 prefix
= "" if (style
<= Style
.SHORT
) else "r"
1426 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1427 style
=style
, indent
=indent
)
1430 class GPRPairOperand(GPROperand
):
1434 class FPROperand(SimpleRegisterOperand
):
1435 def assemble(self
, insn
, value
):
1436 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1438 def disassemble(self
, insn
,
1439 style
=Style
.NORMAL
, indent
=""):
1440 prefix
= "" if (style
<= Style
.SHORT
) else "f"
1441 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1442 style
=style
, indent
=indent
)
1445 class FPRPairOperand(FPROperand
):
1449 class ConditionRegisterFieldOperand(ExtendableOperand
):
1450 def pattern(name_pattern
):
1451 (name
, pattern
) = name_pattern
1452 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1461 CR
= r
"(?:CR|cr)([0-9]+)"
1463 BIT
= rf
"({'|'.join(CONDS.keys())})"
1464 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1465 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1466 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1467 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1468 XCR
= fr
"{CR}\.{BIT}"
1469 PATTERNS
= tuple(map(pattern
, (
1474 ("BIT+CR", (LBIT
+ CR
)),
1475 ("CR+BIT", (CR
+ RBIT
)),
1476 ("BIT+CR*N", (LBIT
+ CRN
)),
1477 ("CR*N+BIT", (CRN
+ RBIT
)),
1478 ("BIT+N*CR", (LBIT
+ NCR
)),
1479 ("N*CR+BIT", (NCR
+ RBIT
)),
1482 def remap(self
, value
, vector
, regtype
):
1483 if regtype
is _RegType
.CR_5BIT
:
1484 subvalue
= (value
& 0b11)
1488 extra
= (value
& 0b1111)
1491 extra
= (value
>> 3)
1494 if self
.record
.etype
is _SVEType
.EXTRA2
:
1496 assert (extra
& 0b111) == 0, \
1497 "vector CR cannot fit into EXTRA2"
1498 extra
= (0b10 |
(extra
>> 3))
1500 assert (extra
>> 1) == 0, \
1501 "scalar CR cannot fit into EXTRA2"
1503 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1505 assert (extra
& 0b11) == 0, \
1506 "vector CR cannot fit into EXTRA3"
1507 extra
= (0b100 |
(extra
>> 2))
1509 assert (extra
>> 2) == 0, \
1510 "scalar CR cannot fit into EXTRA3"
1513 if regtype
is _RegType
.CR_5BIT
:
1514 value
= ((value
<< 2) | subvalue
)
1516 return (value
, extra
)
1518 def assemble(self
, insn
, value
):
1519 if isinstance(value
, str):
1522 if value
.startswith("*"):
1523 if not isinstance(insn
, SVP64Instruction
):
1524 raise ValueError(value
)
1528 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1529 match
= pattern
.match(value
)
1530 if match
is not None:
1531 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1532 values
= match
.groups()
1533 match
= dict(zip(keys
, values
))
1534 CR
= int(match
["CR"])
1538 N
= int(match
.get("N", "1"))
1539 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1540 value
= ((CR
* N
) + BIT
)
1547 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1549 def disassemble(self
, insn
,
1550 style
=Style
.NORMAL
, prefix
="", indent
=""):
1551 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1553 if style
>= Style
.VERBOSE
:
1554 mode
= "vector" if vector
else "scalar"
1555 yield f
"{indent}{self.name} ({mode})"
1556 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1557 yield f
"{indent}{indent}{', '.join(span)}"
1558 if isinstance(insn
, SVP64Instruction
):
1559 for extra_idx
in frozenset(self
.extra_idx
):
1560 if self
.record
.etype
is _SVEType
.NONE
:
1561 yield f
"{indent}{indent}extra[none]"
1563 etype
= repr(self
.record
.etype
).lower()
1564 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1566 vector
= "*" if vector
else ""
1567 CR
= int(value
>> 2)
1569 cond
= ("lt", "gt", "eq", "so")[CC
]
1570 if style
>= Style
.NORMAL
:
1572 if isinstance(insn
, SVP64Instruction
):
1573 yield f
"{vector}cr{CR}.{cond}"
1575 yield f
"4*cr{CR}+{cond}"
1579 yield f
"{vector}{prefix}{int(value)}"
1582 class CR3Operand(ConditionRegisterFieldOperand
):
1583 def remap(self
, value
, vector
):
1584 return super().remap(value
=value
, vector
=vector
,
1585 regtype
=_RegType
.CR_3BIT
)
1588 class CR5Operand(ConditionRegisterFieldOperand
):
1589 def remap(self
, value
, vector
):
1590 return super().remap(value
=value
, vector
=vector
,
1591 regtype
=_RegType
.CR_5BIT
)
1593 def sv_spec_enter(self
, value
, span
):
1594 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1595 return (value
, span
)
1597 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1598 value
= _selectconcat(value
, origin_value
[3:5])
1600 return (value
, span
)
1603 class EXTSOperand(SignedOperand
):
1604 field
: str # real name to report
1605 nz
: int = 0 # number of zeros
1606 fmt
: str = "d" # integer formatter
1608 def __init__(self
, record
, name
, field
, nz
=0, fmt
="d"):
1609 self
.__field
= field
1612 return super().__init
__(record
=record
, name
=name
)
1628 return self
.record
.fields
[self
.field
]
1630 def assemble(self
, insn
, value
):
1632 if isinstance(value
, str):
1633 value
= int(value
, 0)
1634 insn
[span
] = (value
>> self
.nz
)
1636 def disassemble(self
, insn
,
1637 style
=Style
.NORMAL
, indent
=""):
1639 value
= insn
[span
].to_signed_int()
1640 sign
= "-" if (value
< 0) else ""
1641 value
= (abs(value
) << self
.nz
)
1643 if style
>= Style
.VERBOSE
:
1644 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1645 zeros
= ("0" * self
.nz
)
1646 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1647 yield f
"{indent * 1}{hint}"
1648 yield f
"{indent * 2}{self.field}"
1649 yield f
"{indent * 3}{sign}{value:{self.fmt}}"
1650 yield f
"{indent * 3}{', '.join(span)}"
1652 yield f
"{sign}{value:{self.fmt}}"
1655 class TargetAddrOperand(EXTSOperand
):
1656 def __init__(self
, record
, name
, field
):
1657 return super().__init
__(record
=record
, name
=name
, field
=field
,
1661 class TargetAddrOperandLI(TargetAddrOperand
):
1662 def __init__(self
, record
, name
):
1663 return super().__init
__(record
=record
, name
=name
, field
="LI")
1666 class TargetAddrOperandBD(TargetAddrOperand
):
1667 def __init__(self
, record
, name
):
1668 return super().__init
__(record
=record
, name
=name
, field
="BD")
1671 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1672 def __init__(self
, record
, name
):
1673 return super().__init
__(record
=record
, name
=name
, field
="DS", nz
=2)
1676 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1677 def __init__(self
, record
, name
):
1678 return super().__init
__(record
=record
, name
=name
, field
="DQ", nz
=4)
1681 class DOperandDX(SignedOperand
):
1684 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1685 operands
= map(cls
, ("d0", "d1", "d2"))
1686 spans
= map(lambda operand
: operand
.span
, operands
)
1687 return sum(spans
, tuple())
1689 def disassemble(self
, insn
,
1690 style
=Style
.NORMAL
, indent
=""):
1692 value
= insn
[span
].to_signed_int()
1693 sign
= "-" if (value
< 0) else ""
1696 if style
>= Style
.VERBOSE
:
1703 for (subname
, subspan
) in mapping
.items():
1704 operand
= DynamicOperand(name
=subname
)
1706 span
= map(str, span
)
1707 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1708 yield f
"{indent}{indent}{indent}{sign}{value}"
1709 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1711 yield f
"{sign}{value}"
1714 class Instruction(_Mapping
):
1716 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1717 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1718 raise ValueError(bits
)
1720 if isinstance(value
, bytes
):
1721 if ((len(value
) * 8) != bits
):
1722 raise ValueError(f
"bit length mismatch")
1723 value
= int.from_bytes(value
, byteorder
=byteorder
)
1725 if isinstance(value
, int):
1726 value
= _SelectableInt(value
=value
, bits
=bits
)
1727 elif isinstance(value
, Instruction
):
1728 value
= value
.storage
1730 if not isinstance(value
, _SelectableInt
):
1731 raise ValueError(value
)
1734 if len(value
) != bits
:
1735 raise ValueError(value
)
1737 value
= _SelectableInt(value
=value
, bits
=bits
)
1739 return cls(storage
=value
)
1742 return hash(int(self
))
1744 def __getitem__(self
, key
):
1745 return self
.storage
.__getitem
__(key
)
1747 def __setitem__(self
, key
, value
):
1748 return self
.storage
.__setitem
__(key
, value
)
1750 def bytes(self
, byteorder
="little"):
1751 nr_bytes
= (len(self
.__class
__) // 8)
1752 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1755 def record(cls
, db
, entry
):
1758 raise KeyError(entry
)
1762 def operands(cls
, record
):
1763 yield from record
.operands
1766 def static_operands(cls
, record
):
1767 return filter(lambda operand
: isinstance(operand
, StaticOperand
),
1768 cls
.operands(record
=record
))
1771 def dynamic_operands(cls
, record
):
1772 return filter(lambda operand
: isinstance(operand
, DynamicOperand
),
1773 cls
.operands(record
=record
))
1775 def spec(self
, record
, prefix
):
1776 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1777 self
.spec_dynamic_operands(record
=record
)))
1779 static_operands
= []
1780 for (name
, value
) in self
.spec_static_operands(record
=record
):
1781 static_operands
.append(f
"{name}={value}")
1784 if dynamic_operands
:
1786 operands
+= ",".join(dynamic_operands
)
1789 operands
+= " ".join(static_operands
)
1791 return f
"{prefix}{record.name}{operands}"
1793 def spec_static_operands(self
, record
):
1794 for operand
in self
.static_operands(record
=record
):
1795 if not isinstance(operand
, (POStaticOperand
, XOStaticOperand
)):
1796 yield (operand
.name
, operand
.value
)
1798 def spec_dynamic_operands(self
, record
, style
=Style
.NORMAL
):
1802 for operand
in self
.dynamic_operands(record
=record
):
1804 value
= " ".join(operand
.disassemble(insn
=self
,
1805 style
=min(style
, Style
.NORMAL
)))
1807 name
= f
"{imm_name}({name})"
1808 value
= f
"{imm_value}({value})"
1810 if isinstance(operand
, ImmediateOperand
):
1818 def assemble(cls
, record
, arguments
=None):
1819 if arguments
is None:
1822 insn
= cls
.integer(value
=0)
1824 for operand
in cls
.static_operands(record
=record
):
1825 operand
.assemble(insn
=insn
)
1827 arguments
= Arguments(record
=record
,
1828 arguments
=arguments
, operands
=cls
.dynamic_operands(record
=record
))
1829 for (value
, operand
) in arguments
:
1830 operand
.assemble(insn
=insn
, value
=value
)
1834 def disassemble(self
, record
,
1836 style
=Style
.NORMAL
):
1837 raise NotImplementedError()
1840 class WordInstruction(Instruction
):
1841 _
: _Field
= range(0, 32)
1842 PO
: _Field
= range(0, 6)
1845 def integer(cls
, value
, byteorder
="little"):
1846 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1851 for idx
in range(32):
1852 bit
= int(self
[idx
])
1854 return "".join(map(str, bits
))
1856 def disassemble(self
, record
,
1858 style
=Style
.NORMAL
):
1859 if style
<= Style
.SHORT
:
1862 blob
= self
.bytes(byteorder
=byteorder
)
1863 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1867 yield f
"{blob}.long 0x{int(self):08x}"
1870 # awful temporary hack: workaround for ld-update
1871 # https://bugs.libre-soc.org/show_bug.cgi?id=1056#c2
1872 # XXX TODO must check that *EXTENDED* RA != extended-RT
1873 if (record
.svp64
is not None and
1874 record
.mode
== _SVMode
.LDST_IMM
and
1875 'u' in record
.name
):
1876 yield f
"{blob}.long 0x{int(self):08x}"
1880 if style
is Style
.LEGACY
:
1882 for operand
in self
.dynamic_operands(record
=record
):
1883 if isinstance(operand
, (GPRPairOperand
, FPRPairOperand
)):
1886 if style
is Style
.LEGACY
and (paired
or record
.ppc
.unofficial
):
1887 yield f
"{blob}.long 0x{int(self):08x}"
1889 operands
= tuple(map(_operator
.itemgetter(1),
1890 self
.spec_dynamic_operands(record
=record
, style
=style
)))
1892 operands
= ",".join(operands
)
1893 yield f
"{blob}{record.name} {operands}"
1895 yield f
"{blob}{record.name}"
1897 if style
>= Style
.VERBOSE
:
1899 binary
= self
.binary
1900 spec
= self
.spec(record
=record
, prefix
="")
1901 yield f
"{indent}spec"
1902 yield f
"{indent}{indent}{spec}"
1903 yield f
"{indent}pcode"
1904 for stmt
in record
.mdwn
.pcode
:
1905 yield f
"{indent}{indent}{stmt}"
1906 yield f
"{indent}binary"
1907 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1908 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1909 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1910 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1911 yield f
"{indent}opcodes"
1912 for opcode
in record
.opcodes
:
1913 yield f
"{indent}{indent}{opcode!r}"
1914 for operand
in self
.operands(record
=record
):
1915 yield from operand
.disassemble(insn
=self
,
1916 style
=style
, indent
=indent
)
1920 class PrefixedInstruction(Instruction
):
1921 class Prefix(WordInstruction
.remap(range(0, 32))):
1924 class Suffix(WordInstruction
.remap(range(32, 64))):
1927 _
: _Field
= range(64)
1933 def integer(cls
, value
, byteorder
="little"):
1934 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
1937 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
1938 def transform(value
):
1939 return WordInstruction
.integer(value
=value
,
1940 byteorder
=byteorder
)[0:32]
1942 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
1943 value
= _selectconcat(prefix
, suffix
)
1945 return super().integer(bits
=64, value
=value
)
1948 class Mode(_Mapping
):
1949 _
: _Field
= range(0, 5)
1950 sel
: _Field
= (0, 1)
1953 class ExtraRM(_Mapping
):
1954 _
: _Field
= range(0, 9)
1957 class Extra2RM(ExtraRM
):
1958 idx0
: _Field
= range(0, 2)
1959 idx1
: _Field
= range(2, 4)
1960 idx2
: _Field
= range(4, 6)
1961 idx3
: _Field
= range(6, 8)
1963 def __getitem__(self
, key
):
1969 _SVExtra
.Idx0
: self
.idx0
,
1970 _SVExtra
.Idx1
: self
.idx1
,
1971 _SVExtra
.Idx2
: self
.idx2
,
1972 _SVExtra
.Idx3
: self
.idx3
,
1975 def __setitem__(self
, key
, value
):
1976 self
[key
].assign(value
)
1979 class Extra3RM(ExtraRM
):
1980 idx0
: _Field
= range(0, 3)
1981 idx1
: _Field
= range(3, 6)
1982 idx2
: _Field
= range(6, 9)
1984 def __getitem__(self
, key
):
1989 _SVExtra
.Idx0
: self
.idx0
,
1990 _SVExtra
.Idx1
: self
.idx1
,
1991 _SVExtra
.Idx2
: self
.idx2
,
1994 def __setitem__(self
, key
, value
):
1995 self
[key
].assign(value
)
1998 class BaseRM(_Mapping
):
1999 _
: _Field
= range(24)
2000 mmode
: _Field
= (0,)
2001 mask
: _Field
= range(1, 4)
2002 elwidth
: _Field
= range(4, 6)
2003 ewsrc
: _Field
= range(6, 8)
2004 subvl
: _Field
= range(8, 10)
2005 mode
: Mode
.remap(range(19, 24))
2006 smask_extra322
: _Field
= (6,7,18,) # LDST_IDX is EXTRA332
2007 smask
: _Field
= range(16, 19) # everything else use this
2008 extra
: ExtraRM
.remap(range(10, 19))
2009 extra2
: Extra2RM
.remap(range(10, 19))
2010 extra3
: Extra3RM
.remap(range(10, 19))
2011 # XXX extra332 = (extra3[0], extra3[1], extra2[3])
2013 def specifiers(self
, record
):
2014 subvl
= int(self
.subvl
)
2022 def disassemble(self
, style
=Style
.NORMAL
):
2023 if style
>= Style
.VERBOSE
:
2025 for (name
, span
) in self
.traverse(path
="RM"):
2026 value
= self
.storage
[span
]
2028 yield f
"{indent}{int(value):0{value.bits}b}"
2029 yield f
"{indent}{', '.join(map(str, span))}"
2032 class FFRc1BaseRM(BaseRM
):
2033 def specifiers(self
, record
, mode
):
2034 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
2035 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
2036 mask
= int(_selectconcat(CR
, inv
))
2037 predicate
= PredicateBaseRM
.predicate(True, mask
)
2038 yield f
"{mode}={predicate}"
2040 yield from super().specifiers(record
=record
)
2043 class FFRc0BaseRM(BaseRM
):
2044 def specifiers(self
, record
, mode
):
2046 inv
= "~" if self
.inv
else ""
2047 yield f
"{mode}={inv}RC1"
2049 yield from super().specifiers(record
=record
)
2052 class SatBaseRM(BaseRM
):
2053 def specifiers(self
, record
):
2059 yield from super().specifiers(record
=record
)
2062 class ZZBaseRM(BaseRM
):
2063 def specifiers(self
, record
):
2067 yield from super().specifiers(record
=record
)
2070 class ZZCombinedBaseRM(BaseRM
):
2071 def specifiers(self
, record
):
2072 if self
.sz
and self
.dz
:
2079 yield from super().specifiers(record
=record
)
2082 class DZBaseRM(BaseRM
):
2083 def specifiers(self
, record
):
2087 yield from super().specifiers(record
=record
)
2090 class SZBaseRM(BaseRM
):
2091 def specifiers(self
, record
):
2095 yield from super().specifiers(record
=record
)
2098 class MRBaseRM(BaseRM
):
2099 def specifiers(self
, record
):
2105 yield from super().specifiers(record
=record
)
2108 class ElsBaseRM(BaseRM
):
2109 def specifiers(self
, record
):
2113 yield from super().specifiers(record
=record
)
2116 class WidthBaseRM(BaseRM
):
2118 def width(FP
, width
):
2127 width
= ("fp" + width
)
2130 def specifiers(self
, record
):
2131 # elwidths: use "w=" if same otherwise dw/sw
2132 # FIXME this should consider FP instructions
2134 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
2135 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2136 if record
.svp64
.mode
is _SVMode
.CROP
:
2140 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2149 yield from super().specifiers(record
=record
)
2152 class PredicateBaseRM(BaseRM
):
2154 def predicate(CR
, mask
):
2157 (False, 0b001): "1<<r3",
2158 (False, 0b010): "r3",
2159 (False, 0b011): "~r3",
2160 (False, 0b100): "r10",
2161 (False, 0b101): "~r10",
2162 (False, 0b110): "r30",
2163 (False, 0b111): "~r30",
2165 (True, 0b000): "lt",
2166 (True, 0b001): "ge",
2167 (True, 0b010): "gt",
2168 (True, 0b011): "le",
2169 (True, 0b100): "eq",
2170 (True, 0b101): "ne",
2171 (True, 0b110): "so",
2172 (True, 0b111): "ns",
2175 def specifiers(self
, record
):
2176 # predication - single and twin
2177 # use "m=" if same otherwise sm/dm
2178 CR
= (int(self
.mmode
) == 1)
2179 mask
= int(self
.mask
)
2180 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
2181 if record
.svp64
.ptype
is _SVPType
.P2
:
2182 # LDST_IDX smask moving to extra322 but not straight away (False)
2183 if False and record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2184 smask
= int(self
.smask_extra332
)
2186 smask
= int(self
.smask
)
2187 sm
= PredicateBaseRM
.predicate(CR
, smask
)
2196 yield from super().specifiers(record
=record
)
2199 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
2203 class SEABaseRM(BaseRM
):
2204 def specifiers(self
, record
):
2208 yield from super().specifiers(record
=record
)
2211 class VLiBaseRM(BaseRM
):
2212 def specifiers(self
, record
):
2216 yield from super().specifiers(record
=record
)
2219 class NormalBaseRM(PredicateWidthBaseRM
):
2222 https://libre-soc.org/openpower/sv/normal/
2227 class NormalSimpleRM(ZZCombinedBaseRM
, NormalBaseRM
):
2228 """normal: simple mode"""
2232 def specifiers(self
, record
):
2233 yield from super().specifiers(record
=record
)
2236 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
2237 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
2241 class NormalFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, NormalBaseRM
):
2242 """normal: Rc=1: ffirst CR sel"""
2245 CR
: BaseRM
.mode
[3, 4]
2247 def specifiers(self
, record
):
2248 yield from super().specifiers(record
=record
, mode
="ff")
2251 class NormalFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
2252 """normal: Rc=0: ffirst z/nonz"""
2257 def specifiers(self
, record
):
2258 yield from super().specifiers(record
=record
, mode
="ff")
2261 class NormalSatRM(SatBaseRM
, ZZCombinedBaseRM
, NormalBaseRM
):
2262 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2268 class NormalRM(NormalBaseRM
):
2269 simple
: NormalSimpleRM
2271 ffrc1
: NormalFFRc1RM
2272 ffrc0
: NormalFFRc0RM
2276 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2278 LD/ST Immediate mode
2279 https://libre-soc.org/openpower/sv/ldst/
2284 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2285 """ld/st immediate: simple mode"""
2286 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2287 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2293 def specifiers(self
, record
):
2299 yield from super().specifiers(record
=record
)
2302 class LDSTFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2303 """ld/st immediate&indexed: Rc=1: ffirst CR sel"""
2306 CR
: BaseRM
.mode
[3, 4]
2308 def specifiers(self
, record
):
2309 yield from super().specifiers(record
=record
, mode
="ff")
2312 class LDSTFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2313 """ld/st immediate&indexed: Rc=0: ffirst z/nonz"""
2318 def specifiers(self
, record
):
2319 yield from super().specifiers(record
=record
, mode
="ff")
2322 class LDSTImmRM(LDSTImmBaseRM
):
2323 simple
: LDSTImmSimpleRM
2328 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2331 https://libre-soc.org/openpower/sv/ldst/
2336 class LDSTIdxSimpleRM(SEABaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2337 """ld/st index: simple mode (includes element-strided and Signed-EA)"""
2338 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2345 def specifiers(self
, record
):
2351 yield from super().specifiers(record
=record
)
2354 class LDSTIdxRM(LDSTIdxBaseRM
):
2355 simple
: LDSTIdxSimpleRM
2361 class CROpBaseRM(BaseRM
):
2364 https://libre-soc.org/openpower/sv/cr_ops/
2369 class CROpSimpleRM(PredicateBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2370 """crop: simple mode"""
2375 def specifiers(self
, record
):
2377 yield "rg" # simple CR Mode reports /rg
2379 yield from super().specifiers(record
=record
)
2382 class CROpMRRM(MRBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2383 """crop: scalar reduce mode (mapreduce)"""
2389 class CROpFF5RM(FFRc0BaseRM
, PredicateBaseRM
, VLiBaseRM
, DZBaseRM
,
2390 SZBaseRM
, CROpBaseRM
):
2391 """crop: ffirst 5-bit mode"""
2398 def specifiers(self
, record
):
2399 yield from super().specifiers(record
=record
, mode
="ff")
2402 # FIXME: almost everything in this class contradicts the specs (it doesn't)
2403 # The modes however are swapped: 5-bit is 3-bit, 3-bit is 5-bit
2404 class CROpFF3RM(FFRc1BaseRM
, PredicateBaseRM
, VLiBaseRM
, ZZBaseRM
, CROpBaseRM
):
2405 """cr_op: ffirst 3-bit mode"""
2411 def specifiers(self
, record
):
2412 yield from super().specifiers(record
=record
, mode
="ff")
2415 class CROpRM(CROpBaseRM
):
2416 simple
: CROpSimpleRM
2422 # ********************
2424 # https://libre-soc.org/openpower/sv/branches/
2425 class BranchBaseRM(BaseRM
):
2435 def specifiers(self
, record
):
2447 raise ValueError(self
.sz
)
2459 # Branch modes lack source mask.
2460 # Therefore a custom code is needed.
2461 CR
= (int(self
.mmode
) == 1)
2462 mask
= int(self
.mask
)
2463 m
= PredicateBaseRM
.predicate(CR
, mask
)
2467 yield from super().specifiers(record
=record
)
2470 class BranchSimpleRM(BranchBaseRM
):
2471 """branch: simple mode"""
2475 class BranchVLSRM(BranchBaseRM
):
2476 """branch: VLSET mode"""
2480 def specifiers(self
, record
):
2486 }[int(self
.VSb
), int(self
.VLi
)]
2488 yield from super().specifiers(record
=record
)
2491 class BranchCTRRM(BranchBaseRM
):
2492 """branch: CTR-test mode"""
2495 def specifiers(self
, record
):
2501 yield from super().specifiers(record
=record
)
2504 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2505 """branch: CTR-test+VLSET mode"""
2509 class BranchRM(BranchBaseRM
):
2510 simple
: BranchSimpleRM
2513 ctrvls
: BranchCTRVLSRM
2524 @_dataclasses.dataclass(eq
=True, frozen
=True)
2529 def match(cls
, desc
, record
):
2530 raise NotImplementedError()
2532 def validate(self
, others
):
2535 def assemble(self
, insn
):
2536 raise NotImplementedError()
2539 @_dataclasses.dataclass(eq
=True, frozen
=True)
2540 class SpecifierWidth(Specifier
):
2544 def match(cls
, desc
, record
, etalon
):
2545 (mode
, _
, value
) = desc
.partition("=")
2547 value
= value
.strip()
2550 width
= _SVP64Width(value
)
2552 return cls(record
=record
, width
=width
)
2555 @_dataclasses.dataclass(eq
=True, frozen
=True)
2556 class SpecifierW(SpecifierWidth
):
2558 def match(cls
, desc
, record
):
2559 return super().match(desc
=desc
, record
=record
, etalon
="w")
2561 def assemble(self
, insn
):
2562 selector
= insn
.select(record
=self
.record
)
2563 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2564 selector
.ewsrc
= self
.width
.value
2565 selector
.elwidth
= self
.width
.value
2568 @_dataclasses.dataclass(eq
=True, frozen
=True)
2569 class SpecifierSW(SpecifierWidth
):
2571 def match(cls
, desc
, record
):
2572 if record
.svp64
.mode
is _SVMode
.CROP
:
2574 return super().match(desc
=desc
, record
=record
, etalon
="sw")
2576 def assemble(self
, insn
):
2577 selector
= insn
.select(record
=self
.record
)
2578 selector
.ewsrc
= self
.width
.value
2581 @_dataclasses.dataclass(eq
=True, frozen
=True)
2582 class SpecifierDW(SpecifierWidth
):
2584 def match(cls
, desc
, record
):
2585 return super().match(desc
=desc
, record
=record
, etalon
="dw")
2587 def assemble(self
, insn
):
2588 selector
= insn
.select(record
=self
.record
)
2589 selector
.elwidth
= self
.width
.value
2592 @_dataclasses.dataclass(eq
=True, frozen
=True)
2593 class SpecifierSubVL(Specifier
):
2597 def match(cls
, desc
, record
):
2599 value
= _SVP64SubVL(desc
)
2603 return cls(record
=record
, value
=value
)
2605 def assemble(self
, insn
):
2606 selector
= insn
.select(record
=self
.record
)
2607 selector
.subvl
= int(self
.value
.value
)
2610 @_dataclasses.dataclass(eq
=True, frozen
=True)
2611 class SpecifierPredicate(Specifier
):
2616 def match(cls
, desc
, record
, mode_match
, pred_match
):
2617 (mode
, _
, pred
) = desc
.partition("=")
2620 if not mode_match(mode
):
2623 pred
= _SVP64Pred(pred
.strip())
2624 if not pred_match(pred
):
2625 raise ValueError(pred
)
2627 return cls(record
=record
, mode
=mode
, pred
=pred
)
2630 @_dataclasses.dataclass(eq
=True, frozen
=True)
2631 class SpecifierFF(SpecifierPredicate
):
2633 def match(cls
, desc
, record
):
2634 return super().match(desc
=desc
, record
=record
,
2635 mode_match
=lambda mode_arg
: mode_arg
== "ff",
2636 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2641 def assemble(self
, insn
):
2642 selector
= insn
.select(record
=self
.record
)
2643 if selector
.mode
.sel
!= 0:
2644 raise ValueError("cannot override mode")
2645 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2646 selector
.mode
.sel
= 0b01
2647 # HACK: please finally provide correct logic for CRs.
2648 if self
.pred
in (_SVP64Pred
.RC1
, _SVP64Pred
.RC1_N
):
2649 selector
.mode
[2] = (self
.pred
is _SVP64Pred
.RC1_N
)
2651 selector
.mode
[2] = self
.pred
.inv
2652 selector
.mode
[3, 4] = self
.pred
.state
2654 selector
.mode
.sel
= 0b01 if self
.mode
== "ff" else 0b11
2655 selector
.inv
= self
.pred
.inv
2657 selector
.CR
= self
.pred
.state
2659 selector
.RC1
= self
.pred
.state
2662 @_dataclasses.dataclass(eq
=True, frozen
=True)
2663 class SpecifierMask(SpecifierPredicate
):
2665 def match(cls
, desc
, record
, mode
):
2666 return super().match(desc
=desc
, record
=record
,
2667 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2668 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2673 def assemble(self
, insn
):
2674 raise NotImplementedError()
2677 @_dataclasses.dataclass(eq
=True, frozen
=True)
2678 class SpecifierM(SpecifierMask
):
2680 def match(cls
, desc
, record
):
2681 return super().match(desc
=desc
, record
=record
, mode
="m")
2683 def validate(self
, others
):
2685 if isinstance(spec
, SpecifierSM
):
2686 raise ValueError("source-mask and predicate mask conflict")
2687 elif isinstance(spec
, SpecifierDM
):
2688 raise ValueError("dest-mask and predicate mask conflict")
2690 def assemble(self
, insn
):
2691 selector
= insn
.select(record
=self
.record
)
2692 selector
.mask
= int(self
.pred
)
2693 if ((self
.record
.ptype
is _SVPType
.P2
) and
2694 (self
.record
.svp64
.mode
is not _SVMode
.BRANCH
)):
2695 selector
.smask
= int(self
.pred
)
2696 # LDST_IDX smask moving to extra322 but not straight away (False)
2697 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2698 selector
.smask_extra332
= int(self
.pred
)
2700 selector
.smask
= int(self
.pred
)
2702 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2705 @_dataclasses.dataclass(eq
=True, frozen
=True)
2706 class SpecifierSM(SpecifierMask
):
2708 def match(cls
, desc
, record
):
2709 return super().match(desc
=desc
, record
=record
, mode
="sm")
2711 def validate(self
, others
):
2712 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2713 raise ValueError("source-mask on non-twin predicate")
2715 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2718 if isinstance(spec
, SpecifierDM
):
2722 raise ValueError("missing dest-mask in CR twin predication")
2723 if self
.pred
.mode
!= twin
.pred
.mode
:
2724 raise ValueError(f
"predicate masks mismatch: "
2725 f
"{self.pred!r} vs {twin.pred!r}")
2727 def assemble(self
, insn
):
2728 selector
= insn
.select(record
=self
.record
)
2729 # LDST_IDX smask moving to extra322 but not straight away (False)
2730 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2731 selector
.smask_extra332
= int(self
.pred
)
2733 selector
.smask
= int(self
.pred
)
2734 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2737 @_dataclasses.dataclass(eq
=True, frozen
=True)
2738 class SpecifierDM(SpecifierMask
):
2740 def match(cls
, desc
, record
):
2741 return super().match(desc
=desc
, record
=record
, mode
="dm")
2743 def validate(self
, others
):
2744 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2745 raise ValueError("dest-mask on non-twin predicate")
2747 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2750 if isinstance(spec
, SpecifierSM
):
2754 raise ValueError("missing source-mask in CR twin predication")
2755 if self
.pred
.mode
!= twin
.pred
.mode
:
2756 raise ValueError(f
"predicate masks mismatch: "
2757 f
"{self.pred!r} vs {twin.pred!r}")
2759 def assemble(self
, insn
):
2760 selector
= insn
.select(record
=self
.record
)
2761 selector
.mask
= int(self
.pred
)
2762 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2765 @_dataclasses.dataclass(eq
=True, frozen
=True)
2766 class SpecifierZZ(Specifier
):
2768 def match(cls
, desc
, record
):
2772 return cls(record
=record
)
2774 def validate(self
, others
):
2776 # Since zz takes precedence (overrides) sz and dz,
2777 # treat them as mutually exclusive.
2778 if isinstance(spec
, (SpecifierSZ
, SpecifierDZ
)):
2779 raise ValueError("mutually exclusive predicate masks")
2781 def assemble(self
, insn
):
2782 selector
= insn
.select(record
=self
.record
)
2783 if hasattr(selector
, "zz"): # this should be done in a different way
2790 @_dataclasses.dataclass(eq
=True, frozen
=True)
2791 class SpecifierXZ(Specifier
):
2793 hint
: str = _dataclasses
.field(repr=False)
2796 def match(cls
, desc
, record
, etalon
, hint
):
2800 return cls(desc
=desc
, record
=record
, hint
=hint
)
2802 def validate(self
, others
):
2803 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2804 raise ValueError(f
"{self.hint} on non-twin predicate")
2806 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2809 if isinstance(spec
, SpecifierXZ
):
2813 raise ValueError(f
"missing {self.hint} in CR twin predication")
2814 if self
.pred
!= twin
.pred
:
2815 raise ValueError(f
"predicate masks mismatch: "
2816 f
"{self.pred!r} vs {twin.pred!r}")
2818 def assemble(self
, insn
):
2819 selector
= insn
.select(record
=self
.record
)
2820 setattr(selector
, self
.desc
, 1)
2823 @_dataclasses.dataclass(eq
=True, frozen
=True)
2824 class SpecifierSZ(SpecifierXZ
):
2826 def match(cls
, desc
, record
):
2827 return super().match(desc
=desc
, record
=record
,
2828 etalon
="sz", hint
="source-mask")
2830 def validate(self
, others
):
2832 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2833 if isinstance(spec
, SpecifierFF
):
2834 raise ValueError("source-zero not allowed in ff mode")
2837 @_dataclasses.dataclass(eq
=True, frozen
=True)
2838 class SpecifierDZ(SpecifierXZ
):
2840 def match(cls
, desc
, record
):
2841 return super().match(desc
=desc
, record
=record
,
2842 etalon
="dz", hint
="dest-mask")
2844 def validate(self
, others
):
2846 if ((self
.record
.svp64
.mode
is not _SVMode
.CROP
) and
2847 isinstance(spec
, SpecifierFF
) and
2848 (spec
.pred
.mode
is _SVP64PredMode
.RC1
)):
2849 raise ValueError(f
"dest-zero not allowed in ff mode BO")
2852 @_dataclasses.dataclass(eq
=True, frozen
=True)
2853 class SpecifierEls(Specifier
):
2855 def match(cls
, desc
, record
):
2859 if record
.svp64
.mode
not in (_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
):
2860 raise ValueError("els is only valid in ld/st modes, not "
2861 "%s" % str(self
.record
.svp64
.mode
))
2863 return cls(record
=record
)
2865 def assemble(self
, insn
):
2866 if self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
: # stride mode
2867 insn
.prefix
.rm
.mode
[1] = 0
2869 selector
= insn
.select(record
=self
.record
)
2874 @_dataclasses.dataclass(eq
=True, frozen
=True)
2875 class SpecifierSEA(Specifier
):
2877 def match(cls
, desc
, record
):
2881 return cls(record
=record
)
2883 def validate(self
, others
):
2884 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
:
2885 raise ValueError("sea is only valid in ld/st modes, not "
2886 "%s" % str(self
.record
.svp64
.mode
))
2889 if isinstance(spec
, SpecifierFF
):
2890 raise ValueError(f
"sea cannot be used in ff mode")
2892 def assemble(self
, insn
):
2893 selector
= insn
.select(record
=self
.record
)
2894 if selector
.mode
.sel
not in (0b10, 0b00):
2895 raise ValueError("sea is only valid for normal and els modes, "
2896 "not %d" % int(selector
.mode
.sel
))
2900 @_dataclasses.dataclass(eq
=True, frozen
=True)
2901 class SpecifierSat(Specifier
):
2906 def match(cls
, desc
, record
, etalon
, sign
):
2910 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.LDST_IMM
,
2912 raise ValueError("only normal, ld/st imm and "
2913 "ld/st idx modes supported")
2915 return cls(record
=record
, desc
=desc
, sign
=sign
)
2917 def assemble(self
, insn
):
2918 selector
= insn
.select(record
=self
.record
)
2919 selector
.mode
[0] = 0b1
2920 selector
.mode
[1] = 0b0
2921 selector
.N
= int(self
.sign
)
2924 @_dataclasses.dataclass(eq
=True, frozen
=True)
2925 class SpecifierSatS(SpecifierSat
):
2927 def match(cls
, desc
, record
):
2928 return super().match(desc
=desc
, record
=record
,
2929 etalon
="sats", sign
=True)
2932 @_dataclasses.dataclass(eq
=True, frozen
=True)
2933 class SpecifierSatU(SpecifierSat
):
2935 def match(cls
, desc
, record
):
2936 return super().match(desc
=desc
, record
=record
,
2937 etalon
="satu", sign
=False)
2940 @_dataclasses.dataclass(eq
=True, frozen
=True)
2941 class SpecifierMapReduce(Specifier
):
2945 def match(cls
, record
, RG
):
2946 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2947 raise ValueError("only normal and crop modes supported")
2949 return cls(record
=record
, RG
=RG
)
2951 def assemble(self
, insn
):
2952 selector
= insn
.select(record
=self
.record
)
2953 if self
.record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2954 raise ValueError("only normal and crop modes supported")
2955 selector
.mode
[0] = 0
2956 selector
.mode
[1] = 0
2957 selector
.mode
[2] = 1
2958 selector
.RG
= self
.RG
2961 @_dataclasses.dataclass(eq
=True, frozen
=True)
2962 class SpecifierMR(SpecifierMapReduce
):
2964 def match(cls
, desc
, record
):
2968 return super().match(record
=record
, RG
=False)
2971 @_dataclasses.dataclass(eq
=True, frozen
=True)
2972 class SpecifierMRR(SpecifierMapReduce
):
2974 def match(cls
, desc
, record
):
2978 return super().match(record
=record
, RG
=True)
2981 @_dataclasses.dataclass(eq
=True, frozen
=True)
2982 class SpecifierBranch(Specifier
):
2984 def match(cls
, desc
, record
, etalon
):
2988 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
2989 raise ValueError("only branch modes supported")
2991 return cls(record
=record
)
2994 @_dataclasses.dataclass(eq
=True, frozen
=True)
2995 class SpecifierAll(SpecifierBranch
):
2997 def match(cls
, desc
, record
):
2998 return super().match(desc
=desc
, record
=record
, etalon
="all")
3000 def assemble(self
, insn
):
3001 selector
= insn
.select(record
=self
.record
)
3005 @_dataclasses.dataclass(eq
=True, frozen
=True)
3006 class SpecifierSNZ(Specifier
):
3008 def match(cls
, desc
, record
):
3012 if record
.svp64
.mode
not in (_SVMode
.BRANCH
, _SVMode
.CROP
):
3013 raise ValueError("only branch and crop modes supported")
3015 return cls(record
=record
)
3017 def assemble(self
, insn
):
3018 selector
= insn
.select(record
=self
.record
)
3019 if self
.record
.svp64
.mode
in (_SVMode
.CROP
, _SVMode
.BRANCH
):
3021 if self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3024 raise ValueError("only branch and crop modes supported")
3027 @_dataclasses.dataclass(eq
=True, frozen
=True)
3028 class SpecifierSL(SpecifierBranch
):
3030 def match(cls
, desc
, record
):
3031 return super().match(desc
=desc
, record
=record
, etalon
="sl")
3033 def assemble(self
, insn
):
3034 selector
= insn
.select(record
=self
.record
)
3038 @_dataclasses.dataclass(eq
=True, frozen
=True)
3039 class SpecifierSLu(SpecifierBranch
):
3041 def match(cls
, desc
, record
):
3042 return super().match(desc
=desc
, record
=record
, etalon
="slu")
3044 def assemble(self
, insn
):
3045 selector
= insn
.select(record
=self
.record
)
3049 @_dataclasses.dataclass(eq
=True, frozen
=True)
3050 class SpecifierLRu(SpecifierBranch
):
3052 def match(cls
, desc
, record
):
3053 return super().match(desc
=desc
, record
=record
, etalon
="lru")
3055 def assemble(self
, insn
):
3056 selector
= insn
.select(record
=self
.record
)
3060 @_dataclasses.dataclass(eq
=True, frozen
=True)
3061 class SpecifierVSXX(SpecifierBranch
):
3066 def match(cls
, desc
, record
, etalon
, VSb
, VLi
):
3070 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3071 raise ValueError("only branch modes supported")
3073 return cls(record
=record
, VSb
=VSb
, VLi
=VLi
)
3075 def assemble(self
, insn
):
3076 selector
= insn
.select(record
=self
.record
)
3078 selector
.VSb
= int(self
.VSb
)
3079 selector
.VLi
= int(self
.VLi
)
3082 @_dataclasses.dataclass(eq
=True, frozen
=True)
3083 class SpecifierVS(SpecifierVSXX
):
3085 def match(cls
, desc
, record
):
3086 return super().match(desc
=desc
, record
=record
,
3087 etalon
="vs", VSb
=False, VLi
=False)
3090 @_dataclasses.dataclass(eq
=True, frozen
=True)
3091 class SpecifierVSi(SpecifierVSXX
):
3093 def match(cls
, desc
, record
):
3094 return super().match(desc
=desc
, record
=record
,
3095 etalon
="vsi", VSb
=False, VLi
=True)
3098 @_dataclasses.dataclass(eq
=True, frozen
=True)
3099 class SpecifierVSb(SpecifierVSXX
):
3101 def match(cls
, desc
, record
):
3102 return super().match(desc
=desc
, record
=record
,
3103 etalon
="vsb", VSb
=True, VLi
=False)
3106 @_dataclasses.dataclass(eq
=True, frozen
=True)
3107 class SpecifierVSbi(SpecifierVSXX
):
3109 def match(cls
, desc
, record
):
3110 return super().match(desc
=desc
, record
=record
,
3111 etalon
="vsbi", VSb
=True, VLi
=True)
3114 @_dataclasses.dataclass(eq
=True, frozen
=True)
3115 class SpecifierCTX(Specifier
):
3119 def match(cls
, desc
, record
, etalon
, CTi
):
3123 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3124 raise ValueError("only branch modes supported")
3126 return cls(record
=record
, CTi
=CTi
)
3128 def assemble(self
, insn
):
3129 selector
= insn
.select(record
=self
.record
)
3131 selector
.CTi
= int(self
.CTi
)
3134 @_dataclasses.dataclass(eq
=True, frozen
=True)
3135 class SpecifierCTR(SpecifierCTX
):
3137 def match(cls
, desc
, record
):
3138 return super().match(desc
=desc
, record
=record
,
3139 etalon
="ctr", CTi
=False)
3142 @_dataclasses.dataclass(eq
=True, frozen
=True)
3143 class SpecifierCTi(SpecifierCTX
):
3145 def match(cls
, desc
, record
):
3146 return super().match(desc
=desc
, record
=record
,
3147 etalon
="cti", CTi
=True)
3150 @_dataclasses.dataclass(eq
=True, frozen
=True)
3151 class SpecifierPI(Specifier
):
3153 def match(cls
, desc
, record
):
3157 if record
.svp64
.mode
not in [_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
]:
3158 raise ValueError("only ld/st imm/idx mode supported")
3160 return cls(record
=record
)
3162 def assemble(self
, insn
):
3163 selector
= insn
.select(record
=self
.record
)
3164 selector
.mode
[2] = 0b1
3168 @_dataclasses.dataclass(eq
=True, frozen
=True)
3169 class SpecifierLF(Specifier
):
3171 def match(cls
, desc
, record
):
3175 if record
.svp64
.mode
is not _SVMode
.LDST_IMM
:
3176 raise ValueError("only ld/st imm mode supported")
3178 return cls(record
=record
)
3180 def assemble(self
, insn
):
3181 selector
= insn
.select(record
=self
.record
)
3182 selector
.mode
[1] = 0
3186 @_dataclasses.dataclass(eq
=True, frozen
=True)
3187 class SpecifierVLi(Specifier
):
3189 def match(cls
, desc
, record
):
3193 return cls(record
=record
)
3195 def validate(self
, others
):
3197 if isinstance(spec
, SpecifierFF
):
3200 raise ValueError("VLi only allowed in failfirst")
3202 def assemble(self
, insn
):
3203 selector
= insn
.select(record
=self
.record
)
3204 selector
.mode
[1] = 1
3208 class Specifiers(tuple):
3243 def __new__(cls
, items
, record
):
3244 def transform(item
):
3245 for spec_cls
in cls
.SPECS
:
3246 spec
= spec_cls
.match(item
, record
=record
)
3247 if spec
is not None:
3249 raise ValueError(item
)
3251 # TODO: remove this hack
3252 items
= dict.fromkeys(items
)
3256 items
= tuple(items
)
3258 specs
= tuple(map(transform
, items
))
3259 for (index
, spec
) in enumerate(specs
):
3260 head
= specs
[:index
]
3261 tail
= specs
[index
+ 1:]
3262 spec
.validate(others
=(head
+ tail
))
3264 return super().__new
__(cls
, specs
)
3267 class SVP64OperandMeta(type):
3268 class SVP64NonZeroOperand(NonZeroOperand
):
3269 def assemble(self
, insn
, value
):
3270 if isinstance(value
, str):
3271 value
= int(value
, 0)
3272 if not isinstance(value
, int):
3273 raise ValueError("non-integer operand")
3275 # FIXME: this is really weird
3276 if self
.record
.name
in ("svstep", "svstep."):
3277 value
+= 1 # compensation
3279 return super().assemble(value
=value
, insn
=insn
)
3281 class SVP64XOStaticOperand(SpanStaticOperand
):
3282 def __init__(self
, record
, value
, span
):
3283 return super().__init
__(record
=record
, name
="XO",
3284 value
=value
, span
=span
)
3287 NonZeroOperand
: SVP64NonZeroOperand
,
3288 XOStaticOperand
: SVP64XOStaticOperand
,
3291 def __new__(metacls
, name
, bases
, ns
):
3293 for (index
, base_cls
) in enumerate(bases
):
3294 bases
[index
] = metacls
.__TRANSFORM
.get(base_cls
, base_cls
)
3296 bases
= tuple(bases
)
3298 return super().__new
__(metacls
, name
, bases
, ns
)
3301 class SVP64Operand(Operand
, metaclass
=SVP64OperandMeta
):
3304 return tuple(map(lambda bit
: (bit
+ 32), super().span
))
3308 def __init__(self
, insn
, record
):
3310 self
.__record
= record
3311 return super().__init
__()
3314 return self
.rm
.__doc
__
3317 return repr(self
.rm
)
3325 return self
.__record
3329 rm
= getattr(self
.insn
.prefix
.rm
, self
.record
.svp64
.mode
.name
.lower())
3331 # The idea behind these tables is that they are now literally
3332 # in identical format to insndb.csv and minor_xx.csv and can
3333 # be done precisely as that. The only thing to watch out for
3334 # is the insertion of Rc=1 as a "mask/value" bit and likewise
3335 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
3338 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
3339 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3340 # mode Rc mask Rc member
3342 (0b000000, 0b111000, "simple"), # simple (no Rc)
3343 (0b001000, 0b111100, "mr"), # mapreduce (no Rc)
3344 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3345 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3346 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3347 (0b001100, 0b111100, "rsvd"), # reserved
3349 mode
= int(self
.insn
.prefix
.rm
.normal
.mode
)
3350 search
= ((mode
<< 1) | self
.record
.Rc
)
3352 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
3353 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3354 # mode Rc mask Rc member
3355 # ironically/coincidentally this table is identical to NORMAL
3356 # mode except reserved in place of mr
3358 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3359 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3360 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3362 search
= ((int(self
.insn
.prefix
.rm
.ldst_imm
.mode
) << 1) |
3365 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
3366 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3367 # mode Rc mask Rc member
3369 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3370 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3371 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3373 search
= ((int(self
.insn
.prefix
.rm
.ldst_idx
.mode
) << 1) |
3376 elif self
.record
.svp64
.mode
is _SVMode
.CROP
:
3377 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
3378 # mode 3b mask 3b member
3380 (0b000000, 0b111000, "simple"), # simple
3381 (0b001000, 0b111000, "mr"), # mapreduce
3382 (0b010001, 0b010001, "ff3"), # ffirst, 3-bit CR
3383 (0b010000, 0b010000, "ff5"), # ffirst, 5-bit CR
3385 search
= ((int(self
.insn
.prefix
.rm
.crop
.mode
) << 1) |
3386 int(self
.record
.svp64
.extra_CR_3bit
))
3388 elif self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3392 (0b00, 0b11, "simple"), # simple
3393 (0b01, 0b11, "vls"), # VLset
3394 (0b10, 0b11, "ctr"), # CTR mode
3395 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
3397 # slightly weird: doesn't have a 5-bit "mode" field like others
3398 search
= int(self
.insn
.prefix
.rm
.branch
.mode
.sel
)
3401 if table
is not None:
3402 for (value
, mask
, field
) in table
:
3403 if field
.startswith("rsvd"):
3405 if ((value
& mask
) == (search
& mask
)):
3406 return getattr(rm
, field
)
3410 def __getattr__(self
, key
):
3411 if key
.startswith(f
"_{self.__class__.__name__}__"):
3412 return super().__getattribute
__(key
)
3414 return getattr(self
.rm
, key
)
3416 def __setattr__(self
, key
, value
):
3417 if key
.startswith(f
"_{self.__class__.__name__}__"):
3418 return super().__setattr
__(key
, value
)
3421 if not hasattr(rm
, key
):
3422 raise AttributeError(key
)
3424 return setattr(rm
, key
, value
)
3427 class SVP64Instruction(PrefixedInstruction
):
3428 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
3429 class Prefix(PrefixedInstruction
.Prefix
):
3431 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
3435 def select(self
, record
):
3436 return RMSelector(insn
=self
, record
=record
)
3441 for idx
in range(64):
3442 bit
= int(self
[idx
])
3444 return "".join(map(str, bits
))
3447 def assemble(cls
, record
, arguments
=None, specifiers
=None):
3448 insn
= super().assemble(record
=record
, arguments
=arguments
)
3450 specifiers
= Specifiers(items
=specifiers
, record
=record
)
3451 for specifier
in specifiers
:
3452 specifier
.assemble(insn
=insn
)
3454 insn
.prefix
.PO
= 0x1
3455 insn
.prefix
.id = 0x3
3459 def disassemble(self
, record
,
3461 style
=Style
.NORMAL
):
3463 if style
<= Style
.SHORT
:
3466 blob
= insn
.bytes(byteorder
=byteorder
)
3467 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
3470 blob_prefix
= blob(self
.prefix
)
3471 blob_suffix
= blob(self
.suffix
)
3473 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3474 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
3477 assert record
.svp64
is not None
3479 name
= f
"sv.{record.name}"
3481 rm
= self
.select(record
=record
)
3483 # convert specifiers to /x/y/z (sorted lexicographically)
3484 specifiers
= sorted(rm
.specifiers(record
=record
))
3485 if specifiers
: # if any add one extra to get the extra "/"
3486 specifiers
= ([""] + specifiers
)
3487 specifiers
= "/".join(specifiers
)
3489 # convert operands to " ,x,y,z"
3490 operands
= tuple(map(_operator
.itemgetter(1),
3491 self
.spec_dynamic_operands(record
=record
, style
=style
)))
3492 operands
= ",".join(operands
)
3493 if len(operands
) > 0: # if any separate with a space
3494 operands
= (" " + operands
)
3496 if style
<= Style
.LEGACY
:
3497 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3498 suffix
= WordInstruction
.integer(value
=int(self
.suffix
))
3499 yield from suffix
.disassemble(record
=record
,
3500 byteorder
=byteorder
, style
=style
)
3502 yield f
"{blob_prefix}{name}{specifiers}{operands}"
3504 yield f
"{blob_suffix}"
3506 if style
>= Style
.VERBOSE
:
3508 binary
= self
.binary
3509 spec
= self
.spec(record
=record
, prefix
="sv.")
3511 yield f
"{indent}spec"
3512 yield f
"{indent}{indent}{spec}"
3513 yield f
"{indent}pcode"
3514 for stmt
in record
.mdwn
.pcode
:
3515 yield f
"{indent}{indent}{stmt}"
3516 yield f
"{indent}binary"
3517 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
3518 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
3519 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
3520 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
3521 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
3522 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
3523 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
3524 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
3525 yield f
"{indent}opcodes"
3526 for opcode
in record
.opcodes
:
3527 yield f
"{indent}{indent}{opcode!r}"
3528 for operand
in self
.operands(record
=record
):
3529 yield from operand
.disassemble(insn
=self
,
3530 style
=style
, indent
=indent
)
3532 yield f
"{indent}{indent}{str(rm)}"
3533 for line
in rm
.disassemble(style
=style
):
3534 yield f
"{indent}{indent}{line}"
3538 def operands(cls
, record
):
3539 for operand
in super().operands(record
=record
):
3540 parent
= operand
.__class
__
3541 name
= f
"SVP64{parent.__name__}"
3542 bases
= (SVP64Operand
, parent
)
3543 child
= type(name
, bases
, {})
3544 yield child(**dict(operand
))
3547 def parse(stream
, factory
):
3549 return ("TODO" not in frozenset(entry
.values()))
3551 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
3552 entries
= _csv
.DictReader(lines
)
3553 entries
= filter(match
, entries
)
3554 return tuple(map(factory
, entries
))
3557 class MarkdownDatabase
:
3560 for (name
, desc
) in _ISA():
3563 (dynamic
, *static
) = desc
.regs
3564 operands
.extend(dynamic
)
3565 operands
.extend(static
)
3566 pcode
= PCode(iterable
=filter(str.strip
, desc
.pcode
))
3567 operands
= Operands(insn
=name
, operands
=operands
)
3568 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
3570 self
.__db
= dict(sorted(db
.items()))
3572 return super().__init
__()
3575 yield from self
.__db
.items()
3577 def __contains__(self
, key
):
3578 return self
.__db
.__contains
__(key
)
3580 def __getitem__(self
, key
):
3581 return self
.__db
.__getitem
__(key
)
3584 class FieldsDatabase
:
3587 df
= _DecodeFields()
3589 for (form
, fields
) in df
.instrs
.items():
3590 if form
in {"DQE", "TX"}:
3594 db
[_Form
[form
]] = Fields(fields
)
3598 return super().__init
__()
3600 def __getitem__(self
, key
):
3601 return self
.__db
.__getitem
__(key
)
3605 def __init__(self
, root
, mdwndb
):
3606 # The code below groups the instructions by name:section.
3607 # There can be multiple names for the same instruction.
3608 # The point is to capture different opcodes for the same instruction.
3610 records
= _collections
.defaultdict(set)
3611 path
= (root
/ "insndb.csv")
3612 with
open(path
, "r", encoding
="UTF-8") as stream
:
3613 for section
in sorted(parse(stream
, Section
.CSV
)):
3614 path
= (root
/ section
.path
)
3616 section
.Mode
.INTEGER
: IntegerOpcode
,
3617 section
.Mode
.PATTERN
: PatternOpcode
,
3619 factory
= _functools
.partial(
3620 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
3621 with
open(path
, "r", encoding
="UTF-8") as stream
:
3622 for insn
in parse(stream
, factory
):
3623 for name
in insn
.names
:
3624 records
[name
].add(insn
)
3625 sections
[name
] = section
3627 items
= sorted(records
.items())
3629 for (name
, multirecord
) in items
:
3630 records
[name
] = PPCMultiRecord(sorted(multirecord
))
3632 def exact_match(name
):
3633 record
= records
.get(name
)
3639 if not name
.endswith("l"):
3641 alias
= exact_match(name
[:-1])
3644 record
= records
[alias
]
3645 if "lk" not in record
.flags
:
3646 raise ValueError(record
)
3650 if not name
.endswith("a"):
3652 alias
= LK_match(name
[:-1])
3655 record
= records
[alias
]
3656 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
3657 raise ValueError(record
)
3658 if "AA" not in mdwndb
[name
].operands
:
3659 raise ValueError(record
)
3663 if not name
.endswith("."):
3665 alias
= exact_match(name
[:-1])
3668 record
= records
[alias
]
3669 if record
.Rc
is _RCOE
.NONE
:
3670 raise ValueError(record
)
3674 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
3675 for (name
, _
) in mdwndb
:
3676 if name
.startswith("sv."):
3679 for match
in matches
:
3681 if alias
is not None:
3685 section
= sections
[alias
]
3686 record
= records
[alias
]
3687 db
[name
] = (section
, record
)
3689 self
.__db
= dict(sorted(db
.items()))
3691 return super().__init
__()
3693 @_functools.lru_cache(maxsize
=512, typed
=False)
3694 def __getitem__(self
, key
):
3695 return self
.__db
.get(key
, (None, None))
3698 class SVP64Database
:
3699 def __init__(self
, root
, ppcdb
):
3701 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
3702 for (prefix
, _
, names
) in _os
.walk(root
):
3703 prefix
= _pathlib
.Path(prefix
)
3704 for name
in filter(lambda name
: pattern
.match(name
), names
):
3705 path
= (prefix
/ _pathlib
.Path(name
))
3706 with
open(path
, "r", encoding
="UTF-8") as stream
:
3707 db
.update(parse(stream
, SVP64Record
.CSV
))
3708 db
= {record
.name
:record
for record
in db
}
3710 self
.__db
= dict(sorted(db
.items()))
3711 self
.__ppcdb
= ppcdb
3713 return super().__init
__()
3715 def __getitem__(self
, key
):
3716 (_
, record
) = self
.__ppcdb
[key
]
3720 for name
in record
.names
:
3721 record
= self
.__db
.get(name
, None)
3722 if record
is not None:
3728 class Database(Node
):
3729 def __init__(self
, root
):
3730 root
= _pathlib
.Path(root
)
3731 mdwndb
= MarkdownDatabase()
3732 fieldsdb
= FieldsDatabase()
3733 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
3734 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
3738 opcodes
= _collections
.defaultdict(
3739 lambda: _collections
.defaultdict(set))
3741 for (name
, mdwn
) in mdwndb
:
3742 if name
.startswith("sv."):
3744 (section
, ppc
) = ppcdb
[name
]
3747 svp64
= svp64db
[name
]
3748 fields
= fieldsdb
[ppc
.form
]
3749 record
= Record(name
=name
,
3750 section
=section
, ppc
=ppc
, svp64
=svp64
,
3751 mdwn
=mdwn
, fields
=fields
)
3753 names
[record
.name
] = record
3754 opcodes
[section
][record
.PO
].add(record
)
3756 self
.__db
= sorted(db
)
3757 self
.__names
= dict(sorted(names
.items()))
3758 self
.__opcodes
= dict(sorted(opcodes
.items()))
3760 return super().__init
__()
3762 def subnodes(self
, match
=None):
3764 match
= lambda subnode
: True
3766 yield from filter(match
, self
)
3769 return repr(self
.__db
)
3772 yield from self
.__db
3774 @_functools.lru_cache(maxsize
=None)
3775 def __contains__(self
, key
):
3776 return self
.__getitem
__(key
) is not None
3778 @_functools.lru_cache(maxsize
=None)
3779 def __getitem__(self
, key
):
3780 if isinstance(key
, SVP64Instruction
):
3783 if isinstance(key
, Instruction
):
3786 sections
= sorted(self
.__opcodes
)
3787 for section
in sections
:
3788 group
= self
.__opcodes
[section
]
3789 for record
in group
[PO
]:
3790 if record
.match(key
=key
):
3795 elif isinstance(key
, str):
3796 return self
.__names
.get(key
)
3798 raise ValueError("instruction or name expected")