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
14 from functools
import cached_property
16 from cached_property
import cached_property
18 from openpower
.decoder
.power_enums
import (
19 Function
as _Function
,
26 CRIn2Sel
as _CRIn2Sel
,
27 CROutSel
as _CROutSel
,
29 LDSTMode
as _LDSTMode
,
34 SVMaskSrc
as _SVMaskSrc
,
41 SVP64SubVL
as _SVP64SubVL
,
42 SVP64Pred
as _SVP64Pred
,
43 SVP64PredMode
as _SVP64PredMode
,
44 SVP64Width
as _SVP64Width
,
46 from openpower
.decoder
.selectable_int
import (
47 SelectableInt
as _SelectableInt
,
48 selectconcat
as _selectconcat
,
50 from openpower
.decoder
.power_fields
import (
53 DecodeFields
as _DecodeFields
,
55 from openpower
.decoder
.pseudo
.pagereader
import ISA
as _ISA
59 @_contextlib.contextmanager
63 @_contextlib.contextmanager
64 def record(self
, record
):
68 @_functools.total_ordering
69 class Style(_enum
.Enum
):
73 VERBOSE
= _enum
.auto()
75 def __lt__(self
, other
):
76 if not isinstance(other
, self
.__class
__):
78 return (self
.value
< other
.value
)
81 @_functools.total_ordering
82 class Priority(_enum
.Enum
):
88 def _missing_(cls
, value
):
89 if isinstance(value
, str):
94 return super()._missing
_(value
)
96 def __lt__(self
, other
):
97 if not isinstance(other
, self
.__class
__):
100 # NOTE: the order is inversed, LOW < NORMAL < HIGH
101 return (self
.value
> other
.value
)
104 def dataclass(cls
, record
, keymap
=None, typemap
=None):
108 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
110 def transform(key_value
):
111 (key
, value
) = key_value
112 key
= keymap
.get(key
, key
)
113 hook
= typemap
.get(key
, lambda value
: value
)
114 if hook
is bool and value
in ("", "0"):
120 record
= dict(map(transform
, record
.items()))
121 for key
in frozenset(record
.keys()):
122 if record
[key
] == "":
128 @_functools.total_ordering
129 @_dataclasses.dataclass(eq
=True, frozen
=True)
132 def __new__(cls
, value
):
133 if isinstance(value
, str):
134 value
= int(value
, 0)
135 if not isinstance(value
, int):
136 raise ValueError(value
)
138 if value
.bit_length() > 64:
139 raise ValueError(value
)
141 return super().__new
__(cls
, value
)
144 return self
.__repr
__()
147 return f
"{self:0{self.bit_length()}b}"
149 def bit_length(self
):
150 if super().bit_length() > 32:
154 class Value(Integer
):
163 def __lt__(self
, other
):
164 if not isinstance(other
, Opcode
):
165 return NotImplemented
166 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
169 return (self
.value
& self
.mask
)
172 return int(self
).__index
__()
175 def pattern(value
, mask
, bit_length
):
176 for bit
in range(bit_length
):
177 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
179 elif (value
& (1 << (bit_length
- bit
- 1))):
184 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
186 def match(self
, key
):
187 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
190 @_functools.total_ordering
191 @_dataclasses.dataclass(eq
=True, frozen
=True)
192 class IntegerOpcode(Opcode
):
193 def __init__(self
, value
):
194 if value
.startswith("0b"):
195 mask
= int(("1" * len(value
[2:])), 2)
199 value
= Opcode
.Value(value
)
200 mask
= Opcode
.Mask(mask
)
202 return super().__init
__(value
=value
, mask
=mask
)
205 @_functools.total_ordering
206 @_dataclasses.dataclass(eq
=True, frozen
=True)
207 class PatternOpcode(Opcode
):
208 def __init__(self
, pattern
):
209 if not isinstance(pattern
, str):
210 raise ValueError(pattern
)
212 (value
, mask
) = (0, 0)
213 for symbol
in pattern
:
214 if symbol
not in {"0", "1", "-"}:
215 raise ValueError(pattern
)
216 value |
= (symbol
== "1")
217 mask |
= (symbol
!= "-")
223 value
= Opcode
.Value(value
)
224 mask
= Opcode
.Mask(mask
)
226 return super().__init
__(value
=value
, mask
=mask
)
229 @_dataclasses.dataclass(eq
=True, frozen
=True)
231 class FlagsMeta(type):
246 class Flags(tuple, metaclass
=FlagsMeta
):
247 def __new__(cls
, flags
=frozenset()):
248 flags
= frozenset(flags
)
249 diff
= (flags
- frozenset(cls
))
251 raise ValueError(flags
)
252 return super().__new
__(cls
, sorted(flags
))
256 flags
: Flags
= Flags()
258 function
: _Function
= _Function
.NONE
259 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
260 in1
: _In1Sel
= _In1Sel
.NONE
261 in2
: _In2Sel
= _In2Sel
.NONE
262 in3
: _In3Sel
= _In3Sel
.NONE
263 out
: _OutSel
= _OutSel
.NONE
264 cr_in
: _CRInSel
= _CRInSel
.NONE
265 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
266 cr_out
: _CROutSel
= _CROutSel
.NONE
267 cry_in
: _CryIn
= _CryIn
.ZERO
268 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
269 upd
: _LDSTMode
= _LDSTMode
.NONE
270 Rc
: _RCOE
= _RCOE
.NONE
271 form
: _Form
= _Form
.NONE
273 unofficial
: bool = False
277 "internal op": "intop",
281 "ldst len": "ldst_len",
283 "CONDITIONS": "conditions",
286 def __lt__(self
, other
):
287 if not isinstance(other
, self
.__class
__):
288 return NotImplemented
289 lhs
= (self
.opcode
, self
.comment
)
290 rhs
= (other
.opcode
, other
.comment
)
294 def CSV(cls
, record
, opcode_cls
):
295 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
296 typemap
["opcode"] = opcode_cls
298 if record
["CR in"] == "BA_BB":
299 record
["cr_in"] = "BA"
300 record
["cr_in2"] = "BB"
304 for flag
in frozenset(PPCRecord
.Flags
):
305 if bool(record
.pop(flag
, "")):
307 record
["flags"] = PPCRecord
.Flags(flags
)
309 return dataclass(cls
, record
,
310 keymap
=PPCRecord
.__KEYMAP
,
315 return frozenset(self
.comment
.split("=")[-1].split("/"))
318 class PPCMultiRecord(tuple):
319 def __getattr__(self
, attr
):
322 raise AttributeError(attr
)
323 return getattr(self
[0], attr
)
326 @_dataclasses.dataclass(eq
=True, frozen
=True)
328 class ExtraMap(tuple):
330 @_dataclasses.dataclass(eq
=True, frozen
=True)
332 seltype
: _SelType
= _SelType
.NONE
333 reg
: _Reg
= _Reg
.NONE
336 return f
"{self.seltype.value}:{self.reg.name}"
338 def __new__(cls
, value
="0"):
339 if isinstance(value
, str):
340 def transform(value
):
341 (seltype
, reg
) = value
.split(":")
342 seltype
= _SelType(seltype
)
344 return cls
.Entry(seltype
=seltype
, reg
=reg
)
349 value
= map(transform
, value
.split(";"))
351 return super().__new
__(cls
, value
)
354 return repr(list(self
))
356 def __new__(cls
, value
=tuple()):
360 return super().__new
__(cls
, map(cls
.Extra
, value
))
363 return repr({index
:self
[index
] for index
in range(0, 4)})
366 ptype
: _SVPType
= _SVPType
.NONE
367 etype
: _SVEType
= _SVEType
.NONE
368 msrc
: _SVMaskSrc
= _SVMaskSrc
.NO
# MASK_SRC is active
369 in1
: _In1Sel
= _In1Sel
.NONE
370 in2
: _In2Sel
= _In2Sel
.NONE
371 in3
: _In3Sel
= _In3Sel
.NONE
372 out
: _OutSel
= _OutSel
.NONE
373 out2
: _OutSel
= _OutSel
.NONE
374 cr_in
: _CRInSel
= _CRInSel
.NONE
375 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
376 cr_out
: _CROutSel
= _CROutSel
.NONE
377 extra
: ExtraMap
= ExtraMap()
379 mode
: _SVMode
= _SVMode
.NORMAL
383 "CONDITIONS": "conditions",
392 def CSV(cls
, record
):
393 record
["insn"] = record
["insn"].split("=")[-1]
395 for key
in frozenset({
396 "in1", "in2", "in3", "CR in",
397 "out", "out2", "CR out",
403 if record
["CR in"] == "BA_BB":
404 record
["cr_in"] = "BA"
405 record
["cr_in2"] = "BB"
409 for idx
in range(0, 4):
410 extra
.append(record
.pop(f
"{idx}"))
412 record
["extra"] = cls
.ExtraMap(extra
)
414 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
419 "in1", "in2", "in3", "cr_in", "cr_in2",
420 "out", "out2", "cr_out",
435 for index
in range(0, 4):
436 for entry
in self
.extra
[index
]:
437 extras
[entry
.seltype
][entry
.reg
] = idxmap
[index
]
439 for (seltype
, regs
) in extras
.items():
440 idx
= regs
.get(reg
, _SVExtra
.NONE
)
441 if idx
is not _SVExtra
.NONE
:
442 yield (reg
, seltype
, idx
)
449 # has the word "in", it is a SelType.SRC "out" -> DST
450 # in1/2/3 and CR in are SRC, and must match only against "s:NN"
451 # out/out1 and CR out are DST, and must match only against "d:NN"
452 keytype
= _SelType
.SRC
if ("in" in key
) else _SelType
.DST
453 sel
= sels
[key
] = getattr(self
, key
)
454 reg
= regs
[key
] = _Reg(sel
)
455 seltypes
[key
] = _SelType
.NONE
456 idxs
[key
] = _SVExtra
.NONE
457 for (reg
, seltype
, idx
) in extra(reg
.alias
):
458 if keytype
!= seltype
: # only check SRC-to-SRC and DST-to-DST
460 if idx
!= idxs
[key
] and idxs
[key
] is not _SVExtra
.NONE
:
461 raise ValueError(idx
)
464 seltypes
[key
] = seltype
466 if sels
["cr_in"] is _CRInSel
.BA_BB
:
467 sels
["cr_in"] = _CRIn2Sel
.BA
468 sels
["cr_in2"] = _CRIn2Sel
.BB
469 idxs
["cr_in2"] = idxs
["cr_in"]
470 for key
in ("cr_in", "cr_in2"):
471 regs
[key
] = _Reg(sels
[key
])
472 seltype
[key
] = _SelType
.SRC
479 "seltype": seltypes
[key
],
483 return _types
.MappingProxyType(records
)
485 extra_idx_in1
= property(lambda self
: self
.extras
["in1"]["idx"])
486 extra_idx_in2
= property(lambda self
: self
.extras
["in2"]["idx"])
487 extra_idx_in3
= property(lambda self
: self
.extras
["in3"]["idx"])
488 extra_idx_out
= property(lambda self
: self
.extras
["out"]["idx"])
489 extra_idx_out2
= property(lambda self
: self
.extras
["out2"]["idx"])
490 extra_idx_cr_in
= property(lambda self
: self
.extras
["cr_in"]["idx"])
491 extra_idx_cr_in2
= property(lambda self
: self
.extras
["cr_in2"]["idx"])
492 extra_idx_cr_out
= property(lambda self
: self
.extras
["cr_out"]["idx"])
497 for idx
in range(0, 4):
498 for entry
in self
.extra
[idx
]:
499 if entry
.seltype
is _SelType
.DST
:
500 if extra
is not None:
501 raise ValueError(self
.svp64
)
505 if _RegType(extra
.reg
) not in (_RegType
.CR_3BIT
, _RegType
.CR_5BIT
):
506 raise ValueError(self
.svp64
)
511 def extra_CR_3bit(self
):
512 return (_RegType(self
.extra_CR
.reg
) is _RegType
.CR_3BIT
)
516 def __init__(self
, value
=(0, 32)):
517 if isinstance(value
, str):
518 (start
, end
) = map(int, value
.split(":"))
521 if start
< 0 or end
< 0 or start
>= end
:
522 raise ValueError(value
)
527 return super().__init
__()
530 return (self
.__end
- self
.__start
+ 1)
533 return f
"[{self.__start}:{self.__end}]"
536 yield from range(self
.start
, (self
.end
+ 1))
538 def __reversed__(self
):
539 return tuple(reversed(tuple(self
)))
550 @_dataclasses.dataclass(eq
=True, frozen
=True)
552 class Mode(_enum
.Enum
):
553 INTEGER
= _enum
.auto()
554 PATTERN
= _enum
.auto()
557 def _missing_(cls
, value
):
558 if isinstance(value
, str):
559 return cls
[value
.upper()]
560 return super()._missing
_(value
)
563 def __new__(cls
, value
=None):
564 if isinstance(value
, str):
565 if value
.upper() == "NONE":
568 value
= int(value
, 0)
572 return super().__new
__(cls
, value
)
578 return (bin(self
) if self
else "None")
584 opcode
: IntegerOpcode
= None
585 priority
: Priority
= Priority
.NORMAL
587 def __lt__(self
, other
):
588 if not isinstance(other
, self
.__class
__):
589 return NotImplemented
590 return (self
.priority
< other
.priority
)
593 def CSV(cls
, record
):
594 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
595 if record
["opcode"] == "NONE":
596 typemap
["opcode"] = lambda _
: None
598 return dataclass(cls
, record
, typemap
=typemap
)
602 def __init__(self
, items
):
603 if isinstance(items
, dict):
604 items
= items
.items()
607 (name
, bitrange
) = item
608 return (name
, tuple(bitrange
.values()))
610 self
.__mapping
= dict(map(transform
, items
))
612 return super().__init
__()
615 return repr(self
.__mapping
)
618 yield from self
.__mapping
.items()
620 def __contains__(self
, key
):
621 return self
.__mapping
.__contains
__(key
)
623 def __getitem__(self
, key
):
624 return self
.__mapping
.get(key
, None)
639 def __init__(self
, insn
, operands
):
641 "b": {"target_addr": TargetAddrOperandLI
},
642 "ba": {"target_addr": TargetAddrOperandLI
},
643 "bl": {"target_addr": TargetAddrOperandLI
},
644 "bla": {"target_addr": TargetAddrOperandLI
},
645 "bc": {"target_addr": TargetAddrOperandBD
},
646 "bca": {"target_addr": TargetAddrOperandBD
},
647 "bcl": {"target_addr": TargetAddrOperandBD
},
648 "bcla": {"target_addr": TargetAddrOperandBD
},
649 "addpcis": {"D": DOperandDX
},
650 "fishmv": {"D": DOperandDX
},
651 "fmvis": {"D": DOperandDX
},
654 "SVi": NonZeroOperand
,
655 "SVd": NonZeroOperand
,
656 "SVxd": NonZeroOperand
,
657 "SVyd": NonZeroOperand
,
658 "SVzd": NonZeroOperand
,
660 "D": SignedImmediateOperand
,
664 "SIM": SignedOperand
,
665 "SVD": SignedOperand
,
666 "SVDS": SignedOperand
,
667 "RSp": GPRPairOperand
,
668 "RTp": GPRPairOperand
,
669 "FRAp": FPRPairOperand
,
670 "FRBp": FPRPairOperand
,
671 "FRSp": FPRPairOperand
,
672 "FRTp": FPRPairOperand
,
674 custom_immediates
= {
680 for operand
in operands
:
684 (name
, value
) = operand
.split("=")
685 mapping
[name
] = (StaticOperand
, {
691 if name
.endswith(")"):
692 name
= name
.replace("(", " ").replace(")", "")
693 (imm_name
, _
, name
) = name
.partition(" ")
697 if imm_name
is not None:
698 imm_cls
= custom_immediates
.get(imm_name
, ImmediateOperand
)
700 if insn
in custom_insns
and name
in custom_insns
[insn
]:
701 cls
= custom_insns
[insn
][name
]
702 elif name
in custom_fields
:
703 cls
= custom_fields
[name
]
704 elif name
in _Reg
.__members
__:
706 if reg
in self
.__class
__.__GPR
_PAIRS
:
708 elif reg
in self
.__class
__.__FPR
_PAIRS
:
711 regtype
= _RegType
[name
]
712 if regtype
is _RegType
.GPR
:
714 elif regtype
is _RegType
.FPR
:
716 elif regtype
is _RegType
.CR_3BIT
:
718 elif regtype
is _RegType
.CR_5BIT
:
721 if imm_name
is not None:
722 mapping
[imm_name
] = (imm_cls
, {"name": imm_name
})
723 mapping
[name
] = (cls
, {"name": name
})
727 for (name
, (cls
, kwargs
)) in mapping
.items():
728 kwargs
= dict(kwargs
)
729 kwargs
["name"] = name
730 if issubclass(cls
, StaticOperand
):
731 static
.append((cls
, kwargs
))
732 elif issubclass(cls
, DynamicOperand
):
733 dynamic
.append((cls
, kwargs
))
735 raise ValueError(name
)
737 self
.__mapping
= mapping
738 self
.__static
= tuple(static
)
739 self
.__dynamic
= tuple(dynamic
)
741 return super().__init
__()
744 for (_
, items
) in self
.__mapping
.items():
745 (cls
, kwargs
) = items
749 return self
.__mapping
.__repr
__()
751 def __contains__(self
, key
):
752 return self
.__mapping
.__contains
__(key
)
754 def __getitem__(self
, key
):
755 return self
.__mapping
.__getitem
__(key
)
763 return self
.__dynamic
766 class Arguments(tuple):
767 def __new__(cls
, record
, arguments
, operands
):
768 operands
= iter(tuple(operands
))
769 arguments
= iter(tuple(arguments
))
774 operand
= next(operands
)
775 except StopIteration:
779 argument
= next(arguments
)
780 except StopIteration:
781 raise ValueError("operands count mismatch")
783 if isinstance(operand
, ImmediateOperand
):
784 argument
= argument
.replace("(", " ").replace(")", "")
785 (imm_argument
, _
, argument
) = argument
.partition(" ")
787 (imm_operand
, operand
) = (operand
, next(operands
))
788 except StopIteration:
789 raise ValueError("operands count mismatch")
790 items
.append((imm_argument
, imm_operand
))
791 items
.append((argument
, operand
))
795 except StopIteration:
798 raise ValueError("operands count mismatch")
800 return super().__new
__(cls
, items
)
804 def __init__(self
, iterable
):
805 self
.__pcode
= tuple(iterable
)
806 return super().__init
__()
809 yield from self
.__pcode
812 return self
.__pcode
.__repr
__()
815 @_dataclasses.dataclass(eq
=True, frozen
=True)
816 class MarkdownRecord
:
821 @_functools.total_ordering
822 @_dataclasses.dataclass(eq
=True, frozen
=True)
829 svp64
: SVP64Record
= None
831 def visit(self
, visitor
):
832 with visitor
.record(record
=self
) as record
:
837 return self
.svp64
.extras
841 return self
.mdwn
.pcode
843 def __lt__(self
, other
):
844 if not isinstance(other
, Record
):
845 return NotImplemented
846 lhs
= (min(self
.opcodes
), self
.name
)
847 rhs
= (min(other
.opcodes
), other
.name
)
852 return (self
.static_operands
+ self
.dynamic_operands
)
855 def static_operands(self
):
857 operands
.append(POStaticOperand(record
=self
, value
=self
.PO
))
859 operands
.append(XOStaticOperand(
861 value
=ppc
.opcode
.value
,
862 span
=self
.section
.bitsel
,
864 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
865 operands
.append(cls(record
=self
, **kwargs
))
866 return tuple(operands
)
869 def dynamic_operands(self
):
871 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
872 operands
.append(cls(record
=self
, **kwargs
))
873 return tuple(operands
)
878 return int("".join(str(int(mapping
[bit
])) \
879 for bit
in sorted(mapping
)), 2)
881 def PO_XO(value
, mask
, opcode
, bits
):
884 for (src
, dst
) in enumerate(reversed(bits
)):
885 value
[dst
] = ((opcode
.value
& (1 << src
)) != 0)
886 mask
[dst
] = ((opcode
.mask
& (1 << src
)) != 0)
889 def PO(value
, mask
, opcode
, bits
):
890 return PO_XO(value
=value
, mask
=mask
, opcode
=opcode
, bits
=bits
)
892 def XO(value
, mask
, opcode
, bits
):
893 (value
, mask
) = PO_XO(value
=value
, mask
=mask
,
894 opcode
=opcode
, bits
=bits
)
895 for (op_cls
, op_kwargs
) in self
.mdwn
.operands
.static
:
896 operand
= op_cls(record
=self
, **op_kwargs
)
897 for (src
, dst
) in enumerate(reversed(operand
.span
)):
898 value
[dst
] = ((operand
.value
& (1 << src
)) != 0)
903 value
= {bit
:False for bit
in range(32)}
904 mask
= {bit
:False for bit
in range(32)}
905 if self
.section
.opcode
is not None:
906 (value
, mask
) = PO(value
=value
, mask
=mask
,
907 opcode
=self
.section
.opcode
, bits
=range(0, 6))
909 pairs
.append(XO(value
=value
, mask
=mask
,
910 opcode
=ppc
.opcode
, bits
=self
.section
.bitsel
))
913 for (value
, mask
) in pairs
:
914 value
= Opcode
.Value(binary(value
))
915 mask
= Opcode
.Mask(binary(mask
))
916 result
.append(Opcode(value
=value
, mask
=mask
))
922 opcode
= self
.section
.opcode
924 opcode
= self
.ppc
[0].opcode
925 if isinstance(opcode
, PatternOpcode
):
926 value
= int(opcode
.value
)
927 bits
= opcode
.value
.bit_length()
928 return int(_SelectableInt(value
=value
, bits
=bits
)[0:6])
930 return int(opcode
.value
)
934 return tuple(ppc
.opcode
for ppc
in self
.ppc
)
936 def match(self
, key
):
937 for opcode
in self
.opcodes
:
938 if opcode
.match(key
):
945 return self
.svp64
.mode
965 if self
.svp64
is None:
971 return self
.ppc
.cr_in
975 return self
.ppc
.cr_in2
979 return self
.ppc
.cr_out
981 ptype
= property(lambda self
: self
.svp64
.ptype
)
982 etype
= property(lambda self
: self
.svp64
.etype
)
984 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
985 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
986 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
987 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
988 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
989 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
990 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
991 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
993 def __contains__(self
, key
):
994 return self
.mdwn
.operands
.__contains
__(key
)
996 def __getitem__(self
, key
):
997 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
998 return cls(record
=self
, **kwargs
)
1002 if "Rc" not in self
:
1004 return self
["Rc"].value
1008 def __init__(self
, record
, name
):
1009 self
.__record
= record
1013 yield ("record", self
.record
)
1014 yield ("name", self
.__name
)
1017 return f
"{self.__class__.__name__}({self.name})"
1025 return self
.__record
1029 return self
.record
.fields
[self
.name
]
1031 def assemble(self
, insn
):
1032 raise NotImplementedError()
1034 def disassemble(self
, insn
,
1035 style
=Style
.NORMAL
, indent
=""):
1036 raise NotImplementedError()
1039 class DynamicOperand(Operand
):
1040 def assemble(self
, insn
, value
):
1042 if isinstance(value
, str):
1043 value
= int(value
, 0)
1045 raise ValueError("signed operands not allowed")
1048 def disassemble(self
, insn
,
1049 style
=Style
.NORMAL
, indent
=""):
1053 if style
>= Style
.VERBOSE
:
1054 span
= map(str, span
)
1055 yield f
"{indent}{self.name}"
1056 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1057 yield f
"{indent}{indent}{', '.join(span)}"
1059 yield str(int(value
))
1062 class SignedOperand(DynamicOperand
):
1063 def assemble(self
, insn
, value
):
1064 if isinstance(value
, str):
1065 value
= int(value
, 0)
1066 return super().assemble(value
=value
, insn
=insn
)
1068 def assemble(self
, insn
, value
):
1070 if isinstance(value
, str):
1071 value
= int(value
, 0)
1074 def disassemble(self
, insn
,
1075 style
=Style
.NORMAL
, indent
=""):
1077 value
= insn
[span
].to_signed_int()
1078 sign
= "-" if (value
< 0) else ""
1081 if style
>= Style
.VERBOSE
:
1082 span
= map(str, span
)
1083 yield f
"{indent}{self.name}"
1084 yield f
"{indent}{indent}{sign}{value}"
1085 yield f
"{indent}{indent}{', '.join(span)}"
1087 yield f
"{sign}{value}"
1090 class StaticOperand(Operand
):
1091 def __init__(self
, record
, name
, value
):
1092 self
.__value
= value
1093 return super().__init
__(record
=record
, name
=name
)
1096 yield ("value", self
.__value
)
1097 yield from super().__iter
__()
1100 return f
"{self.__class__.__name__}({self.name}, value={self.value})"
1106 def assemble(self
, insn
):
1107 insn
[self
.span
] = self
.value
1109 def disassemble(self
, insn
,
1110 style
=Style
.NORMAL
, indent
=""):
1114 if style
>= Style
.VERBOSE
:
1115 span
= map(str, span
)
1116 yield f
"{indent}{self.name}"
1117 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1118 yield f
"{indent}{indent}{', '.join(span)}"
1120 yield str(int(value
))
1123 class SpanStaticOperand(StaticOperand
):
1124 def __init__(self
, record
, name
, value
, span
):
1125 self
.__span
= tuple(span
)
1126 return super().__init
__(record
=record
, name
=name
, value
=value
)
1129 yield ("span", self
.__span
)
1130 yield from super().__iter
__()
1137 class POStaticOperand(SpanStaticOperand
):
1138 def __init__(self
, record
, value
):
1139 return super().__init
__(record
=record
, name
="PO",
1140 value
=value
, span
=range(0, 6))
1143 for (key
, value
) in super().__iter
__():
1144 if key
not in {"name", "span"}:
1148 class XOStaticOperand(SpanStaticOperand
):
1149 def __init__(self
, record
, value
, span
):
1150 bits
= record
.section
.bitsel
1151 value
= _SelectableInt(value
=value
, bits
=len(bits
))
1152 span
= dict(zip(bits
, range(len(bits
))))
1153 span_rev
= {value
:key
for (key
, value
) in span
.items()}
1155 # This part is tricky: we cannot use record.operands,
1156 # as this code is called by record.static_operands method.
1157 for (cls
, kwargs
) in record
.mdwn
.operands
:
1158 operand
= cls(record
=record
, **kwargs
)
1159 for idx
in operand
.span
:
1160 rev
= span
.pop(idx
, None)
1162 span_rev
.pop(rev
, None)
1164 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1165 span
= tuple(span
.keys())
1167 return super().__init
__(record
=record
, name
="XO",
1168 value
=value
, span
=span
)
1171 for (key
, value
) in super().__iter
__():
1172 if key
not in {"name"}:
1176 class ImmediateOperand(DynamicOperand
):
1180 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1184 class NonZeroOperand(DynamicOperand
):
1185 def assemble(self
, insn
, value
):
1186 if isinstance(value
, str):
1187 value
= int(value
, 0)
1188 if not isinstance(value
, int):
1189 raise ValueError("non-integer operand")
1191 raise ValueError("non-zero operand")
1193 return super().assemble(value
=value
, insn
=insn
)
1195 def disassemble(self
, insn
,
1196 style
=Style
.NORMAL
, indent
=""):
1200 if style
>= Style
.VERBOSE
:
1201 span
= map(str, span
)
1202 yield f
"{indent}{self.name}"
1203 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1204 yield f
"{indent}{indent}{', '.join(span)}"
1206 yield str(int(value
) + 1)
1209 class ExtendableOperand(DynamicOperand
):
1210 def sv_spec_enter(self
, value
, span
):
1211 return (value
, span
)
1213 def sv_spec(self
, insn
):
1217 span
= tuple(map(str, span
))
1219 if isinstance(insn
, SVP64Instruction
):
1220 (origin_value
, origin_span
) = (value
, span
)
1221 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1223 for extra_idx
in self
.extra_idx
:
1224 if self
.record
.etype
is _SVEType
.EXTRA3
:
1225 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1226 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1227 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1229 raise ValueError(self
.record
.etype
)
1232 vector
= bool(spec
[0])
1233 spec_span
= spec
.__class
__
1234 if self
.record
.etype
is _SVEType
.EXTRA3
:
1235 spec_span
= tuple(map(str, spec_span
[1, 2]))
1237 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1238 spec_span
= tuple(map(str, spec_span
[1,]))
1239 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1242 spec_span
= (spec_span
+ ("{0}",))
1244 spec_span
= (("{0}",) + spec_span
)
1246 raise ValueError(self
.record
.etype
)
1248 vector_shift
= (2 + (5 - value
.bits
))
1249 scalar_shift
= value
.bits
1250 spec_shift
= (5 - value
.bits
)
1252 bits
= (len(span
) + len(spec_span
))
1253 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1254 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1256 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1257 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1259 value
= ((spec
<< scalar_shift
) | value
)
1260 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1262 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1263 origin_value
=origin_value
, origin_span
=origin_span
)
1265 return (vector
, value
, span
)
1267 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1268 return (value
, span
)
1271 def extra_idx(self
):
1272 for (key
, record
) in self
.record
.svp64
.extras
.items():
1273 if record
["reg"].alias
is self
.extra_reg
.alias
:
1277 def extra_reg(self
):
1278 return _Reg(self
.name
)
1280 def remap(self
, value
, vector
):
1281 raise NotImplementedError()
1283 def assemble(self
, value
, insn
, prefix
):
1286 if isinstance(value
, str):
1287 value
= value
.lower()
1288 if value
.startswith("%"):
1290 if value
.startswith("*"):
1291 if not isinstance(insn
, SVP64Instruction
):
1292 raise ValueError(value
)
1295 if value
.startswith(prefix
):
1296 if (self
.extra_reg
.or_zero
and (value
== f
"{prefix}0")):
1297 raise ValueError(value
)
1298 value
= value
[len(prefix
):]
1299 value
= int(value
, 0)
1301 if isinstance(insn
, SVP64Instruction
):
1302 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1304 for extra_idx
in self
.extra_idx
:
1305 if self
.record
.etype
is _SVEType
.EXTRA3
:
1306 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1307 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1308 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1310 raise ValueError(self
.record
.etype
)
1312 return super().assemble(value
=value
, insn
=insn
)
1314 def disassemble(self
, insn
,
1315 style
=Style
.NORMAL
, prefix
="", indent
=""):
1316 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1318 if (self
.extra_reg
.or_zero
and (value
== 0)):
1321 if style
>= Style
.VERBOSE
:
1322 mode
= "vector" if vector
else "scalar"
1323 yield f
"{indent}{self.name} ({mode})"
1324 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1325 yield f
"{indent}{indent}{', '.join(span)}"
1326 if isinstance(insn
, SVP64Instruction
):
1327 for extra_idx
in frozenset(self
.extra_idx
):
1328 if self
.record
.etype
is _SVEType
.NONE
:
1329 yield f
"{indent}{indent}extra[none]"
1331 etype
= repr(self
.record
.etype
).lower()
1332 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1334 vector
= "*" if vector
else ""
1335 yield f
"{vector}{prefix}{int(value)}"
1338 class SimpleRegisterOperand(ExtendableOperand
):
1339 def remap(self
, value
, vector
):
1341 extra
= (value
& 0b11)
1342 value
= (value
>> 2)
1344 extra
= (value
>> 5)
1345 value
= (value
& 0b11111)
1347 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1348 # (and shrink to a single bit if ok)
1349 if self
.record
.etype
is _SVEType
.EXTRA2
:
1351 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1352 assert (extra
& 0b01) == 0, \
1353 ("vector field %s cannot fit into EXTRA2" % value
)
1354 extra
= (0b10 |
(extra
>> 1))
1356 # range is r0-r63 in increments of 1
1357 assert (extra
>> 1) == 0, \
1358 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1360 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1362 # EXTRA3 vector bit needs marking
1365 raise ValueError(self
.record
.etype
)
1367 return (value
, extra
)
1370 class GPROperand(SimpleRegisterOperand
):
1371 def assemble(self
, insn
, value
):
1372 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1374 def disassemble(self
, insn
,
1375 style
=Style
.NORMAL
, indent
=""):
1376 prefix
= "" if (style
<= Style
.SHORT
) else "r"
1377 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1378 style
=style
, indent
=indent
)
1381 class GPRPairOperand(GPROperand
):
1385 class FPROperand(SimpleRegisterOperand
):
1386 def assemble(self
, insn
, value
):
1387 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1389 def disassemble(self
, insn
,
1390 style
=Style
.NORMAL
, indent
=""):
1391 prefix
= "" if (style
<= Style
.SHORT
) else "f"
1392 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1393 style
=style
, indent
=indent
)
1396 class FPRPairOperand(FPROperand
):
1400 class ConditionRegisterFieldOperand(ExtendableOperand
):
1401 def pattern(name_pattern
):
1402 (name
, pattern
) = name_pattern
1403 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1412 CR
= r
"(?:CR|cr)([0-9]+)"
1414 BIT
= rf
"({'|'.join(CONDS.keys())})"
1415 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1416 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1417 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1418 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1419 XCR
= fr
"{CR}\.{BIT}"
1420 PATTERNS
= tuple(map(pattern
, (
1425 ("BIT+CR", (LBIT
+ CR
)),
1426 ("CR+BIT", (CR
+ RBIT
)),
1427 ("BIT+CR*N", (LBIT
+ CRN
)),
1428 ("CR*N+BIT", (CRN
+ RBIT
)),
1429 ("BIT+N*CR", (LBIT
+ NCR
)),
1430 ("N*CR+BIT", (NCR
+ RBIT
)),
1433 def remap(self
, value
, vector
, regtype
):
1434 if regtype
is _RegType
.CR_5BIT
:
1435 subvalue
= (value
& 0b11)
1439 extra
= (value
& 0b1111)
1442 extra
= (value
>> 3)
1445 if self
.record
.etype
is _SVEType
.EXTRA2
:
1447 assert (extra
& 0b111) == 0, \
1448 "vector CR cannot fit into EXTRA2"
1449 extra
= (0b10 |
(extra
>> 3))
1451 assert (extra
>> 1) == 0, \
1452 "scalar CR cannot fit into EXTRA2"
1454 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1456 assert (extra
& 0b11) == 0, \
1457 "vector CR cannot fit into EXTRA3"
1458 extra
= (0b100 |
(extra
>> 2))
1460 assert (extra
>> 2) == 0, \
1461 "scalar CR cannot fit into EXTRA3"
1464 if regtype
is _RegType
.CR_5BIT
:
1465 value
= ((value
<< 2) | subvalue
)
1467 return (value
, extra
)
1469 def assemble(self
, insn
, value
):
1470 if isinstance(value
, str):
1473 if value
.startswith("*"):
1474 if not isinstance(insn
, SVP64Instruction
):
1475 raise ValueError(value
)
1479 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1480 match
= pattern
.match(value
)
1481 if match
is not None:
1482 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1483 values
= match
.groups()
1484 match
= dict(zip(keys
, values
))
1485 CR
= int(match
["CR"])
1489 N
= int(match
.get("N", "1"))
1490 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1491 value
= ((CR
* N
) + BIT
)
1498 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1500 def disassemble(self
, insn
,
1501 style
=Style
.NORMAL
, prefix
="", indent
=""):
1502 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1504 if style
>= Style
.VERBOSE
:
1505 mode
= "vector" if vector
else "scalar"
1506 yield f
"{indent}{self.name} ({mode})"
1507 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1508 yield f
"{indent}{indent}{', '.join(span)}"
1509 if isinstance(insn
, SVP64Instruction
):
1510 for extra_idx
in frozenset(self
.extra_idx
):
1511 if self
.record
.etype
is _SVEType
.NONE
:
1512 yield f
"{indent}{indent}extra[none]"
1514 etype
= repr(self
.record
.etype
).lower()
1515 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1517 vector
= "*" if vector
else ""
1518 CR
= int(value
>> 2)
1520 cond
= ("lt", "gt", "eq", "so")[CC
]
1521 if style
>= Style
.NORMAL
:
1523 if isinstance(insn
, SVP64Instruction
):
1524 yield f
"{vector}cr{CR}.{cond}"
1526 yield f
"4*cr{CR}+{cond}"
1530 yield f
"{vector}{prefix}{int(value)}"
1533 class CR3Operand(ConditionRegisterFieldOperand
):
1534 def remap(self
, value
, vector
):
1535 return super().remap(value
=value
, vector
=vector
,
1536 regtype
=_RegType
.CR_3BIT
)
1539 class CR5Operand(ConditionRegisterFieldOperand
):
1540 def remap(self
, value
, vector
):
1541 return super().remap(value
=value
, vector
=vector
,
1542 regtype
=_RegType
.CR_5BIT
)
1544 def sv_spec_enter(self
, value
, span
):
1545 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1546 return (value
, span
)
1548 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1549 value
= _selectconcat(value
, origin_value
[3:5])
1551 return (value
, span
)
1554 class EXTSOperand(SignedOperand
):
1555 field
: str # real name to report
1556 nz
: int = 0 # number of zeros
1557 fmt
: str = "d" # integer formatter
1559 def __init__(self
, record
, name
, field
, nz
=0, fmt
="d"):
1560 self
.__field
= field
1563 return super().__init
__(record
=record
, name
=name
)
1579 return self
.record
.fields
[self
.field
]
1581 def assemble(self
, insn
, value
):
1583 if isinstance(value
, str):
1584 value
= int(value
, 0)
1585 insn
[span
] = (value
>> self
.nz
)
1587 def disassemble(self
, insn
,
1588 style
=Style
.NORMAL
, indent
=""):
1590 value
= insn
[span
].to_signed_int()
1591 sign
= "-" if (value
< 0) else ""
1592 value
= (abs(value
) << self
.nz
)
1594 if style
>= Style
.VERBOSE
:
1595 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1596 zeros
= ("0" * self
.nz
)
1597 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1598 yield f
"{indent * 1}{hint}"
1599 yield f
"{indent * 2}{self.field}"
1600 yield f
"{indent * 3}{sign}{value:{self.fmt}}"
1601 yield f
"{indent * 3}{', '.join(span)}"
1603 yield f
"{sign}{value:{self.fmt}}"
1606 class TargetAddrOperand(EXTSOperand
):
1607 def __init__(self
, record
, name
, field
):
1608 return super().__init
__(record
=record
, name
=name
, field
=field
,
1612 class TargetAddrOperandLI(TargetAddrOperand
):
1613 def __init__(self
, record
, name
):
1614 return super().__init
__(record
=record
, name
=name
, field
="LI")
1617 class TargetAddrOperandBD(TargetAddrOperand
):
1618 def __init__(self
, record
, name
):
1619 return super().__init
__(record
=record
, name
=name
, field
="BD")
1622 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1623 def __init__(self
, record
, name
):
1624 return super().__init
__(record
=record
, name
=name
, field
="DS", nz
=2)
1627 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1628 def __init__(self
, record
, name
):
1629 return super().__init
__(record
=record
, name
=name
, field
="DQ", nz
=4)
1632 class DOperandDX(SignedOperand
):
1635 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1636 operands
= map(cls
, ("d0", "d1", "d2"))
1637 spans
= map(lambda operand
: operand
.span
, operands
)
1638 return sum(spans
, tuple())
1640 def disassemble(self
, insn
,
1641 style
=Style
.NORMAL
, indent
=""):
1643 value
= insn
[span
].to_signed_int()
1644 sign
= "-" if (value
< 0) else ""
1647 if style
>= Style
.VERBOSE
:
1654 for (subname
, subspan
) in mapping
.items():
1655 operand
= DynamicOperand(name
=subname
)
1657 span
= map(str, span
)
1658 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1659 yield f
"{indent}{indent}{indent}{sign}{value}"
1660 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1662 yield f
"{sign}{value}"
1665 class Instruction(_Mapping
):
1667 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1668 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1669 raise ValueError(bits
)
1671 if isinstance(value
, bytes
):
1672 if ((len(value
) * 8) != bits
):
1673 raise ValueError(f
"bit length mismatch")
1674 value
= int.from_bytes(value
, byteorder
=byteorder
)
1676 if isinstance(value
, int):
1677 value
= _SelectableInt(value
=value
, bits
=bits
)
1678 elif isinstance(value
, Instruction
):
1679 value
= value
.storage
1681 if not isinstance(value
, _SelectableInt
):
1682 raise ValueError(value
)
1685 if len(value
) != bits
:
1686 raise ValueError(value
)
1688 value
= _SelectableInt(value
=value
, bits
=bits
)
1690 return cls(storage
=value
)
1693 return hash(int(self
))
1695 def __getitem__(self
, key
):
1696 return self
.storage
.__getitem
__(key
)
1698 def __setitem__(self
, key
, value
):
1699 return self
.storage
.__setitem
__(key
, value
)
1701 def bytes(self
, byteorder
="little"):
1702 nr_bytes
= (len(self
.__class
__) // 8)
1703 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1706 def record(cls
, db
, entry
):
1709 raise KeyError(entry
)
1713 def operands(cls
, record
):
1714 yield from record
.operands
1717 def static_operands(cls
, record
):
1718 return filter(lambda operand
: isinstance(operand
, StaticOperand
),
1719 cls
.operands(record
=record
))
1722 def dynamic_operands(cls
, record
):
1723 return filter(lambda operand
: isinstance(operand
, DynamicOperand
),
1724 cls
.operands(record
=record
))
1726 def spec(self
, record
, prefix
):
1727 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1728 self
.spec_dynamic_operands(record
=record
)))
1730 static_operands
= []
1731 for (name
, value
) in self
.spec_static_operands(record
=record
):
1732 static_operands
.append(f
"{name}={value}")
1735 if dynamic_operands
:
1737 operands
+= ",".join(dynamic_operands
)
1740 operands
+= " ".join(static_operands
)
1742 return f
"{prefix}{record.name}{operands}"
1744 def spec_static_operands(self
, record
):
1745 for operand
in self
.static_operands(record
=record
):
1746 if not isinstance(operand
, (POStaticOperand
, XOStaticOperand
)):
1747 yield (operand
.name
, operand
.value
)
1749 def spec_dynamic_operands(self
, record
, style
=Style
.NORMAL
):
1753 for operand
in self
.dynamic_operands(record
=record
):
1755 value
= " ".join(operand
.disassemble(insn
=self
,
1756 style
=min(style
, Style
.NORMAL
)))
1758 name
= f
"{imm_name}({name})"
1759 value
= f
"{imm_value}({value})"
1761 if isinstance(operand
, ImmediateOperand
):
1769 def assemble(cls
, record
, arguments
=None):
1770 if arguments
is None:
1773 insn
= cls
.integer(value
=0)
1775 for operand
in cls
.static_operands(record
=record
):
1776 operand
.assemble(insn
=insn
)
1778 arguments
= Arguments(record
=record
,
1779 arguments
=arguments
, operands
=cls
.dynamic_operands(record
=record
))
1780 for (value
, operand
) in arguments
:
1781 operand
.assemble(insn
=insn
, value
=value
)
1785 def disassemble(self
, record
,
1787 style
=Style
.NORMAL
):
1788 raise NotImplementedError()
1791 class WordInstruction(Instruction
):
1792 _
: _Field
= range(0, 32)
1793 PO
: _Field
= range(0, 6)
1796 def integer(cls
, value
, byteorder
="little"):
1797 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1802 for idx
in range(32):
1803 bit
= int(self
[idx
])
1805 return "".join(map(str, bits
))
1807 def disassemble(self
, record
,
1809 style
=Style
.NORMAL
):
1810 if style
<= Style
.SHORT
:
1813 blob
= self
.bytes(byteorder
=byteorder
)
1814 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1818 yield f
"{blob}.long 0x{int(self):08x}"
1821 # awful temporary hack: workaround for ld-update
1822 # https://bugs.libre-soc.org/show_bug.cgi?id=1056#c2
1823 # XXX TODO must check that *EXTENDED* RA != extended-RT
1824 if (record
.svp64
is not None and
1825 record
.mode
== _SVMode
.LDST_IMM
and
1826 'u' in record
.name
):
1827 yield f
"{blob}.long 0x{int(self):08x}"
1831 if style
is Style
.LEGACY
:
1833 for operand
in self
.dynamic_operands(record
=record
):
1834 if isinstance(operand
, (GPRPairOperand
, FPRPairOperand
)):
1837 if style
is Style
.LEGACY
and (paired
or record
.ppc
.unofficial
):
1838 yield f
"{blob}.long 0x{int(self):08x}"
1840 operands
= tuple(map(_operator
.itemgetter(1),
1841 self
.spec_dynamic_operands(record
=record
, style
=style
)))
1843 operands
= ",".join(operands
)
1844 yield f
"{blob}{record.name} {operands}"
1846 yield f
"{blob}{record.name}"
1848 if style
>= Style
.VERBOSE
:
1850 binary
= self
.binary
1851 spec
= self
.spec(record
=record
, prefix
="")
1852 yield f
"{indent}spec"
1853 yield f
"{indent}{indent}{spec}"
1854 yield f
"{indent}pcode"
1855 for stmt
in record
.mdwn
.pcode
:
1856 yield f
"{indent}{indent}{stmt}"
1857 yield f
"{indent}binary"
1858 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1859 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1860 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1861 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1862 yield f
"{indent}opcodes"
1863 for opcode
in record
.opcodes
:
1864 yield f
"{indent}{indent}{opcode!r}"
1865 for operand
in self
.operands(record
=record
):
1866 yield from operand
.disassemble(insn
=self
,
1867 style
=style
, indent
=indent
)
1871 class PrefixedInstruction(Instruction
):
1872 class Prefix(WordInstruction
.remap(range(0, 32))):
1875 class Suffix(WordInstruction
.remap(range(32, 64))):
1878 _
: _Field
= range(64)
1884 def integer(cls
, value
, byteorder
="little"):
1885 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
1888 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
1889 def transform(value
):
1890 return WordInstruction
.integer(value
=value
,
1891 byteorder
=byteorder
)[0:32]
1893 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
1894 value
= _selectconcat(prefix
, suffix
)
1896 return super().integer(bits
=64, value
=value
)
1899 class Mode(_Mapping
):
1900 _
: _Field
= range(0, 5)
1901 sel
: _Field
= (0, 1)
1904 class Extra(_Mapping
):
1905 _
: _Field
= range(0, 9)
1908 class Extra2(Extra
):
1909 idx0
: _Field
= range(0, 2)
1910 idx1
: _Field
= range(2, 4)
1911 idx2
: _Field
= range(4, 6)
1912 idx3
: _Field
= range(6, 8)
1914 def __getitem__(self
, key
):
1920 _SVExtra
.Idx0
: self
.idx0
,
1921 _SVExtra
.Idx1
: self
.idx1
,
1922 _SVExtra
.Idx2
: self
.idx2
,
1923 _SVExtra
.Idx3
: self
.idx3
,
1926 def __setitem__(self
, key
, value
):
1927 self
[key
].assign(value
)
1930 class Extra3(Extra
):
1931 idx0
: _Field
= range(0, 3)
1932 idx1
: _Field
= range(3, 6)
1933 idx2
: _Field
= range(6, 9)
1935 def __getitem__(self
, key
):
1940 _SVExtra
.Idx0
: self
.idx0
,
1941 _SVExtra
.Idx1
: self
.idx1
,
1942 _SVExtra
.Idx2
: self
.idx2
,
1945 def __setitem__(self
, key
, value
):
1946 self
[key
].assign(value
)
1949 class BaseRM(_Mapping
):
1950 _
: _Field
= range(24)
1951 mmode
: _Field
= (0,)
1952 mask
: _Field
= range(1, 4)
1953 elwidth
: _Field
= range(4, 6)
1954 ewsrc
: _Field
= range(6, 8)
1955 subvl
: _Field
= range(8, 10)
1956 mode
: Mode
.remap(range(19, 24))
1957 smask_extra322
: _Field
= (6,7,18,) # LDST_IDX is EXTRA332
1958 smask
: _Field
= range(16, 19) # everything else use this
1959 extra
: Extra
.remap(range(10, 19))
1960 extra2
: Extra2
.remap(range(10, 19))
1961 extra3
: Extra3
.remap(range(10, 19))
1962 # XXX extra332 = (extra3[0], extra3[1], extra2[3])
1964 def specifiers(self
, record
):
1965 subvl
= int(self
.subvl
)
1973 def disassemble(self
, style
=Style
.NORMAL
):
1974 if style
>= Style
.VERBOSE
:
1976 for (name
, span
) in self
.traverse(path
="RM"):
1977 value
= self
.storage
[span
]
1979 yield f
"{indent}{int(value):0{value.bits}b}"
1980 yield f
"{indent}{', '.join(map(str, span))}"
1983 class FFRc1BaseRM(BaseRM
):
1984 def specifiers(self
, record
, mode
):
1985 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
1986 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
1987 mask
= int(_selectconcat(CR
, inv
))
1988 predicate
= PredicateBaseRM
.predicate(True, mask
)
1989 yield f
"{mode}={predicate}"
1991 yield from super().specifiers(record
=record
)
1994 class FFRc0BaseRM(BaseRM
):
1995 def specifiers(self
, record
, mode
):
1997 inv
= "~" if self
.inv
else ""
1998 yield f
"{mode}={inv}RC1"
2000 yield from super().specifiers(record
=record
)
2003 class SatBaseRM(BaseRM
):
2004 def specifiers(self
, record
):
2010 yield from super().specifiers(record
=record
)
2013 class ZZBaseRM(BaseRM
):
2014 def specifiers(self
, record
):
2018 yield from super().specifiers(record
=record
)
2021 class ZZCombinedBaseRM(BaseRM
):
2022 def specifiers(self
, record
):
2023 if self
.sz
and self
.dz
:
2030 yield from super().specifiers(record
=record
)
2033 class DZBaseRM(BaseRM
):
2034 def specifiers(self
, record
):
2038 yield from super().specifiers(record
=record
)
2041 class SZBaseRM(BaseRM
):
2042 def specifiers(self
, record
):
2046 yield from super().specifiers(record
=record
)
2049 class MRBaseRM(BaseRM
):
2050 def specifiers(self
, record
):
2056 yield from super().specifiers(record
=record
)
2059 class ElsBaseRM(BaseRM
):
2060 def specifiers(self
, record
):
2064 yield from super().specifiers(record
=record
)
2067 class WidthBaseRM(BaseRM
):
2069 def width(FP
, width
):
2078 width
= ("fp" + width
)
2081 def specifiers(self
, record
):
2082 # elwidths: use "w=" if same otherwise dw/sw
2083 # FIXME this should consider FP instructions
2085 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
2086 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2087 if record
.svp64
.mode
is _SVMode
.CROP
:
2091 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2100 yield from super().specifiers(record
=record
)
2103 class PredicateBaseRM(BaseRM
):
2105 def predicate(CR
, mask
):
2108 (False, 0b001): "1<<r3",
2109 (False, 0b010): "r3",
2110 (False, 0b011): "~r3",
2111 (False, 0b100): "r10",
2112 (False, 0b101): "~r10",
2113 (False, 0b110): "r30",
2114 (False, 0b111): "~r30",
2116 (True, 0b000): "lt",
2117 (True, 0b001): "ge",
2118 (True, 0b010): "gt",
2119 (True, 0b011): "le",
2120 (True, 0b100): "eq",
2121 (True, 0b101): "ne",
2122 (True, 0b110): "so",
2123 (True, 0b111): "ns",
2126 def specifiers(self
, record
):
2127 # predication - single and twin
2128 # use "m=" if same otherwise sm/dm
2129 CR
= (int(self
.mmode
) == 1)
2130 mask
= int(self
.mask
)
2131 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
2132 if record
.svp64
.ptype
is _SVPType
.P2
:
2133 # LDST_IDX smask moving to extra322 but not straight away (False)
2134 if False and record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2135 smask
= int(self
.smask_extra332
)
2137 smask
= int(self
.smask
)
2138 sm
= PredicateBaseRM
.predicate(CR
, smask
)
2147 yield from super().specifiers(record
=record
)
2150 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
2154 class SEABaseRM(BaseRM
):
2155 def specifiers(self
, record
):
2159 yield from super().specifiers(record
=record
)
2162 class VLiBaseRM(BaseRM
):
2163 def specifiers(self
, record
):
2167 yield from super().specifiers(record
=record
)
2170 class NormalBaseRM(PredicateWidthBaseRM
):
2173 https://libre-soc.org/openpower/sv/normal/
2178 class NormalSimpleRM(ZZCombinedBaseRM
, NormalBaseRM
):
2179 """normal: simple mode"""
2183 def specifiers(self
, record
):
2184 yield from super().specifiers(record
=record
)
2187 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
2188 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
2192 class NormalFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, NormalBaseRM
):
2193 """normal: Rc=1: ffirst CR sel"""
2196 CR
: BaseRM
.mode
[3, 4]
2198 def specifiers(self
, record
):
2199 yield from super().specifiers(record
=record
, mode
="ff")
2202 class NormalFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
2203 """normal: Rc=0: ffirst z/nonz"""
2208 def specifiers(self
, record
):
2209 yield from super().specifiers(record
=record
, mode
="ff")
2212 class NormalSatRM(SatBaseRM
, ZZCombinedBaseRM
, NormalBaseRM
):
2213 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2219 class NormalRM(NormalBaseRM
):
2220 simple
: NormalSimpleRM
2222 ffrc1
: NormalFFRc1RM
2223 ffrc0
: NormalFFRc0RM
2227 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2229 LD/ST Immediate mode
2230 https://libre-soc.org/openpower/sv/ldst/
2235 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2236 """ld/st immediate: simple mode"""
2237 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2238 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2244 def specifiers(self
, record
):
2250 yield from super().specifiers(record
=record
)
2253 class LDSTFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2254 """ld/st immediate&indexed: Rc=1: ffirst CR sel"""
2257 CR
: BaseRM
.mode
[3, 4]
2259 def specifiers(self
, record
):
2260 yield from super().specifiers(record
=record
, mode
="ff")
2263 class LDSTFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2264 """ld/st immediate&indexed: Rc=0: ffirst z/nonz"""
2269 def specifiers(self
, record
):
2270 yield from super().specifiers(record
=record
, mode
="ff")
2273 class LDSTImmRM(LDSTImmBaseRM
):
2274 simple
: LDSTImmSimpleRM
2279 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2282 https://libre-soc.org/openpower/sv/ldst/
2287 class LDSTIdxSimpleRM(SEABaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2288 """ld/st index: simple mode (includes element-strided and Signed-EA)"""
2289 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2296 def specifiers(self
, record
):
2302 yield from super().specifiers(record
=record
)
2305 class LDSTIdxRM(LDSTIdxBaseRM
):
2306 simple
: LDSTIdxSimpleRM
2312 class CROpBaseRM(BaseRM
):
2315 https://libre-soc.org/openpower/sv/cr_ops/
2320 class CROpSimpleRM(PredicateBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2321 """crop: simple mode"""
2326 def specifiers(self
, record
):
2328 yield "rg" # simple CR Mode reports /rg
2330 yield from super().specifiers(record
=record
)
2333 class CROpMRRM(MRBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2334 """crop: scalar reduce mode (mapreduce)"""
2340 class CROpFF5RM(FFRc0BaseRM
, PredicateBaseRM
, VLiBaseRM
, DZBaseRM
,
2341 SZBaseRM
, CROpBaseRM
):
2342 """crop: ffirst 5-bit mode"""
2349 def specifiers(self
, record
):
2350 yield from super().specifiers(record
=record
, mode
="ff")
2353 # FIXME: almost everything in this class contradicts the specs (it doesn't)
2354 # The modes however are swapped: 5-bit is 3-bit, 3-bit is 5-bit
2355 class CROpFF3RM(FFRc1BaseRM
, PredicateBaseRM
, VLiBaseRM
, ZZBaseRM
, CROpBaseRM
):
2356 """cr_op: ffirst 3-bit mode"""
2362 def specifiers(self
, record
):
2363 yield from super().specifiers(record
=record
, mode
="ff")
2366 class CROpRM(CROpBaseRM
):
2367 simple
: CROpSimpleRM
2373 # ********************
2375 # https://libre-soc.org/openpower/sv/branches/
2376 class BranchBaseRM(BaseRM
):
2386 def specifiers(self
, record
):
2398 raise ValueError(self
.sz
)
2410 # Branch modes lack source mask.
2411 # Therefore a custom code is needed.
2412 CR
= (int(self
.mmode
) == 1)
2413 mask
= int(self
.mask
)
2414 m
= PredicateBaseRM
.predicate(CR
, mask
)
2418 yield from super().specifiers(record
=record
)
2421 class BranchSimpleRM(BranchBaseRM
):
2422 """branch: simple mode"""
2426 class BranchVLSRM(BranchBaseRM
):
2427 """branch: VLSET mode"""
2431 def specifiers(self
, record
):
2437 }[int(self
.VSb
), int(self
.VLi
)]
2439 yield from super().specifiers(record
=record
)
2442 class BranchCTRRM(BranchBaseRM
):
2443 """branch: CTR-test mode"""
2446 def specifiers(self
, record
):
2452 yield from super().specifiers(record
=record
)
2455 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2456 """branch: CTR-test+VLSET mode"""
2460 class BranchRM(BranchBaseRM
):
2461 simple
: BranchSimpleRM
2464 ctrvls
: BranchCTRVLSRM
2475 @_dataclasses.dataclass(eq
=True, frozen
=True)
2480 def match(cls
, desc
, record
):
2481 raise NotImplementedError()
2483 def validate(self
, others
):
2486 def assemble(self
, insn
):
2487 raise NotImplementedError()
2490 @_dataclasses.dataclass(eq
=True, frozen
=True)
2491 class SpecifierWidth(Specifier
):
2495 def match(cls
, desc
, record
, etalon
):
2496 (mode
, _
, value
) = desc
.partition("=")
2498 value
= value
.strip()
2501 width
= _SVP64Width(value
)
2503 return cls(record
=record
, width
=width
)
2506 @_dataclasses.dataclass(eq
=True, frozen
=True)
2507 class SpecifierW(SpecifierWidth
):
2509 def match(cls
, desc
, record
):
2510 return super().match(desc
=desc
, record
=record
, etalon
="w")
2512 def assemble(self
, insn
):
2513 selector
= insn
.select(record
=self
.record
)
2514 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2515 selector
.ewsrc
= self
.width
.value
2516 selector
.elwidth
= self
.width
.value
2519 @_dataclasses.dataclass(eq
=True, frozen
=True)
2520 class SpecifierSW(SpecifierWidth
):
2522 def match(cls
, desc
, record
):
2523 if record
.svp64
.mode
is _SVMode
.CROP
:
2525 return super().match(desc
=desc
, record
=record
, etalon
="sw")
2527 def assemble(self
, insn
):
2528 selector
= insn
.select(record
=self
.record
)
2529 selector
.ewsrc
= self
.width
.value
2532 @_dataclasses.dataclass(eq
=True, frozen
=True)
2533 class SpecifierDW(SpecifierWidth
):
2535 def match(cls
, desc
, record
):
2536 return super().match(desc
=desc
, record
=record
, etalon
="dw")
2538 def assemble(self
, insn
):
2539 selector
= insn
.select(record
=self
.record
)
2540 selector
.elwidth
= self
.width
.value
2543 @_dataclasses.dataclass(eq
=True, frozen
=True)
2544 class SpecifierSubVL(Specifier
):
2548 def match(cls
, desc
, record
):
2550 value
= _SVP64SubVL(desc
)
2554 return cls(record
=record
, value
=value
)
2556 def assemble(self
, insn
):
2557 selector
= insn
.select(record
=self
.record
)
2558 selector
.subvl
= int(self
.value
.value
)
2561 @_dataclasses.dataclass(eq
=True, frozen
=True)
2562 class SpecifierPredicate(Specifier
):
2567 def match(cls
, desc
, record
, mode_match
, pred_match
):
2568 (mode
, _
, pred
) = desc
.partition("=")
2571 if not mode_match(mode
):
2574 pred
= _SVP64Pred(pred
.strip())
2575 if not pred_match(pred
):
2576 raise ValueError(pred
)
2578 return cls(record
=record
, mode
=mode
, pred
=pred
)
2581 @_dataclasses.dataclass(eq
=True, frozen
=True)
2582 class SpecifierFF(SpecifierPredicate
):
2584 def match(cls
, desc
, record
):
2585 return super().match(desc
=desc
, record
=record
,
2586 mode_match
=lambda mode_arg
: mode_arg
== "ff",
2587 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2592 def assemble(self
, insn
):
2593 selector
= insn
.select(record
=self
.record
)
2594 if selector
.mode
.sel
!= 0:
2595 raise ValueError("cannot override mode")
2596 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2597 selector
.mode
.sel
= 0b01
2598 # HACK: please finally provide correct logic for CRs.
2599 if self
.pred
in (_SVP64Pred
.RC1
, _SVP64Pred
.RC1_N
):
2600 selector
.mode
[2] = (self
.pred
is _SVP64Pred
.RC1_N
)
2602 selector
.mode
[2] = self
.pred
.inv
2603 selector
.mode
[3, 4] = self
.pred
.state
2605 selector
.mode
.sel
= 0b01 if self
.mode
== "ff" else 0b11
2606 selector
.inv
= self
.pred
.inv
2608 selector
.CR
= self
.pred
.state
2610 selector
.RC1
= self
.pred
.state
2613 @_dataclasses.dataclass(eq
=True, frozen
=True)
2614 class SpecifierMask(SpecifierPredicate
):
2616 def match(cls
, desc
, record
, mode
):
2617 return super().match(desc
=desc
, record
=record
,
2618 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2619 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2624 def assemble(self
, insn
):
2625 raise NotImplementedError()
2628 @_dataclasses.dataclass(eq
=True, frozen
=True)
2629 class SpecifierM(SpecifierMask
):
2631 def match(cls
, desc
, record
):
2632 return super().match(desc
=desc
, record
=record
, mode
="m")
2634 def validate(self
, others
):
2636 if isinstance(spec
, SpecifierSM
):
2637 raise ValueError("source-mask and predicate mask conflict")
2638 elif isinstance(spec
, SpecifierDM
):
2639 raise ValueError("dest-mask and predicate mask conflict")
2641 def assemble(self
, insn
):
2642 selector
= insn
.select(record
=self
.record
)
2643 selector
.mask
= int(self
.pred
)
2644 if ((self
.record
.ptype
is _SVPType
.P2
) and
2645 (self
.record
.svp64
.mode
is not _SVMode
.BRANCH
)):
2646 selector
.smask
= int(self
.pred
)
2647 # LDST_IDX smask moving to extra322 but not straight away (False)
2648 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2649 selector
.smask_extra332
= int(self
.pred
)
2651 selector
.smask
= int(self
.pred
)
2653 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2656 @_dataclasses.dataclass(eq
=True, frozen
=True)
2657 class SpecifierSM(SpecifierMask
):
2659 def match(cls
, desc
, record
):
2660 return super().match(desc
=desc
, record
=record
, mode
="sm")
2662 def validate(self
, others
):
2663 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2664 raise ValueError("source-mask on non-twin predicate")
2666 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2669 if isinstance(spec
, SpecifierDM
):
2673 raise ValueError("missing dest-mask in CR twin predication")
2674 if self
.pred
.mode
!= twin
.pred
.mode
:
2675 raise ValueError(f
"predicate masks mismatch: "
2676 f
"{self.pred!r} vs {twin.pred!r}")
2678 def assemble(self
, insn
):
2679 selector
= insn
.select(record
=self
.record
)
2680 # LDST_IDX smask moving to extra322 but not straight away (False)
2681 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2682 selector
.smask_extra332
= int(self
.pred
)
2684 selector
.smask
= int(self
.pred
)
2685 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2688 @_dataclasses.dataclass(eq
=True, frozen
=True)
2689 class SpecifierDM(SpecifierMask
):
2691 def match(cls
, desc
, record
):
2692 return super().match(desc
=desc
, record
=record
, mode
="dm")
2694 def validate(self
, others
):
2695 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2696 raise ValueError("dest-mask on non-twin predicate")
2698 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2701 if isinstance(spec
, SpecifierSM
):
2705 raise ValueError("missing source-mask in CR twin predication")
2706 if self
.pred
.mode
!= twin
.pred
.mode
:
2707 raise ValueError(f
"predicate masks mismatch: "
2708 f
"{self.pred!r} vs {twin.pred!r}")
2710 def assemble(self
, insn
):
2711 selector
= insn
.select(record
=self
.record
)
2712 selector
.mask
= int(self
.pred
)
2713 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2716 @_dataclasses.dataclass(eq
=True, frozen
=True)
2717 class SpecifierZZ(Specifier
):
2719 def match(cls
, desc
, record
):
2723 return cls(record
=record
)
2725 def validate(self
, others
):
2727 # Since zz takes precedence (overrides) sz and dz,
2728 # treat them as mutually exclusive.
2729 if isinstance(spec
, (SpecifierSZ
, SpecifierDZ
)):
2730 raise ValueError("mutually exclusive predicate masks")
2732 def assemble(self
, insn
):
2733 selector
= insn
.select(record
=self
.record
)
2734 if hasattr(selector
, "zz"): # this should be done in a different way
2741 @_dataclasses.dataclass(eq
=True, frozen
=True)
2742 class SpecifierXZ(Specifier
):
2744 hint
: str = _dataclasses
.field(repr=False)
2747 def match(cls
, desc
, record
, etalon
, hint
):
2751 return cls(desc
=desc
, record
=record
, hint
=hint
)
2753 def validate(self
, others
):
2754 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2755 raise ValueError(f
"{self.hint} on non-twin predicate")
2757 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2760 if isinstance(spec
, SpecifierXZ
):
2764 raise ValueError(f
"missing {self.hint} in CR twin predication")
2765 if self
.pred
!= twin
.pred
:
2766 raise ValueError(f
"predicate masks mismatch: "
2767 f
"{self.pred!r} vs {twin.pred!r}")
2769 def assemble(self
, insn
):
2770 selector
= insn
.select(record
=self
.record
)
2771 setattr(selector
, self
.desc
, 1)
2774 @_dataclasses.dataclass(eq
=True, frozen
=True)
2775 class SpecifierSZ(SpecifierXZ
):
2777 def match(cls
, desc
, record
):
2778 return super().match(desc
=desc
, record
=record
,
2779 etalon
="sz", hint
="source-mask")
2781 def validate(self
, others
):
2783 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2784 if isinstance(spec
, SpecifierFF
):
2785 raise ValueError("source-zero not allowed in ff mode")
2788 @_dataclasses.dataclass(eq
=True, frozen
=True)
2789 class SpecifierDZ(SpecifierXZ
):
2791 def match(cls
, desc
, record
):
2792 return super().match(desc
=desc
, record
=record
,
2793 etalon
="dz", hint
="dest-mask")
2795 def validate(self
, others
):
2797 if ((self
.record
.svp64
.mode
is not _SVMode
.CROP
) and
2798 isinstance(spec
, SpecifierFF
) and
2799 (spec
.pred
.mode
is _SVP64PredMode
.RC1
)):
2800 raise ValueError(f
"dest-zero not allowed in ff mode BO")
2803 @_dataclasses.dataclass(eq
=True, frozen
=True)
2804 class SpecifierEls(Specifier
):
2806 def match(cls
, desc
, record
):
2810 if record
.svp64
.mode
not in (_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
):
2811 raise ValueError("els is only valid in ld/st modes, not "
2812 "%s" % str(self
.record
.svp64
.mode
))
2814 return cls(record
=record
)
2816 def assemble(self
, insn
):
2817 if self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
: # stride mode
2818 insn
.prefix
.rm
.mode
[1] = 0
2820 selector
= insn
.select(record
=self
.record
)
2825 @_dataclasses.dataclass(eq
=True, frozen
=True)
2826 class SpecifierSEA(Specifier
):
2828 def match(cls
, desc
, record
):
2832 return cls(record
=record
)
2834 def validate(self
, others
):
2835 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
:
2836 raise ValueError("sea is only valid in ld/st modes, not "
2837 "%s" % str(self
.record
.svp64
.mode
))
2840 if isinstance(spec
, SpecifierFF
):
2841 raise ValueError(f
"sea cannot be used in ff mode")
2843 def assemble(self
, insn
):
2844 selector
= insn
.select(record
=self
.record
)
2845 if selector
.mode
.sel
not in (0b10, 0b00):
2846 raise ValueError("sea is only valid for normal and els modes, "
2847 "not %d" % int(selector
.mode
.sel
))
2851 @_dataclasses.dataclass(eq
=True, frozen
=True)
2852 class SpecifierSat(Specifier
):
2857 def match(cls
, desc
, record
, etalon
, sign
):
2861 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.LDST_IMM
,
2863 raise ValueError("only normal, ld/st imm and "
2864 "ld/st idx modes supported")
2866 return cls(record
=record
, desc
=desc
, sign
=sign
)
2868 def assemble(self
, insn
):
2869 selector
= insn
.select(record
=self
.record
)
2870 selector
.mode
[0] = 0b1
2871 selector
.mode
[1] = 0b0
2872 selector
.N
= int(self
.sign
)
2875 @_dataclasses.dataclass(eq
=True, frozen
=True)
2876 class SpecifierSatS(SpecifierSat
):
2878 def match(cls
, desc
, record
):
2879 return super().match(desc
=desc
, record
=record
,
2880 etalon
="sats", sign
=True)
2883 @_dataclasses.dataclass(eq
=True, frozen
=True)
2884 class SpecifierSatU(SpecifierSat
):
2886 def match(cls
, desc
, record
):
2887 return super().match(desc
=desc
, record
=record
,
2888 etalon
="satu", sign
=False)
2891 @_dataclasses.dataclass(eq
=True, frozen
=True)
2892 class SpecifierMapReduce(Specifier
):
2896 def match(cls
, record
, RG
):
2897 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2898 raise ValueError("only normal and crop modes supported")
2900 return cls(record
=record
, RG
=RG
)
2902 def assemble(self
, insn
):
2903 selector
= insn
.select(record
=self
.record
)
2904 if self
.record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2905 raise ValueError("only normal and crop modes supported")
2906 selector
.mode
[0] = 0
2907 selector
.mode
[1] = 0
2908 selector
.mode
[2] = 1
2909 selector
.RG
= self
.RG
2912 @_dataclasses.dataclass(eq
=True, frozen
=True)
2913 class SpecifierMR(SpecifierMapReduce
):
2915 def match(cls
, desc
, record
):
2919 return super().match(record
=record
, RG
=False)
2922 @_dataclasses.dataclass(eq
=True, frozen
=True)
2923 class SpecifierMRR(SpecifierMapReduce
):
2925 def match(cls
, desc
, record
):
2929 return super().match(record
=record
, RG
=True)
2932 @_dataclasses.dataclass(eq
=True, frozen
=True)
2933 class SpecifierBranch(Specifier
):
2935 def match(cls
, desc
, record
, etalon
):
2939 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
2940 raise ValueError("only branch modes supported")
2942 return cls(record
=record
)
2945 @_dataclasses.dataclass(eq
=True, frozen
=True)
2946 class SpecifierAll(SpecifierBranch
):
2948 def match(cls
, desc
, record
):
2949 return super().match(desc
=desc
, record
=record
, etalon
="all")
2951 def assemble(self
, insn
):
2952 selector
= insn
.select(record
=self
.record
)
2956 @_dataclasses.dataclass(eq
=True, frozen
=True)
2957 class SpecifierSNZ(Specifier
):
2959 def match(cls
, desc
, record
):
2963 if record
.svp64
.mode
not in (_SVMode
.BRANCH
, _SVMode
.CROP
):
2964 raise ValueError("only branch and crop modes supported")
2966 return cls(record
=record
)
2968 def assemble(self
, insn
):
2969 selector
= insn
.select(record
=self
.record
)
2970 if self
.record
.svp64
.mode
in (_SVMode
.CROP
, _SVMode
.BRANCH
):
2972 if self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
2975 raise ValueError("only branch and crop modes supported")
2978 @_dataclasses.dataclass(eq
=True, frozen
=True)
2979 class SpecifierSL(SpecifierBranch
):
2981 def match(cls
, desc
, record
):
2982 return super().match(desc
=desc
, record
=record
, etalon
="sl")
2984 def assemble(self
, insn
):
2985 selector
= insn
.select(record
=self
.record
)
2989 @_dataclasses.dataclass(eq
=True, frozen
=True)
2990 class SpecifierSLu(SpecifierBranch
):
2992 def match(cls
, desc
, record
):
2993 return super().match(desc
=desc
, record
=record
, etalon
="slu")
2995 def assemble(self
, insn
):
2996 selector
= insn
.select(record
=self
.record
)
3000 @_dataclasses.dataclass(eq
=True, frozen
=True)
3001 class SpecifierLRu(SpecifierBranch
):
3003 def match(cls
, desc
, record
):
3004 return super().match(desc
=desc
, record
=record
, etalon
="lru")
3006 def assemble(self
, insn
):
3007 selector
= insn
.select(record
=self
.record
)
3011 @_dataclasses.dataclass(eq
=True, frozen
=True)
3012 class SpecifierVSXX(SpecifierBranch
):
3017 def match(cls
, desc
, record
, etalon
, VSb
, VLi
):
3021 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3022 raise ValueError("only branch modes supported")
3024 return cls(record
=record
, VSb
=VSb
, VLi
=VLi
)
3026 def assemble(self
, insn
):
3027 selector
= insn
.select(record
=self
.record
)
3029 selector
.VSb
= int(self
.VSb
)
3030 selector
.VLi
= int(self
.VLi
)
3033 @_dataclasses.dataclass(eq
=True, frozen
=True)
3034 class SpecifierVS(SpecifierVSXX
):
3036 def match(cls
, desc
, record
):
3037 return super().match(desc
=desc
, record
=record
,
3038 etalon
="vs", VSb
=False, VLi
=False)
3041 @_dataclasses.dataclass(eq
=True, frozen
=True)
3042 class SpecifierVSi(SpecifierVSXX
):
3044 def match(cls
, desc
, record
):
3045 return super().match(desc
=desc
, record
=record
,
3046 etalon
="vsi", VSb
=False, VLi
=True)
3049 @_dataclasses.dataclass(eq
=True, frozen
=True)
3050 class SpecifierVSb(SpecifierVSXX
):
3052 def match(cls
, desc
, record
):
3053 return super().match(desc
=desc
, record
=record
,
3054 etalon
="vsb", VSb
=True, VLi
=False)
3057 @_dataclasses.dataclass(eq
=True, frozen
=True)
3058 class SpecifierVSbi(SpecifierVSXX
):
3060 def match(cls
, desc
, record
):
3061 return super().match(desc
=desc
, record
=record
,
3062 etalon
="vsbi", VSb
=True, VLi
=True)
3065 @_dataclasses.dataclass(eq
=True, frozen
=True)
3066 class SpecifierCTX(Specifier
):
3070 def match(cls
, desc
, record
, etalon
, CTi
):
3074 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3075 raise ValueError("only branch modes supported")
3077 return cls(record
=record
, CTi
=CTi
)
3079 def assemble(self
, insn
):
3080 selector
= insn
.select(record
=self
.record
)
3082 selector
.CTi
= int(self
.CTi
)
3085 @_dataclasses.dataclass(eq
=True, frozen
=True)
3086 class SpecifierCTR(SpecifierCTX
):
3088 def match(cls
, desc
, record
):
3089 return super().match(desc
=desc
, record
=record
,
3090 etalon
="ctr", CTi
=False)
3093 @_dataclasses.dataclass(eq
=True, frozen
=True)
3094 class SpecifierCTi(SpecifierCTX
):
3096 def match(cls
, desc
, record
):
3097 return super().match(desc
=desc
, record
=record
,
3098 etalon
="cti", CTi
=True)
3101 @_dataclasses.dataclass(eq
=True, frozen
=True)
3102 class SpecifierPI(Specifier
):
3104 def match(cls
, desc
, record
):
3108 if record
.svp64
.mode
not in [_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
]:
3109 raise ValueError("only ld/st imm/idx mode supported")
3111 return cls(record
=record
)
3113 def assemble(self
, insn
):
3114 selector
= insn
.select(record
=self
.record
)
3115 selector
.mode
[2] = 0b1
3119 @_dataclasses.dataclass(eq
=True, frozen
=True)
3120 class SpecifierLF(Specifier
):
3122 def match(cls
, desc
, record
):
3126 if record
.svp64
.mode
is not _SVMode
.LDST_IMM
:
3127 raise ValueError("only ld/st imm mode supported")
3129 return cls(record
=record
)
3131 def assemble(self
, insn
):
3132 selector
= insn
.select(record
=self
.record
)
3133 selector
.mode
[1] = 0
3137 @_dataclasses.dataclass(eq
=True, frozen
=True)
3138 class SpecifierVLi(Specifier
):
3140 def match(cls
, desc
, record
):
3144 return cls(record
=record
)
3146 def validate(self
, others
):
3148 if isinstance(spec
, SpecifierFF
):
3151 raise ValueError("VLi only allowed in failfirst")
3153 def assemble(self
, insn
):
3154 selector
= insn
.select(record
=self
.record
)
3155 selector
.mode
[1] = 1
3159 class Specifiers(tuple):
3194 def __new__(cls
, items
, record
):
3195 def transform(item
):
3196 for spec_cls
in cls
.SPECS
:
3197 spec
= spec_cls
.match(item
, record
=record
)
3198 if spec
is not None:
3200 raise ValueError(item
)
3202 # TODO: remove this hack
3203 items
= dict.fromkeys(items
)
3207 items
= tuple(items
)
3209 specs
= tuple(map(transform
, items
))
3210 for (index
, spec
) in enumerate(specs
):
3211 head
= specs
[:index
]
3212 tail
= specs
[index
+ 1:]
3213 spec
.validate(others
=(head
+ tail
))
3215 return super().__new
__(cls
, specs
)
3218 class SVP64OperandMeta(type):
3219 class SVP64NonZeroOperand(NonZeroOperand
):
3220 def assemble(self
, insn
, value
):
3221 if isinstance(value
, str):
3222 value
= int(value
, 0)
3223 if not isinstance(value
, int):
3224 raise ValueError("non-integer operand")
3226 # FIXME: this is really weird
3227 if self
.record
.name
in ("svstep", "svstep."):
3228 value
+= 1 # compensation
3230 return super().assemble(value
=value
, insn
=insn
)
3232 class SVP64XOStaticOperand(SpanStaticOperand
):
3233 def __init__(self
, record
, value
, span
):
3234 return super().__init
__(record
=record
, name
="XO",
3235 value
=value
, span
=span
)
3238 NonZeroOperand
: SVP64NonZeroOperand
,
3239 XOStaticOperand
: SVP64XOStaticOperand
,
3242 def __new__(metacls
, name
, bases
, ns
):
3244 for (index
, base_cls
) in enumerate(bases
):
3245 bases
[index
] = metacls
.__TRANSFORM
.get(base_cls
, base_cls
)
3247 bases
= tuple(bases
)
3249 return super().__new
__(metacls
, name
, bases
, ns
)
3252 class SVP64Operand(Operand
, metaclass
=SVP64OperandMeta
):
3255 return tuple(map(lambda bit
: (bit
+ 32), super().span
))
3259 def __init__(self
, insn
, record
):
3261 self
.__record
= record
3262 return super().__init
__()
3265 return self
.rm
.__doc
__
3268 return repr(self
.rm
)
3276 return self
.__record
3280 rm
= getattr(self
.insn
.prefix
.rm
, self
.record
.svp64
.mode
.name
.lower())
3282 # The idea behind these tables is that they are now literally
3283 # in identical format to insndb.csv and minor_xx.csv and can
3284 # be done precisely as that. The only thing to watch out for
3285 # is the insertion of Rc=1 as a "mask/value" bit and likewise
3286 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
3289 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
3290 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3291 # mode Rc mask Rc member
3293 (0b000000, 0b111000, "simple"), # simple (no Rc)
3294 (0b001000, 0b111100, "mr"), # mapreduce (no Rc)
3295 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3296 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3297 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3298 (0b001100, 0b111100, "rsvd"), # reserved
3300 mode
= int(self
.insn
.prefix
.rm
.normal
.mode
)
3301 search
= ((mode
<< 1) | self
.record
.Rc
)
3303 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
3304 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3305 # mode Rc mask Rc member
3306 # ironically/coincidentally this table is identical to NORMAL
3307 # mode except reserved in place of mr
3309 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3310 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3311 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3313 search
= ((int(self
.insn
.prefix
.rm
.ldst_imm
.mode
) << 1) |
3316 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
3317 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3318 # mode Rc mask Rc member
3320 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3321 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3322 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3324 search
= ((int(self
.insn
.prefix
.rm
.ldst_idx
.mode
) << 1) |
3327 elif self
.record
.svp64
.mode
is _SVMode
.CROP
:
3328 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
3329 # mode 3b mask 3b member
3331 (0b000000, 0b111000, "simple"), # simple
3332 (0b001000, 0b111000, "mr"), # mapreduce
3333 (0b010001, 0b010001, "ff3"), # ffirst, 3-bit CR
3334 (0b010000, 0b010000, "ff5"), # ffirst, 5-bit CR
3336 search
= ((int(self
.insn
.prefix
.rm
.crop
.mode
) << 1) |
3337 int(self
.record
.svp64
.extra_CR_3bit
))
3339 elif self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3343 (0b00, 0b11, "simple"), # simple
3344 (0b01, 0b11, "vls"), # VLset
3345 (0b10, 0b11, "ctr"), # CTR mode
3346 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
3348 # slightly weird: doesn't have a 5-bit "mode" field like others
3349 search
= int(self
.insn
.prefix
.rm
.branch
.mode
.sel
)
3352 if table
is not None:
3353 for (value
, mask
, field
) in table
:
3354 if field
.startswith("rsvd"):
3356 if ((value
& mask
) == (search
& mask
)):
3357 return getattr(rm
, field
)
3361 def __getattr__(self
, key
):
3362 if key
.startswith(f
"_{self.__class__.__name__}__"):
3363 return super().__getattribute
__(key
)
3365 return getattr(self
.rm
, key
)
3367 def __setattr__(self
, key
, value
):
3368 if key
.startswith(f
"_{self.__class__.__name__}__"):
3369 return super().__setattr
__(key
, value
)
3372 if not hasattr(rm
, key
):
3373 raise AttributeError(key
)
3375 return setattr(rm
, key
, value
)
3378 class SVP64Instruction(PrefixedInstruction
):
3379 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
3380 class Prefix(PrefixedInstruction
.Prefix
):
3382 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
3386 def select(self
, record
):
3387 return RMSelector(insn
=self
, record
=record
)
3392 for idx
in range(64):
3393 bit
= int(self
[idx
])
3395 return "".join(map(str, bits
))
3398 def assemble(cls
, record
, arguments
=None, specifiers
=None):
3399 insn
= super().assemble(record
=record
, arguments
=arguments
)
3401 specifiers
= Specifiers(items
=specifiers
, record
=record
)
3402 for specifier
in specifiers
:
3403 specifier
.assemble(insn
=insn
)
3405 insn
.prefix
.PO
= 0x1
3406 insn
.prefix
.id = 0x3
3410 def disassemble(self
, record
,
3412 style
=Style
.NORMAL
):
3414 if style
<= Style
.SHORT
:
3417 blob
= insn
.bytes(byteorder
=byteorder
)
3418 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
3421 blob_prefix
= blob(self
.prefix
)
3422 blob_suffix
= blob(self
.suffix
)
3424 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3425 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
3428 assert record
.svp64
is not None
3430 name
= f
"sv.{record.name}"
3432 rm
= self
.select(record
=record
)
3434 # convert specifiers to /x/y/z (sorted lexicographically)
3435 specifiers
= sorted(rm
.specifiers(record
=record
))
3436 if specifiers
: # if any add one extra to get the extra "/"
3437 specifiers
= ([""] + specifiers
)
3438 specifiers
= "/".join(specifiers
)
3440 # convert operands to " ,x,y,z"
3441 operands
= tuple(map(_operator
.itemgetter(1),
3442 self
.spec_dynamic_operands(record
=record
, style
=style
)))
3443 operands
= ",".join(operands
)
3444 if len(operands
) > 0: # if any separate with a space
3445 operands
= (" " + operands
)
3447 if style
<= Style
.LEGACY
:
3448 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3449 suffix
= WordInstruction
.integer(value
=int(self
.suffix
))
3450 yield from suffix
.disassemble(record
=record
,
3451 byteorder
=byteorder
, style
=style
)
3453 yield f
"{blob_prefix}{name}{specifiers}{operands}"
3455 yield f
"{blob_suffix}"
3457 if style
>= Style
.VERBOSE
:
3459 binary
= self
.binary
3460 spec
= self
.spec(record
=record
, prefix
="sv.")
3462 yield f
"{indent}spec"
3463 yield f
"{indent}{indent}{spec}"
3464 yield f
"{indent}pcode"
3465 for stmt
in record
.mdwn
.pcode
:
3466 yield f
"{indent}{indent}{stmt}"
3467 yield f
"{indent}binary"
3468 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
3469 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
3470 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
3471 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
3472 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
3473 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
3474 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
3475 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
3476 yield f
"{indent}opcodes"
3477 for opcode
in record
.opcodes
:
3478 yield f
"{indent}{indent}{opcode!r}"
3479 for operand
in self
.operands(record
=record
):
3480 yield from operand
.disassemble(insn
=self
,
3481 style
=style
, indent
=indent
)
3483 yield f
"{indent}{indent}{str(rm)}"
3484 for line
in rm
.disassemble(style
=style
):
3485 yield f
"{indent}{indent}{line}"
3489 def operands(cls
, record
):
3490 for operand
in super().operands(record
=record
):
3491 parent
= operand
.__class
__
3492 name
= f
"SVP64{parent.__name__}"
3493 bases
= (SVP64Operand
, parent
)
3494 child
= type(name
, bases
, {})
3495 yield child(**dict(operand
))
3498 def parse(stream
, factory
):
3500 return ("TODO" not in frozenset(entry
.values()))
3502 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
3503 entries
= _csv
.DictReader(lines
)
3504 entries
= filter(match
, entries
)
3505 return tuple(map(factory
, entries
))
3508 class MarkdownDatabase
:
3511 for (name
, desc
) in _ISA():
3514 (dynamic
, *static
) = desc
.regs
3515 operands
.extend(dynamic
)
3516 operands
.extend(static
)
3517 pcode
= PCode(iterable
=filter(str.strip
, desc
.pcode
))
3518 operands
= Operands(insn
=name
, operands
=operands
)
3519 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
3521 self
.__db
= dict(sorted(db
.items()))
3523 return super().__init
__()
3526 yield from self
.__db
.items()
3528 def __contains__(self
, key
):
3529 return self
.__db
.__contains
__(key
)
3531 def __getitem__(self
, key
):
3532 return self
.__db
.__getitem
__(key
)
3535 class FieldsDatabase
:
3538 df
= _DecodeFields()
3540 for (form
, fields
) in df
.instrs
.items():
3541 if form
in {"DQE", "TX"}:
3545 db
[_Form
[form
]] = Fields(fields
)
3549 return super().__init
__()
3551 def __getitem__(self
, key
):
3552 return self
.__db
.__getitem
__(key
)
3556 def __init__(self
, root
, mdwndb
):
3557 # The code below groups the instructions by name:section.
3558 # There can be multiple names for the same instruction.
3559 # The point is to capture different opcodes for the same instruction.
3561 records
= _collections
.defaultdict(set)
3562 path
= (root
/ "insndb.csv")
3563 with
open(path
, "r", encoding
="UTF-8") as stream
:
3564 for section
in sorted(parse(stream
, Section
.CSV
)):
3565 path
= (root
/ section
.path
)
3567 section
.Mode
.INTEGER
: IntegerOpcode
,
3568 section
.Mode
.PATTERN
: PatternOpcode
,
3570 factory
= _functools
.partial(
3571 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
3572 with
open(path
, "r", encoding
="UTF-8") as stream
:
3573 for insn
in parse(stream
, factory
):
3574 for name
in insn
.names
:
3575 records
[name
].add(insn
)
3576 sections
[name
] = section
3578 items
= sorted(records
.items())
3580 for (name
, multirecord
) in items
:
3581 records
[name
] = PPCMultiRecord(sorted(multirecord
))
3583 def exact_match(name
):
3584 record
= records
.get(name
)
3590 if not name
.endswith("l"):
3592 alias
= exact_match(name
[:-1])
3595 record
= records
[alias
]
3596 if "lk" not in record
.flags
:
3597 raise ValueError(record
)
3601 if not name
.endswith("a"):
3603 alias
= LK_match(name
[:-1])
3606 record
= records
[alias
]
3607 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
3608 raise ValueError(record
)
3609 if "AA" not in mdwndb
[name
].operands
:
3610 raise ValueError(record
)
3614 if not name
.endswith("."):
3616 alias
= exact_match(name
[:-1])
3619 record
= records
[alias
]
3620 if record
.Rc
is _RCOE
.NONE
:
3621 raise ValueError(record
)
3625 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
3626 for (name
, _
) in mdwndb
:
3627 if name
.startswith("sv."):
3630 for match
in matches
:
3632 if alias
is not None:
3636 section
= sections
[alias
]
3637 record
= records
[alias
]
3638 db
[name
] = (section
, record
)
3640 self
.__db
= dict(sorted(db
.items()))
3642 return super().__init
__()
3644 @_functools.lru_cache(maxsize
=512, typed
=False)
3645 def __getitem__(self
, key
):
3646 return self
.__db
.get(key
, (None, None))
3649 class SVP64Database
:
3650 def __init__(self
, root
, ppcdb
):
3652 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
3653 for (prefix
, _
, names
) in _os
.walk(root
):
3654 prefix
= _pathlib
.Path(prefix
)
3655 for name
in filter(lambda name
: pattern
.match(name
), names
):
3656 path
= (prefix
/ _pathlib
.Path(name
))
3657 with
open(path
, "r", encoding
="UTF-8") as stream
:
3658 db
.update(parse(stream
, SVP64Record
.CSV
))
3659 db
= {record
.name
:record
for record
in db
}
3661 self
.__db
= dict(sorted(db
.items()))
3662 self
.__ppcdb
= ppcdb
3664 return super().__init
__()
3666 def __getitem__(self
, key
):
3667 (_
, record
) = self
.__ppcdb
[key
]
3671 for name
in record
.names
:
3672 record
= self
.__db
.get(name
, None)
3673 if record
is not None:
3680 def __init__(self
, root
):
3681 root
= _pathlib
.Path(root
)
3682 mdwndb
= MarkdownDatabase()
3683 fieldsdb
= FieldsDatabase()
3684 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
3685 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
3689 opcodes
= _collections
.defaultdict(
3690 lambda: _collections
.defaultdict(set))
3692 for (name
, mdwn
) in mdwndb
:
3693 if name
.startswith("sv."):
3695 (section
, ppc
) = ppcdb
[name
]
3698 svp64
= svp64db
[name
]
3699 fields
= fieldsdb
[ppc
.form
]
3700 record
= Record(name
=name
,
3701 section
=section
, ppc
=ppc
, svp64
=svp64
,
3702 mdwn
=mdwn
, fields
=fields
)
3704 names
[record
.name
] = record
3705 opcodes
[section
][record
.PO
].add(record
)
3707 self
.__db
= sorted(db
)
3708 self
.__names
= dict(sorted(names
.items()))
3709 self
.__opcodes
= dict(sorted(opcodes
.items()))
3711 return super().__init
__()
3713 def visit(self
, visitor
):
3714 with visitor
.db(db
=self
) as db
:
3715 for record
in self
.__db
:
3716 record
.visit(visitor
=visitor
)
3719 return repr(self
.__db
)
3722 yield from self
.__db
3724 @_functools.lru_cache(maxsize
=None)
3725 def __contains__(self
, key
):
3726 return self
.__getitem
__(key
) is not None
3728 @_functools.lru_cache(maxsize
=None)
3729 def __getitem__(self
, key
):
3730 if isinstance(key
, SVP64Instruction
):
3733 if isinstance(key
, Instruction
):
3736 sections
= sorted(self
.__opcodes
)
3737 for section
in sections
:
3738 group
= self
.__opcodes
[section
]
3739 for record
in group
[PO
]:
3740 if record
.match(key
=key
):
3745 elif isinstance(key
, str):
3746 return self
.__names
.get(key
)
3748 raise ValueError("instruction or name expected")