1 import collections
as _collections
2 import contextlib
as _contextlib
4 import dataclasses
as _dataclasses
6 import functools
as _functools
7 import inspect
as _inspect
9 import operator
as _operator
10 import pathlib
as _pathlib
12 import types
as _types
13 import typing
as _typing
15 import mdis
.dispatcher
19 from functools
import cached_property
21 from cached_property
import cached_property
23 from openpower
.decoder
.power_enums
import (
24 Function
as _Function
,
31 CRIn2Sel
as _CRIn2Sel
,
32 CROutSel
as _CROutSel
,
34 LDSTMode
as _LDSTMode
,
39 SVMaskSrc
as _SVMaskSrc
,
46 SVP64SubVL
as _SVP64SubVL
,
47 SVP64Pred
as _SVP64Pred
,
48 SVP64PredMode
as _SVP64PredMode
,
49 SVP64Width
as _SVP64Width
,
51 from openpower
.decoder
.selectable_int
import (
52 SelectableInt
as _SelectableInt
,
53 selectconcat
as _selectconcat
,
55 from openpower
.decoder
.power_fields
import (
58 DecodeFields
as _DecodeFields
,
60 from openpower
.decoder
.pseudo
.pagereader
import ISA
as _ISA
63 class DataclassMeta(type):
64 def __new__(metacls
, name
, bases
, ns
):
65 cls
= super().__new
__(metacls
, name
, bases
, ns
)
66 return _dataclasses
.dataclass(cls
, eq
=True, frozen
=True)
69 class Dataclass(metaclass
=DataclassMeta
):
73 @_functools.total_ordering
74 class Style(_enum
.Enum
):
78 VERBOSE
= _enum
.auto()
80 def __lt__(self
, other
):
81 if not isinstance(other
, self
.__class
__):
83 return (self
.value
< other
.value
)
86 @_functools.total_ordering
87 class Priority(_enum
.Enum
):
93 def _missing_(cls
, value
):
94 if isinstance(value
, str):
99 return super()._missing
_(value
)
101 def __lt__(self
, other
):
102 if not isinstance(other
, self
.__class
__):
103 return NotImplemented
105 # NOTE: the order is inversed, LOW < NORMAL < HIGH
106 return (self
.value
> other
.value
)
109 def dataclass(cls
, record
, keymap
=None, typemap
=None):
113 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
115 def transform(key_value
):
116 (key
, value
) = key_value
117 key
= keymap
.get(key
, key
)
118 hook
= typemap
.get(key
, lambda value
: value
)
119 if hook
is bool and value
in ("", "0"):
125 record
= dict(map(transform
, record
.items()))
126 for key
in frozenset(record
.keys()):
127 if record
[key
] == "":
133 @_functools.total_ordering
134 class Opcode(Dataclass
):
136 def __new__(cls
, value
):
137 if isinstance(value
, str):
138 value
= int(value
, 0)
139 if not isinstance(value
, int):
140 raise ValueError(value
)
142 if value
.bit_length() > 64:
143 raise ValueError(value
)
145 return super().__new
__(cls
, value
)
148 return self
.__repr
__()
151 return f
"{self:0{self.bit_length()}b}"
153 def bit_length(self
):
154 if super().bit_length() > 32:
158 class Value(Integer
):
167 def __lt__(self
, other
):
168 if not isinstance(other
, Opcode
):
169 return NotImplemented
170 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
173 return (self
.value
& self
.mask
)
176 return int(self
).__index
__()
179 def pattern(value
, mask
, bit_length
):
180 for bit
in range(bit_length
):
181 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
183 elif (value
& (1 << (bit_length
- bit
- 1))):
188 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
190 def match(self
, key
):
191 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
194 @_functools.total_ordering
195 class IntegerOpcode(Opcode
):
196 def __init__(self
, value
):
197 if value
.startswith("0b"):
198 mask
= int(("1" * len(value
[2:])), 2)
202 value
= Opcode
.Value(value
)
203 mask
= Opcode
.Mask(mask
)
205 return super().__init
__(value
=value
, mask
=mask
)
208 @_functools.total_ordering
209 class PatternOpcode(Opcode
):
210 def __init__(self
, pattern
):
211 if not isinstance(pattern
, str):
212 raise ValueError(pattern
)
214 (value
, mask
) = (0, 0)
215 for symbol
in pattern
:
216 if symbol
not in {"0", "1", "-"}:
217 raise ValueError(pattern
)
218 value |
= (symbol
== "1")
219 mask |
= (symbol
!= "-")
225 value
= Opcode
.Value(value
)
226 mask
= Opcode
.Mask(mask
)
228 return super().__init
__(value
=value
, mask
=mask
)
231 class PPCRecord(Dataclass
):
232 class FlagsMeta(type):
247 class Flags(tuple, metaclass
=FlagsMeta
):
248 def __new__(cls
, flags
=frozenset()):
249 flags
= frozenset(flags
)
250 diff
= (flags
- frozenset(cls
))
252 raise ValueError(flags
)
253 return super().__new
__(cls
, sorted(flags
))
257 flags
: Flags
= Flags()
259 function
: _Function
= _Function
.NONE
260 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
261 in1
: _In1Sel
= _In1Sel
.NONE
262 in2
: _In2Sel
= _In2Sel
.NONE
263 in3
: _In3Sel
= _In3Sel
.NONE
264 out
: _OutSel
= _OutSel
.NONE
265 cr_in
: _CRInSel
= _CRInSel
.NONE
266 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
267 cr_out
: _CROutSel
= _CROutSel
.NONE
268 cry_in
: _CryIn
= _CryIn
.ZERO
269 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
270 upd
: _LDSTMode
= _LDSTMode
.NONE
271 Rc
: _RCOE
= _RCOE
.NONE
272 form
: _Form
= _Form
.NONE
274 unofficial
: bool = False
278 "internal op": "intop",
282 "ldst len": "ldst_len",
284 "CONDITIONS": "conditions",
287 def __lt__(self
, other
):
288 if not isinstance(other
, self
.__class
__):
289 return NotImplemented
290 lhs
= (self
.opcode
, self
.comment
)
291 rhs
= (other
.opcode
, other
.comment
)
295 def CSV(cls
, record
, opcode_cls
):
296 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
297 typemap
["opcode"] = opcode_cls
299 if record
["CR in"] == "BA_BB":
300 record
["cr_in"] = "BA"
301 record
["cr_in2"] = "BB"
305 for flag
in frozenset(PPCRecord
.Flags
):
306 if bool(record
.pop(flag
, "")):
308 record
["flags"] = PPCRecord
.Flags(flags
)
310 return dataclass(cls
, record
,
311 keymap
=PPCRecord
.__KEYMAP
,
316 return frozenset(self
.comment
.split("=")[-1].split("/"))
319 class PPCMultiRecord(tuple):
320 def __getattr__(self
, attr
):
323 raise AttributeError(attr
)
324 return getattr(self
[0], attr
)
327 class SVP64Record(Dataclass
):
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 class Section(Dataclass
):
551 class Path(type(_pathlib
.Path("."))):
554 class Mode(_enum
.Enum
):
555 INTEGER
= _enum
.auto()
556 PATTERN
= _enum
.auto()
559 def _missing_(cls
, value
):
560 if isinstance(value
, str):
561 return cls
[value
.upper()]
562 return super()._missing
_(value
)
565 def __new__(cls
, value
=None):
566 if isinstance(value
, str):
567 if value
.upper() == "NONE":
570 value
= int(value
, 0)
574 return super().__new
__(cls
, value
)
580 return (bin(self
) if self
else "None")
586 opcode
: IntegerOpcode
= None
587 priority
: Priority
= Priority
.NORMAL
589 def __lt__(self
, other
):
590 if not isinstance(other
, self
.__class
__):
591 return NotImplemented
592 return (self
.priority
< other
.priority
)
595 def CSV(cls
, record
):
596 keymap
= {"path": "csv"}
597 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
598 if record
["opcode"] == "NONE":
599 typemap
["opcode"] = lambda _
: None
601 return dataclass(cls
, record
, typemap
=typemap
, keymap
=keymap
)
605 def __init__(self
, items
):
606 if isinstance(items
, dict):
607 items
= items
.items()
610 (name
, bitrange
) = item
611 return (name
, tuple(bitrange
.values()))
613 mapping
= dict(map(transform
, items
))
615 return super().__init
__(mapping
)
618 return hash(tuple(sorted(self
.items())))
621 yield from self
.__mapping
.items()
624 class Operands(dict):
636 def __init__(self
, insn
, operands
):
638 "b": {"target_addr": TargetAddrOperandLI
},
639 "ba": {"target_addr": TargetAddrOperandLI
},
640 "bl": {"target_addr": TargetAddrOperandLI
},
641 "bla": {"target_addr": TargetAddrOperandLI
},
642 "bc": {"target_addr": TargetAddrOperandBD
},
643 "bca": {"target_addr": TargetAddrOperandBD
},
644 "bcl": {"target_addr": TargetAddrOperandBD
},
645 "bcla": {"target_addr": TargetAddrOperandBD
},
646 "addpcis": {"D": DOperandDX
},
647 "fishmv": {"D": DOperandDX
},
648 "fmvis": {"D": DOperandDX
},
651 "SVi": NonZeroOperand
,
652 "SVd": NonZeroOperand
,
653 "SVxd": NonZeroOperand
,
654 "SVyd": NonZeroOperand
,
655 "SVzd": NonZeroOperand
,
657 "D": SignedImmediateOperand
,
661 "SIM": SignedOperand
,
662 "SVD": SignedOperand
,
663 "SVDS": SignedOperand
,
664 "RSp": GPRPairOperand
,
665 "RTp": GPRPairOperand
,
666 "FRAp": FPRPairOperand
,
667 "FRBp": FPRPairOperand
,
668 "FRSp": FPRPairOperand
,
669 "FRTp": FPRPairOperand
,
671 custom_immediates
= {
677 for operand
in operands
:
681 (name
, value
) = operand
.split("=")
682 mapping
[name
] = (StaticOperand
, (
684 ("value", int(value
)),
688 if name
.endswith(")"):
689 name
= name
.replace("(", " ").replace(")", "")
690 (imm_name
, _
, name
) = name
.partition(" ")
694 if imm_name
is not None:
695 imm_cls
= custom_immediates
.get(imm_name
, ImmediateOperand
)
697 if insn
in custom_insns
and name
in custom_insns
[insn
]:
698 cls
= custom_insns
[insn
][name
]
699 elif name
in custom_fields
:
700 cls
= custom_fields
[name
]
701 elif name
in _Reg
.__members
__:
703 if reg
in self
.__class
__.__GPR
_PAIRS
:
705 elif reg
in self
.__class
__.__FPR
_PAIRS
:
708 regtype
= _RegType
[name
]
709 if regtype
is _RegType
.GPR
:
711 elif regtype
is _RegType
.FPR
:
713 elif regtype
is _RegType
.CR_3BIT
:
715 elif regtype
is _RegType
.CR_5BIT
:
718 if imm_name
is not None:
719 mapping
[imm_name
] = (imm_cls
, (
722 mapping
[name
] = (cls
, (
726 return super().__init
__(mapping
)
729 for (cls
, kwargs
) in self
.values():
730 yield (cls
, dict(kwargs
))
733 return hash(tuple(sorted(self
.items())))
737 return tuple(filter(lambda pair
: issubclass(pair
[0], StaticOperand
), self
))
741 return tuple(filter(lambda pair
: issubclass(pair
[0], DynamicOperand
), self
))
744 class Arguments(tuple):
745 def __new__(cls
, record
, arguments
, operands
):
746 operands
= iter(tuple(operands
))
747 arguments
= iter(tuple(arguments
))
752 operand
= next(operands
)
753 except StopIteration:
757 argument
= next(arguments
)
758 except StopIteration:
759 raise ValueError("operands count mismatch")
761 if isinstance(operand
, ImmediateOperand
):
762 argument
= argument
.replace("(", " ").replace(")", "")
763 (imm_argument
, _
, argument
) = argument
.partition(" ")
765 (imm_operand
, operand
) = (operand
, next(operands
))
766 except StopIteration:
767 raise ValueError("operands count mismatch")
768 items
.append((imm_argument
, imm_operand
))
769 items
.append((argument
, operand
))
773 except StopIteration:
776 raise ValueError("operands count mismatch")
778 return super().__new
__(cls
, items
)
785 class MarkdownRecord(Dataclass
):
790 @_functools.total_ordering
791 class Record(Dataclass
):
797 svp64
: SVP64Record
= None
801 if self
.svp64
is not None:
802 return self
.svp64
.extras
804 return _types
.MappingProxyType({})
808 return self
.mdwn
.pcode
810 def __lt__(self
, other
):
811 if not isinstance(other
, Record
):
812 return NotImplemented
813 lhs
= (min(self
.opcodes
), self
.name
)
814 rhs
= (min(other
.opcodes
), other
.name
)
819 return (self
.static_operands
+ self
.dynamic_operands
)
822 def static_operands(self
):
824 operands
.append(POStaticOperand(record
=self
, value
=self
.PO
))
826 operands
.append(XOStaticOperand(
828 value
=ppc
.opcode
.value
,
829 span
=self
.section
.bitsel
,
831 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
832 operands
.append(cls(record
=self
, **kwargs
))
833 return tuple(operands
)
836 def dynamic_operands(self
):
838 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
839 operands
.append(cls(record
=self
, **kwargs
))
840 return tuple(operands
)
845 return int("".join(str(int(mapping
[bit
])) \
846 for bit
in sorted(mapping
)), 2)
848 def PO_XO(value
, mask
, opcode
, bits
):
851 for (src
, dst
) in enumerate(reversed(bits
)):
852 value
[dst
] = ((opcode
.value
& (1 << src
)) != 0)
853 mask
[dst
] = ((opcode
.mask
& (1 << src
)) != 0)
856 def PO(value
, mask
, opcode
, bits
):
857 return PO_XO(value
=value
, mask
=mask
, opcode
=opcode
, bits
=bits
)
859 def XO(value
, mask
, opcode
, bits
):
860 (value
, mask
) = PO_XO(value
=value
, mask
=mask
,
861 opcode
=opcode
, bits
=bits
)
862 for (op_cls
, op_kwargs
) in self
.mdwn
.operands
.static
:
863 operand
= op_cls(record
=self
, **op_kwargs
)
864 for (src
, dst
) in enumerate(reversed(operand
.span
)):
865 value
[dst
] = ((operand
.value
& (1 << src
)) != 0)
870 value
= {bit
:False for bit
in range(32)}
871 mask
= {bit
:False for bit
in range(32)}
872 if self
.section
.opcode
is not None:
873 (value
, mask
) = PO(value
=value
, mask
=mask
,
874 opcode
=self
.section
.opcode
, bits
=range(0, 6))
876 pairs
.append(XO(value
=value
, mask
=mask
,
877 opcode
=ppc
.opcode
, bits
=self
.section
.bitsel
))
880 for (value
, mask
) in pairs
:
881 value
= Opcode
.Value(binary(value
))
882 mask
= Opcode
.Mask(binary(mask
))
883 result
.append(Opcode(value
=value
, mask
=mask
))
889 opcode
= self
.section
.opcode
891 opcode
= self
.ppc
[0].opcode
892 if isinstance(opcode
, PatternOpcode
):
893 value
= int(opcode
.value
)
894 bits
= opcode
.value
.bit_length()
895 return int(_SelectableInt(value
=value
, bits
=bits
)[0:6])
897 return int(opcode
.value
)
901 return tuple(ppc
.opcode
for ppc
in self
.ppc
)
903 def match(self
, key
):
904 for opcode
in self
.opcodes
:
905 if opcode
.match(key
):
912 return self
.svp64
.mode
932 if self
.svp64
is None:
938 return self
.ppc
.cr_in
942 return self
.ppc
.cr_in2
946 return self
.ppc
.cr_out
948 ptype
= property(lambda self
: self
.svp64
.ptype
)
949 etype
= property(lambda self
: self
.svp64
.etype
)
951 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
952 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
953 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
954 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
955 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
956 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
957 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
958 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
960 def __contains__(self
, key
):
961 return self
.mdwn
.operands
.__contains
__(key
)
963 def __getitem__(self
, key
):
964 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
965 return cls(record
=self
, **dict(kwargs
))
971 return self
["Rc"].value
975 def __init__(self
, record
, name
):
976 self
.__record
= record
980 yield ("record", self
.record
)
981 yield ("name", self
.__name
)
984 return f
"{self.__class__.__name__}({self.name})"
996 return self
.record
.fields
[self
.name
]
998 def assemble(self
, insn
):
999 raise NotImplementedError()
1001 def disassemble(self
, insn
,
1002 style
=Style
.NORMAL
, indent
=""):
1003 raise NotImplementedError()
1006 class DynamicOperand(Operand
):
1007 def assemble(self
, insn
, value
):
1009 if isinstance(value
, str):
1010 value
= int(value
, 0)
1012 raise ValueError("signed operands not allowed")
1015 def disassemble(self
, insn
,
1016 style
=Style
.NORMAL
, indent
=""):
1020 if style
>= Style
.VERBOSE
:
1021 span
= map(str, span
)
1022 yield f
"{indent}{self.name}"
1023 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1024 yield f
"{indent}{indent}{', '.join(span)}"
1026 yield str(int(value
))
1029 class SignedOperand(DynamicOperand
):
1030 def assemble(self
, insn
, value
):
1031 if isinstance(value
, str):
1032 value
= int(value
, 0)
1033 return super().assemble(value
=value
, insn
=insn
)
1035 def assemble(self
, insn
, value
):
1037 if isinstance(value
, str):
1038 value
= int(value
, 0)
1041 def disassemble(self
, insn
,
1042 style
=Style
.NORMAL
, indent
=""):
1044 value
= insn
[span
].to_signed_int()
1045 sign
= "-" if (value
< 0) else ""
1048 if style
>= Style
.VERBOSE
:
1049 span
= map(str, span
)
1050 yield f
"{indent}{self.name}"
1051 yield f
"{indent}{indent}{sign}{value}"
1052 yield f
"{indent}{indent}{', '.join(span)}"
1054 yield f
"{sign}{value}"
1057 class StaticOperand(Operand
):
1058 def __init__(self
, record
, name
, value
):
1059 self
.__value
= value
1060 return super().__init
__(record
=record
, name
=name
)
1063 yield ("value", self
.__value
)
1064 yield from super().__iter
__()
1067 return f
"{self.__class__.__name__}({self.name}, value={self.value})"
1073 def assemble(self
, insn
):
1074 insn
[self
.span
] = self
.value
1076 def disassemble(self
, insn
,
1077 style
=Style
.NORMAL
, indent
=""):
1081 if style
>= Style
.VERBOSE
:
1082 span
= map(str, span
)
1083 yield f
"{indent}{self.name}"
1084 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1085 yield f
"{indent}{indent}{', '.join(span)}"
1087 yield str(int(value
))
1090 class SpanStaticOperand(StaticOperand
):
1091 def __init__(self
, record
, name
, value
, span
):
1092 self
.__span
= tuple(span
)
1093 return super().__init
__(record
=record
, name
=name
, value
=value
)
1096 yield ("span", self
.__span
)
1097 yield from super().__iter
__()
1104 class POStaticOperand(SpanStaticOperand
):
1105 def __init__(self
, record
, value
):
1106 return super().__init
__(record
=record
, name
="PO",
1107 value
=value
, span
=range(0, 6))
1110 for (key
, value
) in super().__iter
__():
1111 if key
not in {"name", "span"}:
1115 class XOStaticOperand(SpanStaticOperand
):
1116 def __init__(self
, record
, value
, span
):
1117 bits
= record
.section
.bitsel
1118 value
= _SelectableInt(value
=value
, bits
=len(bits
))
1119 span
= dict(zip(bits
, range(len(bits
))))
1120 span_rev
= {value
:key
for (key
, value
) in span
.items()}
1122 # This part is tricky: we cannot use record.operands,
1123 # as this code is called by record.static_operands method.
1124 for (cls
, kwargs
) in record
.mdwn
.operands
:
1125 operand
= cls(record
=record
, **kwargs
)
1126 for idx
in operand
.span
:
1127 rev
= span
.pop(idx
, None)
1129 span_rev
.pop(rev
, None)
1131 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1132 span
= tuple(span
.keys())
1134 return super().__init
__(record
=record
, name
="XO",
1135 value
=value
, span
=span
)
1138 for (key
, value
) in super().__iter
__():
1139 if key
not in {"name"}:
1143 class ImmediateOperand(DynamicOperand
):
1147 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1151 class NonZeroOperand(DynamicOperand
):
1152 def assemble(self
, insn
, value
):
1153 if isinstance(value
, str):
1154 value
= int(value
, 0)
1155 if not isinstance(value
, int):
1156 raise ValueError("non-integer operand")
1158 raise ValueError("non-zero operand")
1160 return super().assemble(value
=value
, insn
=insn
)
1162 def disassemble(self
, insn
,
1163 style
=Style
.NORMAL
, indent
=""):
1167 if style
>= Style
.VERBOSE
:
1168 span
= map(str, span
)
1169 yield f
"{indent}{self.name}"
1170 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1171 yield f
"{indent}{indent}{', '.join(span)}"
1173 yield str(int(value
) + 1)
1176 class ExtendableOperand(DynamicOperand
):
1177 def sv_spec_enter(self
, value
, span
):
1178 return (value
, span
)
1180 def sv_spec(self
, insn
):
1184 span
= tuple(map(str, span
))
1186 if isinstance(insn
, SVP64Instruction
):
1187 (origin_value
, origin_span
) = (value
, span
)
1188 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1190 for extra_idx
in self
.extra_idx
:
1191 if self
.record
.etype
is _SVEType
.EXTRA3
:
1192 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1193 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1194 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1196 raise ValueError(self
.record
.etype
)
1199 vector
= bool(spec
[0])
1200 spec_span
= spec
.__class
__
1201 if self
.record
.etype
is _SVEType
.EXTRA3
:
1202 spec_span
= tuple(map(str, spec_span
[1, 2]))
1204 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1205 spec_span
= tuple(map(str, spec_span
[1,]))
1206 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1209 spec_span
= (spec_span
+ ("{0}",))
1211 spec_span
= (("{0}",) + spec_span
)
1213 raise ValueError(self
.record
.etype
)
1215 vector_shift
= (2 + (5 - value
.bits
))
1216 scalar_shift
= value
.bits
1217 spec_shift
= (5 - value
.bits
)
1219 bits
= (len(span
) + len(spec_span
))
1220 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1221 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1223 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1224 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1226 value
= ((spec
<< scalar_shift
) | value
)
1227 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1229 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1230 origin_value
=origin_value
, origin_span
=origin_span
)
1232 return (vector
, value
, span
)
1234 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1235 return (value
, span
)
1238 def extra_idx(self
):
1239 for (key
, record
) in self
.record
.svp64
.extras
.items():
1240 if record
["reg"].alias
is self
.extra_reg
.alias
:
1244 def extra_reg(self
):
1245 return _Reg(self
.name
)
1247 def remap(self
, value
, vector
):
1248 raise NotImplementedError()
1250 def assemble(self
, value
, insn
, prefix
):
1253 if isinstance(value
, str):
1254 value
= value
.lower()
1255 if value
.startswith("%"):
1257 if value
.startswith("*"):
1258 if not isinstance(insn
, SVP64Instruction
):
1259 raise ValueError(value
)
1262 if value
.startswith(prefix
):
1263 if (self
.extra_reg
.or_zero
and (value
== f
"{prefix}0")):
1264 raise ValueError(value
)
1265 value
= value
[len(prefix
):]
1266 value
= int(value
, 0)
1268 if isinstance(insn
, SVP64Instruction
):
1269 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1271 for extra_idx
in self
.extra_idx
:
1272 if self
.record
.etype
is _SVEType
.EXTRA3
:
1273 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1274 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1275 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1277 raise ValueError(self
.record
.etype
)
1279 return super().assemble(value
=value
, insn
=insn
)
1281 def disassemble(self
, insn
,
1282 style
=Style
.NORMAL
, prefix
="", indent
=""):
1283 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1285 if (self
.extra_reg
.or_zero
and (value
== 0)):
1288 if style
>= Style
.VERBOSE
:
1289 mode
= "vector" if vector
else "scalar"
1290 yield f
"{indent}{self.name} ({mode})"
1291 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1292 yield f
"{indent}{indent}{', '.join(span)}"
1293 if isinstance(insn
, SVP64Instruction
):
1294 for extra_idx
in frozenset(self
.extra_idx
):
1295 if self
.record
.etype
is _SVEType
.NONE
:
1296 yield f
"{indent}{indent}extra[none]"
1298 etype
= repr(self
.record
.etype
).lower()
1299 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1301 vector
= "*" if vector
else ""
1302 yield f
"{vector}{prefix}{int(value)}"
1305 class SimpleRegisterOperand(ExtendableOperand
):
1306 def remap(self
, value
, vector
):
1308 extra
= (value
& 0b11)
1309 value
= (value
>> 2)
1311 extra
= (value
>> 5)
1312 value
= (value
& 0b11111)
1314 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1315 # (and shrink to a single bit if ok)
1316 if self
.record
.etype
is _SVEType
.EXTRA2
:
1318 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1319 assert (extra
& 0b01) == 0, \
1320 ("vector field %s cannot fit into EXTRA2" % value
)
1321 extra
= (0b10 |
(extra
>> 1))
1323 # range is r0-r63 in increments of 1
1324 assert (extra
>> 1) == 0, \
1325 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1327 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1329 # EXTRA3 vector bit needs marking
1332 raise ValueError(self
.record
.etype
)
1334 return (value
, extra
)
1337 class GPROperand(SimpleRegisterOperand
):
1338 def assemble(self
, insn
, value
):
1339 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1341 def disassemble(self
, insn
,
1342 style
=Style
.NORMAL
, indent
=""):
1343 prefix
= "" if (style
<= Style
.SHORT
) else "r"
1344 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1345 style
=style
, indent
=indent
)
1348 class GPRPairOperand(GPROperand
):
1352 class FPROperand(SimpleRegisterOperand
):
1353 def assemble(self
, insn
, value
):
1354 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1356 def disassemble(self
, insn
,
1357 style
=Style
.NORMAL
, indent
=""):
1358 prefix
= "" if (style
<= Style
.SHORT
) else "f"
1359 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1360 style
=style
, indent
=indent
)
1363 class FPRPairOperand(FPROperand
):
1367 class ConditionRegisterFieldOperand(ExtendableOperand
):
1368 def pattern(name_pattern
):
1369 (name
, pattern
) = name_pattern
1370 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1379 CR
= r
"(?:CR|cr)([0-9]+)"
1381 BIT
= rf
"({'|'.join(CONDS.keys())})"
1382 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1383 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1384 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1385 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1386 XCR
= fr
"{CR}\.{BIT}"
1387 PATTERNS
= tuple(map(pattern
, (
1392 ("BIT+CR", (LBIT
+ CR
)),
1393 ("CR+BIT", (CR
+ RBIT
)),
1394 ("BIT+CR*N", (LBIT
+ CRN
)),
1395 ("CR*N+BIT", (CRN
+ RBIT
)),
1396 ("BIT+N*CR", (LBIT
+ NCR
)),
1397 ("N*CR+BIT", (NCR
+ RBIT
)),
1400 def remap(self
, value
, vector
, regtype
):
1401 if regtype
is _RegType
.CR_5BIT
:
1402 subvalue
= (value
& 0b11)
1406 extra
= (value
& 0b1111)
1409 extra
= (value
>> 3)
1412 if self
.record
.etype
is _SVEType
.EXTRA2
:
1414 assert (extra
& 0b111) == 0, \
1415 "vector CR cannot fit into EXTRA2"
1416 extra
= (0b10 |
(extra
>> 3))
1418 assert (extra
>> 1) == 0, \
1419 "scalar CR cannot fit into EXTRA2"
1421 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1423 assert (extra
& 0b11) == 0, \
1424 "vector CR cannot fit into EXTRA3"
1425 extra
= (0b100 |
(extra
>> 2))
1427 assert (extra
>> 2) == 0, \
1428 "scalar CR cannot fit into EXTRA3"
1431 if regtype
is _RegType
.CR_5BIT
:
1432 value
= ((value
<< 2) | subvalue
)
1434 return (value
, extra
)
1436 def assemble(self
, insn
, value
):
1437 if isinstance(value
, str):
1440 if value
.startswith("*"):
1441 if not isinstance(insn
, SVP64Instruction
):
1442 raise ValueError(value
)
1446 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1447 match
= pattern
.match(value
)
1448 if match
is not None:
1449 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1450 values
= match
.groups()
1451 match
= dict(zip(keys
, values
))
1452 CR
= int(match
["CR"])
1456 N
= int(match
.get("N", "1"))
1457 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1458 value
= ((CR
* N
) + BIT
)
1465 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1467 def disassemble(self
, insn
,
1468 style
=Style
.NORMAL
, prefix
="", indent
=""):
1469 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1471 if style
>= Style
.VERBOSE
:
1472 mode
= "vector" if vector
else "scalar"
1473 yield f
"{indent}{self.name} ({mode})"
1474 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1475 yield f
"{indent}{indent}{', '.join(span)}"
1476 if isinstance(insn
, SVP64Instruction
):
1477 for extra_idx
in frozenset(self
.extra_idx
):
1478 if self
.record
.etype
is _SVEType
.NONE
:
1479 yield f
"{indent}{indent}extra[none]"
1481 etype
= repr(self
.record
.etype
).lower()
1482 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1484 vector
= "*" if vector
else ""
1485 CR
= int(value
>> 2)
1487 cond
= ("lt", "gt", "eq", "so")[CC
]
1488 if style
>= Style
.NORMAL
:
1490 if isinstance(insn
, SVP64Instruction
):
1491 yield f
"{vector}cr{CR}.{cond}"
1493 yield f
"4*cr{CR}+{cond}"
1497 yield f
"{vector}{prefix}{int(value)}"
1500 class CR3Operand(ConditionRegisterFieldOperand
):
1501 def remap(self
, value
, vector
):
1502 return super().remap(value
=value
, vector
=vector
,
1503 regtype
=_RegType
.CR_3BIT
)
1506 class CR5Operand(ConditionRegisterFieldOperand
):
1507 def remap(self
, value
, vector
):
1508 return super().remap(value
=value
, vector
=vector
,
1509 regtype
=_RegType
.CR_5BIT
)
1511 def sv_spec_enter(self
, value
, span
):
1512 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1513 return (value
, span
)
1515 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1516 value
= _selectconcat(value
, origin_value
[3:5])
1518 return (value
, span
)
1521 class EXTSOperand(SignedOperand
):
1522 field
: str # real name to report
1523 nz
: int = 0 # number of zeros
1524 fmt
: str = "d" # integer formatter
1526 def __init__(self
, record
, name
, field
, nz
=0, fmt
="d"):
1527 self
.__field
= field
1530 return super().__init
__(record
=record
, name
=name
)
1546 return self
.record
.fields
[self
.field
]
1548 def assemble(self
, insn
, value
):
1550 if isinstance(value
, str):
1551 value
= int(value
, 0)
1552 insn
[span
] = (value
>> self
.nz
)
1554 def disassemble(self
, insn
,
1555 style
=Style
.NORMAL
, indent
=""):
1557 value
= insn
[span
].to_signed_int()
1558 sign
= "-" if (value
< 0) else ""
1559 value
= (abs(value
) << self
.nz
)
1561 if style
>= Style
.VERBOSE
:
1562 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1563 zeros
= ("0" * self
.nz
)
1564 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1565 yield f
"{indent * 1}{hint}"
1566 yield f
"{indent * 2}{self.field}"
1567 yield f
"{indent * 3}{sign}{value:{self.fmt}}"
1568 yield f
"{indent * 3}{', '.join(span)}"
1570 yield f
"{sign}{value:{self.fmt}}"
1573 class TargetAddrOperand(EXTSOperand
):
1574 def __init__(self
, record
, name
, field
):
1575 return super().__init
__(record
=record
, name
=name
, field
=field
,
1579 class TargetAddrOperandLI(TargetAddrOperand
):
1580 def __init__(self
, record
, name
):
1581 return super().__init
__(record
=record
, name
=name
, field
="LI")
1584 class TargetAddrOperandBD(TargetAddrOperand
):
1585 def __init__(self
, record
, name
):
1586 return super().__init
__(record
=record
, name
=name
, field
="BD")
1589 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1590 def __init__(self
, record
, name
):
1591 return super().__init
__(record
=record
, name
=name
, field
="DS", nz
=2)
1594 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1595 def __init__(self
, record
, name
):
1596 return super().__init
__(record
=record
, name
=name
, field
="DQ", nz
=4)
1599 class DOperandDX(SignedOperand
):
1602 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1603 operands
= map(cls
, ("d0", "d1", "d2"))
1604 spans
= map(lambda operand
: operand
.span
, operands
)
1605 return sum(spans
, tuple())
1607 def disassemble(self
, insn
,
1608 style
=Style
.NORMAL
, indent
=""):
1610 value
= insn
[span
].to_signed_int()
1611 sign
= "-" if (value
< 0) else ""
1614 if style
>= Style
.VERBOSE
:
1621 for (subname
, subspan
) in mapping
.items():
1622 operand
= DynamicOperand(name
=subname
)
1624 span
= map(str, span
)
1625 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1626 yield f
"{indent}{indent}{indent}{sign}{value}"
1627 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1629 yield f
"{sign}{value}"
1632 class Instruction(_Mapping
):
1634 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1635 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1636 raise ValueError(bits
)
1638 if isinstance(value
, bytes
):
1639 if ((len(value
) * 8) != bits
):
1640 raise ValueError(f
"bit length mismatch")
1641 value
= int.from_bytes(value
, byteorder
=byteorder
)
1643 if isinstance(value
, int):
1644 value
= _SelectableInt(value
=value
, bits
=bits
)
1645 elif isinstance(value
, Instruction
):
1646 value
= value
.storage
1648 if not isinstance(value
, _SelectableInt
):
1649 raise ValueError(value
)
1652 if len(value
) != bits
:
1653 raise ValueError(value
)
1655 value
= _SelectableInt(value
=value
, bits
=bits
)
1657 return cls(storage
=value
)
1660 return hash(int(self
))
1662 def __getitem__(self
, key
):
1663 return self
.storage
.__getitem
__(key
)
1665 def __setitem__(self
, key
, value
):
1666 return self
.storage
.__setitem
__(key
, value
)
1668 def bytes(self
, byteorder
="little"):
1669 nr_bytes
= (len(self
.__class
__) // 8)
1670 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1673 def record(cls
, db
, entry
):
1676 raise KeyError(entry
)
1680 def operands(cls
, record
):
1681 yield from record
.operands
1684 def static_operands(cls
, record
):
1685 return filter(lambda operand
: isinstance(operand
, StaticOperand
),
1686 cls
.operands(record
=record
))
1689 def dynamic_operands(cls
, record
):
1690 return filter(lambda operand
: isinstance(operand
, DynamicOperand
),
1691 cls
.operands(record
=record
))
1693 def spec(self
, record
, prefix
):
1694 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1695 self
.spec_dynamic_operands(record
=record
)))
1697 static_operands
= []
1698 for (name
, value
) in self
.spec_static_operands(record
=record
):
1699 static_operands
.append(f
"{name}={value}")
1702 if dynamic_operands
:
1704 operands
+= ",".join(dynamic_operands
)
1707 operands
+= " ".join(static_operands
)
1709 return f
"{prefix}{record.name}{operands}"
1711 def spec_static_operands(self
, record
):
1712 for operand
in self
.static_operands(record
=record
):
1713 if not isinstance(operand
, (POStaticOperand
, XOStaticOperand
)):
1714 yield (operand
.name
, operand
.value
)
1716 def spec_dynamic_operands(self
, record
, style
=Style
.NORMAL
):
1720 for operand
in self
.dynamic_operands(record
=record
):
1722 value
= " ".join(operand
.disassemble(insn
=self
,
1723 style
=min(style
, Style
.NORMAL
)))
1725 name
= f
"{imm_name}({name})"
1726 value
= f
"{imm_value}({value})"
1728 if isinstance(operand
, ImmediateOperand
):
1736 def assemble(cls
, record
, arguments
=None):
1737 if arguments
is None:
1740 insn
= cls
.integer(value
=0)
1742 for operand
in cls
.static_operands(record
=record
):
1743 operand
.assemble(insn
=insn
)
1745 arguments
= Arguments(record
=record
,
1746 arguments
=arguments
, operands
=cls
.dynamic_operands(record
=record
))
1747 for (value
, operand
) in arguments
:
1748 operand
.assemble(insn
=insn
, value
=value
)
1752 def disassemble(self
, record
,
1754 style
=Style
.NORMAL
):
1755 raise NotImplementedError()
1758 class WordInstruction(Instruction
):
1759 _
: _Field
= range(0, 32)
1760 PO
: _Field
= range(0, 6)
1763 def integer(cls
, value
, byteorder
="little"):
1764 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1769 for idx
in range(32):
1770 bit
= int(self
[idx
])
1772 return "".join(map(str, bits
))
1774 def disassemble(self
, record
,
1776 style
=Style
.NORMAL
):
1777 if style
<= Style
.SHORT
:
1780 blob
= self
.bytes(byteorder
=byteorder
)
1781 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1785 yield f
"{blob}.long 0x{int(self):08x}"
1788 # awful temporary hack: workaround for ld-update
1789 # https://bugs.libre-soc.org/show_bug.cgi?id=1056#c2
1790 # XXX TODO must check that *EXTENDED* RA != extended-RT
1791 if (record
.svp64
is not None and
1792 record
.mode
== _SVMode
.LDST_IMM
and
1793 'u' in record
.name
):
1794 yield f
"{blob}.long 0x{int(self):08x}"
1798 if style
is Style
.LEGACY
:
1800 for operand
in self
.dynamic_operands(record
=record
):
1801 if isinstance(operand
, (GPRPairOperand
, FPRPairOperand
)):
1804 if style
is Style
.LEGACY
and (paired
or record
.ppc
.unofficial
):
1805 yield f
"{blob}.long 0x{int(self):08x}"
1807 operands
= tuple(map(_operator
.itemgetter(1),
1808 self
.spec_dynamic_operands(record
=record
, style
=style
)))
1810 operands
= ",".join(operands
)
1811 yield f
"{blob}{record.name} {operands}"
1813 yield f
"{blob}{record.name}"
1815 if style
>= Style
.VERBOSE
:
1817 binary
= self
.binary
1818 spec
= self
.spec(record
=record
, prefix
="")
1819 yield f
"{indent}spec"
1820 yield f
"{indent}{indent}{spec}"
1821 yield f
"{indent}pcode"
1822 for stmt
in record
.mdwn
.pcode
:
1823 yield f
"{indent}{indent}{stmt}"
1824 yield f
"{indent}binary"
1825 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1826 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1827 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1828 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1829 yield f
"{indent}opcodes"
1830 for opcode
in record
.opcodes
:
1831 yield f
"{indent}{indent}{opcode!r}"
1832 for operand
in self
.operands(record
=record
):
1833 yield from operand
.disassemble(insn
=self
,
1834 style
=style
, indent
=indent
)
1838 class PrefixedInstruction(Instruction
):
1839 class Prefix(WordInstruction
.remap(range(0, 32))):
1842 class Suffix(WordInstruction
.remap(range(32, 64))):
1845 _
: _Field
= range(64)
1851 def integer(cls
, value
, byteorder
="little"):
1852 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
1855 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
1856 def transform(value
):
1857 return WordInstruction
.integer(value
=value
,
1858 byteorder
=byteorder
)[0:32]
1860 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
1861 value
= _selectconcat(prefix
, suffix
)
1863 return super().integer(bits
=64, value
=value
)
1866 class Mode(_Mapping
):
1867 _
: _Field
= range(0, 5)
1868 sel
: _Field
= (0, 1)
1871 class ExtraRM(_Mapping
):
1872 _
: _Field
= range(0, 9)
1875 class Extra2RM(ExtraRM
):
1876 idx0
: _Field
= range(0, 2)
1877 idx1
: _Field
= range(2, 4)
1878 idx2
: _Field
= range(4, 6)
1879 idx3
: _Field
= range(6, 8)
1881 def __getitem__(self
, key
):
1887 _SVExtra
.Idx0
: self
.idx0
,
1888 _SVExtra
.Idx1
: self
.idx1
,
1889 _SVExtra
.Idx2
: self
.idx2
,
1890 _SVExtra
.Idx3
: self
.idx3
,
1893 def __setitem__(self
, key
, value
):
1894 self
[key
].assign(value
)
1897 class Extra3RM(ExtraRM
):
1898 idx0
: _Field
= range(0, 3)
1899 idx1
: _Field
= range(3, 6)
1900 idx2
: _Field
= range(6, 9)
1902 def __getitem__(self
, key
):
1907 _SVExtra
.Idx0
: self
.idx0
,
1908 _SVExtra
.Idx1
: self
.idx1
,
1909 _SVExtra
.Idx2
: self
.idx2
,
1912 def __setitem__(self
, key
, value
):
1913 self
[key
].assign(value
)
1916 class BaseRM(_Mapping
):
1917 _
: _Field
= range(24)
1918 mmode
: _Field
= (0,)
1919 mask
: _Field
= range(1, 4)
1920 elwidth
: _Field
= range(4, 6)
1921 ewsrc
: _Field
= range(6, 8)
1922 subvl
: _Field
= range(8, 10)
1923 mode
: Mode
.remap(range(19, 24))
1924 smask_extra322
: _Field
= (6,7,18,) # LDST_IDX is EXTRA332
1925 smask
: _Field
= range(16, 19) # everything else use this
1926 extra
: ExtraRM
.remap(range(10, 19))
1927 extra2
: Extra2RM
.remap(range(10, 19))
1928 extra3
: Extra3RM
.remap(range(10, 19))
1929 # XXX extra332 = (extra3[0], extra3[1], extra2[3])
1931 def specifiers(self
, record
):
1932 subvl
= int(self
.subvl
)
1940 def disassemble(self
, style
=Style
.NORMAL
):
1941 if style
>= Style
.VERBOSE
:
1943 for (name
, span
) in self
.traverse(path
="RM"):
1944 value
= self
.storage
[span
]
1946 yield f
"{indent}{int(value):0{value.bits}b}"
1947 yield f
"{indent}{', '.join(map(str, span))}"
1950 class FFRc1BaseRM(BaseRM
):
1951 def specifiers(self
, record
, mode
):
1952 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
1953 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
1954 mask
= int(_selectconcat(CR
, inv
))
1955 predicate
= PredicateBaseRM
.predicate(True, mask
)
1956 yield f
"{mode}={predicate}"
1958 yield from super().specifiers(record
=record
)
1961 class FFRc0BaseRM(BaseRM
):
1962 def specifiers(self
, record
, mode
):
1964 inv
= "~" if self
.inv
else ""
1965 yield f
"{mode}={inv}RC1"
1967 yield from super().specifiers(record
=record
)
1970 class SatBaseRM(BaseRM
):
1971 def specifiers(self
, record
):
1977 yield from super().specifiers(record
=record
)
1980 class ZZBaseRM(BaseRM
):
1981 def specifiers(self
, record
):
1985 yield from super().specifiers(record
=record
)
1988 class ZZCombinedBaseRM(BaseRM
):
1989 def specifiers(self
, record
):
1990 if self
.sz
and self
.dz
:
1997 yield from super().specifiers(record
=record
)
2000 class DZBaseRM(BaseRM
):
2001 def specifiers(self
, record
):
2005 yield from super().specifiers(record
=record
)
2008 class SZBaseRM(BaseRM
):
2009 def specifiers(self
, record
):
2013 yield from super().specifiers(record
=record
)
2016 class MRBaseRM(BaseRM
):
2017 def specifiers(self
, record
):
2023 yield from super().specifiers(record
=record
)
2026 class ElsBaseRM(BaseRM
):
2027 def specifiers(self
, record
):
2031 yield from super().specifiers(record
=record
)
2034 class WidthBaseRM(BaseRM
):
2036 def width(FP
, width
):
2045 width
= ("fp" + width
)
2048 def specifiers(self
, record
):
2049 # elwidths: use "w=" if same otherwise dw/sw
2050 # FIXME this should consider FP instructions
2052 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
2053 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2054 if record
.svp64
.mode
is _SVMode
.CROP
:
2058 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2067 yield from super().specifiers(record
=record
)
2070 class PredicateBaseRM(BaseRM
):
2072 def predicate(CR
, mask
):
2075 (False, 0b001): "1<<r3",
2076 (False, 0b010): "r3",
2077 (False, 0b011): "~r3",
2078 (False, 0b100): "r10",
2079 (False, 0b101): "~r10",
2080 (False, 0b110): "r30",
2081 (False, 0b111): "~r30",
2083 (True, 0b000): "lt",
2084 (True, 0b001): "ge",
2085 (True, 0b010): "gt",
2086 (True, 0b011): "le",
2087 (True, 0b100): "eq",
2088 (True, 0b101): "ne",
2089 (True, 0b110): "so",
2090 (True, 0b111): "ns",
2093 def specifiers(self
, record
):
2094 # predication - single and twin
2095 # use "m=" if same otherwise sm/dm
2096 CR
= (int(self
.mmode
) == 1)
2097 mask
= int(self
.mask
)
2098 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
2099 if record
.svp64
.ptype
is _SVPType
.P2
:
2100 # LDST_IDX smask moving to extra322 but not straight away (False)
2101 if False and record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2102 smask
= int(self
.smask_extra332
)
2104 smask
= int(self
.smask
)
2105 sm
= PredicateBaseRM
.predicate(CR
, smask
)
2114 yield from super().specifiers(record
=record
)
2117 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
2121 class SEABaseRM(BaseRM
):
2122 def specifiers(self
, record
):
2126 yield from super().specifiers(record
=record
)
2129 class VLiBaseRM(BaseRM
):
2130 def specifiers(self
, record
):
2134 yield from super().specifiers(record
=record
)
2137 class NormalBaseRM(PredicateWidthBaseRM
):
2140 https://libre-soc.org/openpower/sv/normal/
2145 class NormalSimpleRM(ZZCombinedBaseRM
, NormalBaseRM
):
2146 """normal: simple mode"""
2150 def specifiers(self
, record
):
2151 yield from super().specifiers(record
=record
)
2154 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
2155 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
2159 class NormalFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, NormalBaseRM
):
2160 """normal: Rc=1: ffirst CR sel"""
2163 CR
: BaseRM
.mode
[3, 4]
2165 def specifiers(self
, record
):
2166 yield from super().specifiers(record
=record
, mode
="ff")
2169 class NormalFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
2170 """normal: Rc=0: ffirst z/nonz"""
2175 def specifiers(self
, record
):
2176 yield from super().specifiers(record
=record
, mode
="ff")
2179 class NormalSatRM(SatBaseRM
, ZZCombinedBaseRM
, NormalBaseRM
):
2180 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2186 class NormalRM(NormalBaseRM
):
2187 simple
: NormalSimpleRM
2189 ffrc1
: NormalFFRc1RM
2190 ffrc0
: NormalFFRc0RM
2194 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2196 LD/ST Immediate mode
2197 https://libre-soc.org/openpower/sv/ldst/
2202 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2203 """ld/st immediate: simple mode"""
2204 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2205 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2211 def specifiers(self
, record
):
2217 yield from super().specifiers(record
=record
)
2220 class LDSTFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2221 """ld/st immediate&indexed: Rc=1: ffirst CR sel"""
2224 CR
: BaseRM
.mode
[3, 4]
2226 def specifiers(self
, record
):
2227 yield from super().specifiers(record
=record
, mode
="ff")
2230 class LDSTFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2231 """ld/st immediate&indexed: Rc=0: ffirst z/nonz"""
2236 def specifiers(self
, record
):
2237 yield from super().specifiers(record
=record
, mode
="ff")
2240 class LDSTImmRM(LDSTImmBaseRM
):
2241 simple
: LDSTImmSimpleRM
2246 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2249 https://libre-soc.org/openpower/sv/ldst/
2254 class LDSTIdxSimpleRM(SEABaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2255 """ld/st index: simple mode (includes element-strided and Signed-EA)"""
2256 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2263 def specifiers(self
, record
):
2269 yield from super().specifiers(record
=record
)
2272 class LDSTIdxRM(LDSTIdxBaseRM
):
2273 simple
: LDSTIdxSimpleRM
2279 class CROpBaseRM(BaseRM
):
2282 https://libre-soc.org/openpower/sv/cr_ops/
2287 class CROpSimpleRM(PredicateBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2288 """crop: simple mode"""
2293 def specifiers(self
, record
):
2295 yield "rg" # simple CR Mode reports /rg
2297 yield from super().specifiers(record
=record
)
2300 class CROpMRRM(MRBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2301 """crop: scalar reduce mode (mapreduce)"""
2307 class CROpFF5RM(FFRc0BaseRM
, PredicateBaseRM
, VLiBaseRM
, DZBaseRM
,
2308 SZBaseRM
, CROpBaseRM
):
2309 """crop: ffirst 5-bit mode"""
2316 def specifiers(self
, record
):
2317 yield from super().specifiers(record
=record
, mode
="ff")
2320 # FIXME: almost everything in this class contradicts the specs (it doesn't)
2321 # The modes however are swapped: 5-bit is 3-bit, 3-bit is 5-bit
2322 class CROpFF3RM(FFRc1BaseRM
, PredicateBaseRM
, VLiBaseRM
, ZZBaseRM
, CROpBaseRM
):
2323 """cr_op: ffirst 3-bit mode"""
2329 def specifiers(self
, record
):
2330 yield from super().specifiers(record
=record
, mode
="ff")
2333 class CROpRM(CROpBaseRM
):
2334 simple
: CROpSimpleRM
2340 # ********************
2342 # https://libre-soc.org/openpower/sv/branches/
2343 class BranchBaseRM(BaseRM
):
2353 def specifiers(self
, record
):
2365 raise ValueError(self
.sz
)
2377 # Branch modes lack source mask.
2378 # Therefore a custom code is needed.
2379 CR
= (int(self
.mmode
) == 1)
2380 mask
= int(self
.mask
)
2381 m
= PredicateBaseRM
.predicate(CR
, mask
)
2385 yield from super().specifiers(record
=record
)
2388 class BranchSimpleRM(BranchBaseRM
):
2389 """branch: simple mode"""
2393 class BranchVLSRM(BranchBaseRM
):
2394 """branch: VLSET mode"""
2398 def specifiers(self
, record
):
2404 }[int(self
.VSb
), int(self
.VLi
)]
2406 yield from super().specifiers(record
=record
)
2409 class BranchCTRRM(BranchBaseRM
):
2410 """branch: CTR-test mode"""
2413 def specifiers(self
, record
):
2419 yield from super().specifiers(record
=record
)
2422 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2423 """branch: CTR-test+VLSET mode"""
2427 class BranchRM(BranchBaseRM
):
2428 simple
: BranchSimpleRM
2431 ctrvls
: BranchCTRVLSRM
2442 @_dataclasses.dataclass(eq
=True, frozen
=True)
2447 def match(cls
, desc
, record
):
2448 raise NotImplementedError()
2450 def validate(self
, others
):
2453 def assemble(self
, insn
):
2454 raise NotImplementedError()
2457 @_dataclasses.dataclass(eq
=True, frozen
=True)
2458 class SpecifierWidth(Specifier
):
2462 def match(cls
, desc
, record
, etalon
):
2463 (mode
, _
, value
) = desc
.partition("=")
2465 value
= value
.strip()
2468 width
= _SVP64Width(value
)
2470 return cls(record
=record
, width
=width
)
2473 @_dataclasses.dataclass(eq
=True, frozen
=True)
2474 class SpecifierW(SpecifierWidth
):
2476 def match(cls
, desc
, record
):
2477 return super().match(desc
=desc
, record
=record
, etalon
="w")
2479 def assemble(self
, insn
):
2480 selector
= insn
.select(record
=self
.record
)
2481 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2482 selector
.ewsrc
= self
.width
.value
2483 selector
.elwidth
= self
.width
.value
2486 @_dataclasses.dataclass(eq
=True, frozen
=True)
2487 class SpecifierSW(SpecifierWidth
):
2489 def match(cls
, desc
, record
):
2490 if record
.svp64
.mode
is _SVMode
.CROP
:
2492 return super().match(desc
=desc
, record
=record
, etalon
="sw")
2494 def assemble(self
, insn
):
2495 selector
= insn
.select(record
=self
.record
)
2496 selector
.ewsrc
= self
.width
.value
2499 @_dataclasses.dataclass(eq
=True, frozen
=True)
2500 class SpecifierDW(SpecifierWidth
):
2502 def match(cls
, desc
, record
):
2503 return super().match(desc
=desc
, record
=record
, etalon
="dw")
2505 def assemble(self
, insn
):
2506 selector
= insn
.select(record
=self
.record
)
2507 selector
.elwidth
= self
.width
.value
2510 @_dataclasses.dataclass(eq
=True, frozen
=True)
2511 class SpecifierSubVL(Specifier
):
2515 def match(cls
, desc
, record
):
2517 value
= _SVP64SubVL(desc
)
2521 return cls(record
=record
, value
=value
)
2523 def assemble(self
, insn
):
2524 selector
= insn
.select(record
=self
.record
)
2525 selector
.subvl
= int(self
.value
.value
)
2528 @_dataclasses.dataclass(eq
=True, frozen
=True)
2529 class SpecifierPredicate(Specifier
):
2534 def match(cls
, desc
, record
, mode_match
, pred_match
):
2535 (mode
, _
, pred
) = desc
.partition("=")
2538 if not mode_match(mode
):
2541 pred
= _SVP64Pred(pred
.strip())
2542 if not pred_match(pred
):
2543 raise ValueError(pred
)
2545 return cls(record
=record
, mode
=mode
, pred
=pred
)
2548 @_dataclasses.dataclass(eq
=True, frozen
=True)
2549 class SpecifierFF(SpecifierPredicate
):
2551 def match(cls
, desc
, record
):
2552 return super().match(desc
=desc
, record
=record
,
2553 mode_match
=lambda mode_arg
: mode_arg
== "ff",
2554 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2559 def assemble(self
, insn
):
2560 selector
= insn
.select(record
=self
.record
)
2561 if selector
.mode
.sel
!= 0:
2562 raise ValueError("cannot override mode")
2563 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2564 selector
.mode
.sel
= 0b01
2565 # HACK: please finally provide correct logic for CRs.
2566 if self
.pred
in (_SVP64Pred
.RC1
, _SVP64Pred
.RC1_N
):
2567 selector
.mode
[2] = (self
.pred
is _SVP64Pred
.RC1_N
)
2569 selector
.mode
[2] = self
.pred
.inv
2570 selector
.mode
[3, 4] = self
.pred
.state
2572 selector
.mode
.sel
= 0b01 if self
.mode
== "ff" else 0b11
2573 selector
.inv
= self
.pred
.inv
2575 selector
.CR
= self
.pred
.state
2577 selector
.RC1
= self
.pred
.state
2580 @_dataclasses.dataclass(eq
=True, frozen
=True)
2581 class SpecifierMask(SpecifierPredicate
):
2583 def match(cls
, desc
, record
, mode
):
2584 return super().match(desc
=desc
, record
=record
,
2585 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2586 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2591 def assemble(self
, insn
):
2592 raise NotImplementedError()
2595 @_dataclasses.dataclass(eq
=True, frozen
=True)
2596 class SpecifierM(SpecifierMask
):
2598 def match(cls
, desc
, record
):
2599 return super().match(desc
=desc
, record
=record
, mode
="m")
2601 def validate(self
, others
):
2603 if isinstance(spec
, SpecifierSM
):
2604 raise ValueError("source-mask and predicate mask conflict")
2605 elif isinstance(spec
, SpecifierDM
):
2606 raise ValueError("dest-mask and predicate mask conflict")
2608 def assemble(self
, insn
):
2609 selector
= insn
.select(record
=self
.record
)
2610 selector
.mask
= int(self
.pred
)
2611 if ((self
.record
.ptype
is _SVPType
.P2
) and
2612 (self
.record
.svp64
.mode
is not _SVMode
.BRANCH
)):
2613 selector
.smask
= int(self
.pred
)
2614 # LDST_IDX smask moving to extra322 but not straight away (False)
2615 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2616 selector
.smask_extra332
= int(self
.pred
)
2618 selector
.smask
= int(self
.pred
)
2620 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2623 @_dataclasses.dataclass(eq
=True, frozen
=True)
2624 class SpecifierSM(SpecifierMask
):
2626 def match(cls
, desc
, record
):
2627 return super().match(desc
=desc
, record
=record
, mode
="sm")
2629 def validate(self
, others
):
2630 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2631 raise ValueError("source-mask on non-twin predicate")
2633 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2636 if isinstance(spec
, SpecifierDM
):
2640 raise ValueError("missing dest-mask in CR twin predication")
2641 if self
.pred
.mode
!= twin
.pred
.mode
:
2642 raise ValueError(f
"predicate masks mismatch: "
2643 f
"{self.pred!r} vs {twin.pred!r}")
2645 def assemble(self
, insn
):
2646 selector
= insn
.select(record
=self
.record
)
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
)
2652 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2655 @_dataclasses.dataclass(eq
=True, frozen
=True)
2656 class SpecifierDM(SpecifierMask
):
2658 def match(cls
, desc
, record
):
2659 return super().match(desc
=desc
, record
=record
, mode
="dm")
2661 def validate(self
, others
):
2662 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2663 raise ValueError("dest-mask on non-twin predicate")
2665 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2668 if isinstance(spec
, SpecifierSM
):
2672 raise ValueError("missing source-mask in CR twin predication")
2673 if self
.pred
.mode
!= twin
.pred
.mode
:
2674 raise ValueError(f
"predicate masks mismatch: "
2675 f
"{self.pred!r} vs {twin.pred!r}")
2677 def assemble(self
, insn
):
2678 selector
= insn
.select(record
=self
.record
)
2679 selector
.mask
= int(self
.pred
)
2680 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2683 @_dataclasses.dataclass(eq
=True, frozen
=True)
2684 class SpecifierZZ(Specifier
):
2686 def match(cls
, desc
, record
):
2690 return cls(record
=record
)
2692 def validate(self
, others
):
2694 # Since zz takes precedence (overrides) sz and dz,
2695 # treat them as mutually exclusive.
2696 if isinstance(spec
, (SpecifierSZ
, SpecifierDZ
)):
2697 raise ValueError("mutually exclusive predicate masks")
2699 def assemble(self
, insn
):
2700 selector
= insn
.select(record
=self
.record
)
2701 if hasattr(selector
, "zz"): # this should be done in a different way
2708 @_dataclasses.dataclass(eq
=True, frozen
=True)
2709 class SpecifierXZ(Specifier
):
2711 hint
: str = _dataclasses
.field(repr=False)
2714 def match(cls
, desc
, record
, etalon
, hint
):
2718 return cls(desc
=desc
, record
=record
, hint
=hint
)
2720 def validate(self
, others
):
2721 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2722 raise ValueError(f
"{self.hint} on non-twin predicate")
2724 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2727 if isinstance(spec
, SpecifierXZ
):
2731 raise ValueError(f
"missing {self.hint} in CR twin predication")
2732 if self
.pred
!= twin
.pred
:
2733 raise ValueError(f
"predicate masks mismatch: "
2734 f
"{self.pred!r} vs {twin.pred!r}")
2736 def assemble(self
, insn
):
2737 selector
= insn
.select(record
=self
.record
)
2738 setattr(selector
, self
.desc
, 1)
2741 @_dataclasses.dataclass(eq
=True, frozen
=True)
2742 class SpecifierSZ(SpecifierXZ
):
2744 def match(cls
, desc
, record
):
2745 return super().match(desc
=desc
, record
=record
,
2746 etalon
="sz", hint
="source-mask")
2748 def validate(self
, others
):
2750 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2751 if isinstance(spec
, SpecifierFF
):
2752 raise ValueError("source-zero not allowed in ff mode")
2755 @_dataclasses.dataclass(eq
=True, frozen
=True)
2756 class SpecifierDZ(SpecifierXZ
):
2758 def match(cls
, desc
, record
):
2759 return super().match(desc
=desc
, record
=record
,
2760 etalon
="dz", hint
="dest-mask")
2762 def validate(self
, others
):
2764 if ((self
.record
.svp64
.mode
is not _SVMode
.CROP
) and
2765 isinstance(spec
, SpecifierFF
) and
2766 (spec
.pred
.mode
is _SVP64PredMode
.RC1
)):
2767 raise ValueError(f
"dest-zero not allowed in ff mode BO")
2770 @_dataclasses.dataclass(eq
=True, frozen
=True)
2771 class SpecifierEls(Specifier
):
2773 def match(cls
, desc
, record
):
2777 if record
.svp64
.mode
not in (_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
):
2778 raise ValueError("els is only valid in ld/st modes, not "
2779 "%s" % str(self
.record
.svp64
.mode
))
2781 return cls(record
=record
)
2783 def assemble(self
, insn
):
2784 if self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
: # stride mode
2785 insn
.prefix
.rm
.mode
[1] = 0
2787 selector
= insn
.select(record
=self
.record
)
2792 @_dataclasses.dataclass(eq
=True, frozen
=True)
2793 class SpecifierSEA(Specifier
):
2795 def match(cls
, desc
, record
):
2799 return cls(record
=record
)
2801 def validate(self
, others
):
2802 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
:
2803 raise ValueError("sea is only valid in ld/st modes, not "
2804 "%s" % str(self
.record
.svp64
.mode
))
2807 if isinstance(spec
, SpecifierFF
):
2808 raise ValueError(f
"sea cannot be used in ff mode")
2810 def assemble(self
, insn
):
2811 selector
= insn
.select(record
=self
.record
)
2812 if selector
.mode
.sel
not in (0b10, 0b00):
2813 raise ValueError("sea is only valid for normal and els modes, "
2814 "not %d" % int(selector
.mode
.sel
))
2818 @_dataclasses.dataclass(eq
=True, frozen
=True)
2819 class SpecifierSat(Specifier
):
2824 def match(cls
, desc
, record
, etalon
, sign
):
2828 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.LDST_IMM
,
2830 raise ValueError("only normal, ld/st imm and "
2831 "ld/st idx modes supported")
2833 return cls(record
=record
, desc
=desc
, sign
=sign
)
2835 def assemble(self
, insn
):
2836 selector
= insn
.select(record
=self
.record
)
2837 selector
.mode
[0] = 0b1
2838 selector
.mode
[1] = 0b0
2839 selector
.N
= int(self
.sign
)
2842 @_dataclasses.dataclass(eq
=True, frozen
=True)
2843 class SpecifierSatS(SpecifierSat
):
2845 def match(cls
, desc
, record
):
2846 return super().match(desc
=desc
, record
=record
,
2847 etalon
="sats", sign
=True)
2850 @_dataclasses.dataclass(eq
=True, frozen
=True)
2851 class SpecifierSatU(SpecifierSat
):
2853 def match(cls
, desc
, record
):
2854 return super().match(desc
=desc
, record
=record
,
2855 etalon
="satu", sign
=False)
2858 @_dataclasses.dataclass(eq
=True, frozen
=True)
2859 class SpecifierMapReduce(Specifier
):
2863 def match(cls
, record
, RG
):
2864 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2865 raise ValueError("only normal and crop modes supported")
2867 return cls(record
=record
, RG
=RG
)
2869 def assemble(self
, insn
):
2870 selector
= insn
.select(record
=self
.record
)
2871 if self
.record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2872 raise ValueError("only normal and crop modes supported")
2873 selector
.mode
[0] = 0
2874 selector
.mode
[1] = 0
2875 selector
.mode
[2] = 1
2876 selector
.RG
= self
.RG
2879 @_dataclasses.dataclass(eq
=True, frozen
=True)
2880 class SpecifierMR(SpecifierMapReduce
):
2882 def match(cls
, desc
, record
):
2886 return super().match(record
=record
, RG
=False)
2889 @_dataclasses.dataclass(eq
=True, frozen
=True)
2890 class SpecifierMRR(SpecifierMapReduce
):
2892 def match(cls
, desc
, record
):
2896 return super().match(record
=record
, RG
=True)
2899 @_dataclasses.dataclass(eq
=True, frozen
=True)
2900 class SpecifierBranch(Specifier
):
2902 def match(cls
, desc
, record
, etalon
):
2906 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
2907 raise ValueError("only branch modes supported")
2909 return cls(record
=record
)
2912 @_dataclasses.dataclass(eq
=True, frozen
=True)
2913 class SpecifierAll(SpecifierBranch
):
2915 def match(cls
, desc
, record
):
2916 return super().match(desc
=desc
, record
=record
, etalon
="all")
2918 def assemble(self
, insn
):
2919 selector
= insn
.select(record
=self
.record
)
2923 @_dataclasses.dataclass(eq
=True, frozen
=True)
2924 class SpecifierSNZ(Specifier
):
2926 def match(cls
, desc
, record
):
2930 if record
.svp64
.mode
not in (_SVMode
.BRANCH
, _SVMode
.CROP
):
2931 raise ValueError("only branch and crop modes supported")
2933 return cls(record
=record
)
2935 def assemble(self
, insn
):
2936 selector
= insn
.select(record
=self
.record
)
2937 if self
.record
.svp64
.mode
in (_SVMode
.CROP
, _SVMode
.BRANCH
):
2939 if self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
2942 raise ValueError("only branch and crop modes supported")
2945 @_dataclasses.dataclass(eq
=True, frozen
=True)
2946 class SpecifierSL(SpecifierBranch
):
2948 def match(cls
, desc
, record
):
2949 return super().match(desc
=desc
, record
=record
, etalon
="sl")
2951 def assemble(self
, insn
):
2952 selector
= insn
.select(record
=self
.record
)
2956 @_dataclasses.dataclass(eq
=True, frozen
=True)
2957 class SpecifierSLu(SpecifierBranch
):
2959 def match(cls
, desc
, record
):
2960 return super().match(desc
=desc
, record
=record
, etalon
="slu")
2962 def assemble(self
, insn
):
2963 selector
= insn
.select(record
=self
.record
)
2967 @_dataclasses.dataclass(eq
=True, frozen
=True)
2968 class SpecifierLRu(SpecifierBranch
):
2970 def match(cls
, desc
, record
):
2971 return super().match(desc
=desc
, record
=record
, etalon
="lru")
2973 def assemble(self
, insn
):
2974 selector
= insn
.select(record
=self
.record
)
2978 @_dataclasses.dataclass(eq
=True, frozen
=True)
2979 class SpecifierVSXX(SpecifierBranch
):
2984 def match(cls
, desc
, record
, etalon
, VSb
, VLi
):
2988 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
2989 raise ValueError("only branch modes supported")
2991 return cls(record
=record
, VSb
=VSb
, VLi
=VLi
)
2993 def assemble(self
, insn
):
2994 selector
= insn
.select(record
=self
.record
)
2996 selector
.VSb
= int(self
.VSb
)
2997 selector
.VLi
= int(self
.VLi
)
3000 @_dataclasses.dataclass(eq
=True, frozen
=True)
3001 class SpecifierVS(SpecifierVSXX
):
3003 def match(cls
, desc
, record
):
3004 return super().match(desc
=desc
, record
=record
,
3005 etalon
="vs", VSb
=False, VLi
=False)
3008 @_dataclasses.dataclass(eq
=True, frozen
=True)
3009 class SpecifierVSi(SpecifierVSXX
):
3011 def match(cls
, desc
, record
):
3012 return super().match(desc
=desc
, record
=record
,
3013 etalon
="vsi", VSb
=False, VLi
=True)
3016 @_dataclasses.dataclass(eq
=True, frozen
=True)
3017 class SpecifierVSb(SpecifierVSXX
):
3019 def match(cls
, desc
, record
):
3020 return super().match(desc
=desc
, record
=record
,
3021 etalon
="vsb", VSb
=True, VLi
=False)
3024 @_dataclasses.dataclass(eq
=True, frozen
=True)
3025 class SpecifierVSbi(SpecifierVSXX
):
3027 def match(cls
, desc
, record
):
3028 return super().match(desc
=desc
, record
=record
,
3029 etalon
="vsbi", VSb
=True, VLi
=True)
3032 @_dataclasses.dataclass(eq
=True, frozen
=True)
3033 class SpecifierCTX(Specifier
):
3037 def match(cls
, desc
, record
, etalon
, CTi
):
3041 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3042 raise ValueError("only branch modes supported")
3044 return cls(record
=record
, CTi
=CTi
)
3046 def assemble(self
, insn
):
3047 selector
= insn
.select(record
=self
.record
)
3049 selector
.CTi
= int(self
.CTi
)
3052 @_dataclasses.dataclass(eq
=True, frozen
=True)
3053 class SpecifierCTR(SpecifierCTX
):
3055 def match(cls
, desc
, record
):
3056 return super().match(desc
=desc
, record
=record
,
3057 etalon
="ctr", CTi
=False)
3060 @_dataclasses.dataclass(eq
=True, frozen
=True)
3061 class SpecifierCTi(SpecifierCTX
):
3063 def match(cls
, desc
, record
):
3064 return super().match(desc
=desc
, record
=record
,
3065 etalon
="cti", CTi
=True)
3068 @_dataclasses.dataclass(eq
=True, frozen
=True)
3069 class SpecifierPI(Specifier
):
3071 def match(cls
, desc
, record
):
3075 if record
.svp64
.mode
not in [_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
]:
3076 raise ValueError("only ld/st imm/idx mode supported")
3078 return cls(record
=record
)
3080 def assemble(self
, insn
):
3081 selector
= insn
.select(record
=self
.record
)
3082 selector
.mode
[2] = 0b1
3086 @_dataclasses.dataclass(eq
=True, frozen
=True)
3087 class SpecifierLF(Specifier
):
3089 def match(cls
, desc
, record
):
3093 if record
.svp64
.mode
is not _SVMode
.LDST_IMM
:
3094 raise ValueError("only ld/st imm mode supported")
3096 return cls(record
=record
)
3098 def assemble(self
, insn
):
3099 selector
= insn
.select(record
=self
.record
)
3100 selector
.mode
[1] = 0
3104 @_dataclasses.dataclass(eq
=True, frozen
=True)
3105 class SpecifierVLi(Specifier
):
3107 def match(cls
, desc
, record
):
3111 return cls(record
=record
)
3113 def validate(self
, others
):
3115 if isinstance(spec
, SpecifierFF
):
3118 raise ValueError("VLi only allowed in failfirst")
3120 def assemble(self
, insn
):
3121 selector
= insn
.select(record
=self
.record
)
3122 selector
.mode
[1] = 1
3126 class Specifiers(tuple):
3161 def __new__(cls
, items
, record
):
3162 def transform(item
):
3163 for spec_cls
in cls
.SPECS
:
3164 spec
= spec_cls
.match(item
, record
=record
)
3165 if spec
is not None:
3167 raise ValueError(item
)
3169 # TODO: remove this hack
3170 items
= dict.fromkeys(items
)
3174 items
= tuple(items
)
3176 specs
= tuple(map(transform
, items
))
3177 for (index
, spec
) in enumerate(specs
):
3178 head
= specs
[:index
]
3179 tail
= specs
[index
+ 1:]
3180 spec
.validate(others
=(head
+ tail
))
3182 return super().__new
__(cls
, specs
)
3185 class SVP64OperandMeta(type):
3186 class SVP64NonZeroOperand(NonZeroOperand
):
3187 def assemble(self
, insn
, value
):
3188 if isinstance(value
, str):
3189 value
= int(value
, 0)
3190 if not isinstance(value
, int):
3191 raise ValueError("non-integer operand")
3193 # FIXME: this is really weird
3194 if self
.record
.name
in ("svstep", "svstep."):
3195 value
+= 1 # compensation
3197 return super().assemble(value
=value
, insn
=insn
)
3199 class SVP64XOStaticOperand(SpanStaticOperand
):
3200 def __init__(self
, record
, value
, span
):
3201 return super().__init
__(record
=record
, name
="XO",
3202 value
=value
, span
=span
)
3205 NonZeroOperand
: SVP64NonZeroOperand
,
3206 XOStaticOperand
: SVP64XOStaticOperand
,
3209 def __new__(metacls
, name
, bases
, ns
):
3211 for (index
, base_cls
) in enumerate(bases
):
3212 bases
[index
] = metacls
.__TRANSFORM
.get(base_cls
, base_cls
)
3214 bases
= tuple(bases
)
3216 return super().__new
__(metacls
, name
, bases
, ns
)
3219 class SVP64Operand(Operand
, metaclass
=SVP64OperandMeta
):
3222 return tuple(map(lambda bit
: (bit
+ 32), super().span
))
3226 def __init__(self
, insn
, record
):
3228 self
.__record
= record
3229 return super().__init
__()
3232 return self
.rm
.__doc
__
3235 return repr(self
.rm
)
3243 return self
.__record
3247 rm
= getattr(self
.insn
.prefix
.rm
, self
.record
.svp64
.mode
.name
.lower())
3249 # The idea behind these tables is that they are now literally
3250 # in identical format to insndb.csv and minor_xx.csv and can
3251 # be done precisely as that. The only thing to watch out for
3252 # is the insertion of Rc=1 as a "mask/value" bit and likewise
3253 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
3256 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
3257 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3258 # mode Rc mask Rc member
3260 (0b000000, 0b111000, "simple"), # simple (no Rc)
3261 (0b001000, 0b111100, "mr"), # mapreduce (no Rc)
3262 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3263 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3264 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3265 (0b001100, 0b111100, "rsvd"), # reserved
3267 mode
= int(self
.insn
.prefix
.rm
.normal
.mode
)
3268 search
= ((mode
<< 1) | self
.record
.Rc
)
3270 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
3271 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3272 # mode Rc mask Rc member
3273 # ironically/coincidentally this table is identical to NORMAL
3274 # mode except reserved in place of mr
3276 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3277 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3278 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3280 search
= ((int(self
.insn
.prefix
.rm
.ldst_imm
.mode
) << 1) |
3283 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
3284 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3285 # mode Rc mask Rc member
3287 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3288 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3289 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3291 search
= ((int(self
.insn
.prefix
.rm
.ldst_idx
.mode
) << 1) |
3294 elif self
.record
.svp64
.mode
is _SVMode
.CROP
:
3295 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
3296 # mode 3b mask 3b member
3298 (0b000000, 0b111000, "simple"), # simple
3299 (0b001000, 0b111000, "mr"), # mapreduce
3300 (0b010001, 0b010001, "ff3"), # ffirst, 3-bit CR
3301 (0b010000, 0b010000, "ff5"), # ffirst, 5-bit CR
3303 search
= ((int(self
.insn
.prefix
.rm
.crop
.mode
) << 1) |
3304 int(self
.record
.svp64
.extra_CR_3bit
))
3306 elif self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3310 (0b00, 0b11, "simple"), # simple
3311 (0b01, 0b11, "vls"), # VLset
3312 (0b10, 0b11, "ctr"), # CTR mode
3313 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
3315 # slightly weird: doesn't have a 5-bit "mode" field like others
3316 search
= int(self
.insn
.prefix
.rm
.branch
.mode
.sel
)
3319 if table
is not None:
3320 for (value
, mask
, field
) in table
:
3321 if field
.startswith("rsvd"):
3323 if ((value
& mask
) == (search
& mask
)):
3324 return getattr(rm
, field
)
3328 def __getattr__(self
, key
):
3329 if key
.startswith(f
"_{self.__class__.__name__}__"):
3330 return super().__getattribute
__(key
)
3332 return getattr(self
.rm
, key
)
3334 def __setattr__(self
, key
, value
):
3335 if key
.startswith(f
"_{self.__class__.__name__}__"):
3336 return super().__setattr
__(key
, value
)
3339 if not hasattr(rm
, key
):
3340 raise AttributeError(key
)
3342 return setattr(rm
, key
, value
)
3345 class SVP64Instruction(PrefixedInstruction
):
3346 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
3347 class Prefix(PrefixedInstruction
.Prefix
):
3349 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
3353 def select(self
, record
):
3354 return RMSelector(insn
=self
, record
=record
)
3359 for idx
in range(64):
3360 bit
= int(self
[idx
])
3362 return "".join(map(str, bits
))
3365 def assemble(cls
, record
, arguments
=None, specifiers
=None):
3366 insn
= super().assemble(record
=record
, arguments
=arguments
)
3368 specifiers
= Specifiers(items
=specifiers
, record
=record
)
3369 for specifier
in specifiers
:
3370 specifier
.assemble(insn
=insn
)
3372 insn
.prefix
.PO
= 0x1
3373 insn
.prefix
.id = 0x3
3377 def disassemble(self
, record
,
3379 style
=Style
.NORMAL
):
3381 if style
<= Style
.SHORT
:
3384 blob
= insn
.bytes(byteorder
=byteorder
)
3385 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
3388 blob_prefix
= blob(self
.prefix
)
3389 blob_suffix
= blob(self
.suffix
)
3391 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3392 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
3395 assert record
.svp64
is not None
3397 name
= f
"sv.{record.name}"
3399 rm
= self
.select(record
=record
)
3401 # convert specifiers to /x/y/z (sorted lexicographically)
3402 specifiers
= sorted(rm
.specifiers(record
=record
))
3403 if specifiers
: # if any add one extra to get the extra "/"
3404 specifiers
= ([""] + specifiers
)
3405 specifiers
= "/".join(specifiers
)
3407 # convert operands to " ,x,y,z"
3408 operands
= tuple(map(_operator
.itemgetter(1),
3409 self
.spec_dynamic_operands(record
=record
, style
=style
)))
3410 operands
= ",".join(operands
)
3411 if len(operands
) > 0: # if any separate with a space
3412 operands
= (" " + operands
)
3414 if style
<= Style
.LEGACY
:
3415 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3416 suffix
= WordInstruction
.integer(value
=int(self
.suffix
))
3417 yield from suffix
.disassemble(record
=record
,
3418 byteorder
=byteorder
, style
=style
)
3420 yield f
"{blob_prefix}{name}{specifiers}{operands}"
3422 yield f
"{blob_suffix}"
3424 if style
>= Style
.VERBOSE
:
3426 binary
= self
.binary
3427 spec
= self
.spec(record
=record
, prefix
="sv.")
3429 yield f
"{indent}spec"
3430 yield f
"{indent}{indent}{spec}"
3431 yield f
"{indent}pcode"
3432 for stmt
in record
.mdwn
.pcode
:
3433 yield f
"{indent}{indent}{stmt}"
3434 yield f
"{indent}binary"
3435 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
3436 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
3437 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
3438 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
3439 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
3440 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
3441 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
3442 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
3443 yield f
"{indent}opcodes"
3444 for opcode
in record
.opcodes
:
3445 yield f
"{indent}{indent}{opcode!r}"
3446 for operand
in self
.operands(record
=record
):
3447 yield from operand
.disassemble(insn
=self
,
3448 style
=style
, indent
=indent
)
3450 yield f
"{indent}{indent}{str(rm)}"
3451 for line
in rm
.disassemble(style
=style
):
3452 yield f
"{indent}{indent}{line}"
3456 def operands(cls
, record
):
3457 for operand
in super().operands(record
=record
):
3458 parent
= operand
.__class
__
3459 name
= f
"SVP64{parent.__name__}"
3460 bases
= (SVP64Operand
, parent
)
3461 child
= type(name
, bases
, {})
3462 yield child(**dict(operand
))
3465 def parse(stream
, factory
):
3467 return ("TODO" not in frozenset(entry
.values()))
3469 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
3470 entries
= _csv
.DictReader(lines
)
3471 entries
= filter(match
, entries
)
3472 return tuple(map(factory
, entries
))
3475 class MarkdownDatabase
:
3478 for (name
, desc
) in _ISA():
3481 (dynamic
, *static
) = desc
.regs
3482 operands
.extend(dynamic
)
3483 operands
.extend(static
)
3484 pcode
= PCode(filter(str.strip
, desc
.pcode
))
3485 operands
= Operands(insn
=name
, operands
=operands
)
3486 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
3488 self
.__db
= dict(sorted(db
.items()))
3490 return super().__init
__()
3493 yield from self
.__db
.items()
3495 def __contains__(self
, key
):
3496 return self
.__db
.__contains
__(key
)
3498 def __getitem__(self
, key
):
3499 return self
.__db
.__getitem
__(key
)
3502 class FieldsDatabase
:
3505 df
= _DecodeFields()
3507 for (form
, fields
) in df
.instrs
.items():
3508 if form
in {"DQE", "TX"}:
3512 db
[_Form
[form
]] = Fields(fields
)
3516 return super().__init
__()
3518 def __getitem__(self
, key
):
3519 return self
.__db
.__getitem
__(key
)
3523 def __init__(self
, root
, mdwndb
):
3524 # The code below groups the instructions by name:section.
3525 # There can be multiple names for the same instruction.
3526 # The point is to capture different opcodes for the same instruction.
3528 records
= _collections
.defaultdict(set)
3529 path
= (root
/ "insndb.csv")
3530 with
open(path
, "r", encoding
="UTF-8") as stream
:
3531 for section
in sorted(parse(stream
, Section
.CSV
)):
3532 path
= (root
/ section
.csv
)
3534 section
.Mode
.INTEGER
: IntegerOpcode
,
3535 section
.Mode
.PATTERN
: PatternOpcode
,
3537 factory
= _functools
.partial(
3538 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
3539 with
open(path
, "r", encoding
="UTF-8") as stream
:
3540 for insn
in parse(stream
, factory
):
3541 for name
in insn
.names
:
3542 records
[name
].add(insn
)
3543 sections
[name
] = section
3545 items
= sorted(records
.items())
3547 for (name
, multirecord
) in items
:
3548 records
[name
] = PPCMultiRecord(sorted(multirecord
))
3550 def exact_match(name
):
3551 record
= records
.get(name
)
3557 if not name
.endswith("l"):
3559 alias
= exact_match(name
[:-1])
3562 record
= records
[alias
]
3563 if "lk" not in record
.flags
:
3564 raise ValueError(record
)
3568 if not name
.endswith("a"):
3570 alias
= LK_match(name
[:-1])
3573 record
= records
[alias
]
3574 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
3575 raise ValueError(record
)
3576 if "AA" not in mdwndb
[name
].operands
:
3577 raise ValueError(record
)
3581 if not name
.endswith("."):
3583 alias
= exact_match(name
[:-1])
3586 record
= records
[alias
]
3587 if record
.Rc
is _RCOE
.NONE
:
3588 raise ValueError(record
)
3592 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
3593 for (name
, _
) in mdwndb
:
3594 if name
.startswith("sv."):
3597 for match
in matches
:
3599 if alias
is not None:
3603 section
= sections
[alias
]
3604 record
= records
[alias
]
3605 db
[name
] = (section
, record
)
3607 self
.__db
= dict(sorted(db
.items()))
3609 return super().__init
__()
3611 @_functools.lru_cache(maxsize
=512, typed
=False)
3612 def __getitem__(self
, key
):
3613 return self
.__db
.get(key
, (None, None))
3616 class SVP64Database
:
3617 def __init__(self
, root
, ppcdb
):
3619 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
3620 for (prefix
, _
, names
) in _os
.walk(root
):
3621 prefix
= _pathlib
.Path(prefix
)
3622 for name
in filter(lambda name
: pattern
.match(name
), names
):
3623 path
= (prefix
/ _pathlib
.Path(name
))
3624 with
open(path
, "r", encoding
="UTF-8") as stream
:
3625 db
.update(parse(stream
, SVP64Record
.CSV
))
3626 db
= {record
.name
:record
for record
in db
}
3628 self
.__db
= dict(sorted(db
.items()))
3629 self
.__ppcdb
= ppcdb
3631 return super().__init
__()
3633 def __getitem__(self
, key
):
3634 (_
, record
) = self
.__ppcdb
[key
]
3638 for name
in record
.names
:
3639 record
= self
.__db
.get(name
, None)
3640 if record
is not None:
3646 class Records(tuple):
3647 def __new__(cls
, records
):
3648 return super().__new
__(cls
, sorted(records
))
3652 def __init__(self
, root
):
3653 root
= _pathlib
.Path(root
)
3654 mdwndb
= MarkdownDatabase()
3655 fieldsdb
= FieldsDatabase()
3656 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
3657 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
3661 opcodes
= _collections
.defaultdict(
3662 lambda: _collections
.defaultdict(set))
3664 for (name
, mdwn
) in mdwndb
:
3665 if name
.startswith("sv."):
3667 (section
, ppc
) = ppcdb
[name
]
3670 svp64
= svp64db
[name
]
3671 fields
= fieldsdb
[ppc
.form
]
3672 record
= Record(name
=name
,
3673 section
=section
, ppc
=ppc
, svp64
=svp64
,
3674 mdwn
=mdwn
, fields
=fields
)
3676 names
[record
.name
] = record
3677 opcodes
[section
][record
.PO
].add(record
)
3679 self
.__db
= Records(db
)
3680 self
.__names
= dict(sorted(names
.items()))
3681 self
.__opcodes
= dict(sorted(opcodes
.items()))
3683 return super().__init
__()
3686 return repr(self
.__db
)
3689 yield from self
.__db
3691 @_functools.lru_cache(maxsize
=None)
3692 def __contains__(self
, key
):
3693 return self
.__getitem
__(key
) is not None
3695 @_functools.lru_cache(maxsize
=None)
3696 def __getitem__(self
, key
):
3697 if isinstance(key
, SVP64Instruction
):
3700 if isinstance(key
, Instruction
):
3703 sections
= sorted(self
.__opcodes
)
3704 for section
in sections
:
3705 group
= self
.__opcodes
[section
]
3706 for record
in group
[PO
]:
3707 if record
.match(key
=key
):
3712 elif isinstance(key
, str):
3713 return self
.__names
.get(key
)
3715 raise ValueError("instruction or name expected")
3718 class Walker(mdis
.walker
.Walker
):
3719 @mdis.dispatcher
.Hook(Database
)
3720 def dispatch_database(self
, node
):
3721 yield from self(tuple(node
))