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 def dataclass(cls
, record
, keymap
=None, typemap
=None):
90 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
92 def transform(key_value
):
93 (key
, value
) = key_value
94 key
= keymap
.get(key
, key
)
95 hook
= typemap
.get(key
, lambda value
: value
)
96 if hook
is bool and value
in ("", "0"):
102 record
= dict(map(transform
, record
.items()))
103 for key
in frozenset(record
.keys()):
104 if record
[key
] == "":
110 @_functools.total_ordering
113 def __new__(cls
, value
):
114 if isinstance(value
, str):
115 value
= int(value
, 0)
116 if not isinstance(value
, int):
117 raise ValueError(value
)
119 if value
.bit_length() > 64:
120 raise ValueError(value
)
122 return super().__new
__(cls
, value
)
125 return self
.__repr
__()
128 return f
"{self:0{self.bit_length()}b}"
130 def bit_length(self
):
131 if super().bit_length() > 32:
135 class Value(Integer
):
141 def __init__(self
, value
, mask
):
144 return super().__init
__()
154 def __lt__(self
, other
):
155 if not isinstance(other
, Opcode
):
156 return NotImplemented
157 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
160 return (self
.value
& self
.mask
)
163 return int(self
).__index
__()
166 def pattern(value
, mask
, bit_length
):
167 for bit
in range(bit_length
):
168 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
170 elif (value
& (1 << (bit_length
- bit
- 1))):
175 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
177 def match(self
, key
):
178 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
181 @_functools.total_ordering
182 class IntegerOpcode(Opcode
):
183 def __init__(self
, value
):
184 if value
.startswith("0b"):
185 mask
= int(("1" * len(value
[2:])), 2)
189 value
= Opcode
.Value(value
)
190 mask
= Opcode
.Mask(mask
)
192 return super().__init
__(value
=value
, mask
=mask
)
195 @_functools.total_ordering
196 class PatternOpcode(Opcode
):
197 def __init__(self
, pattern
):
198 if not isinstance(pattern
, str):
199 raise ValueError(pattern
)
201 (value
, mask
) = (0, 0)
202 for symbol
in pattern
:
203 if symbol
not in {"0", "1", "-"}:
204 raise ValueError(pattern
)
205 value |
= (symbol
== "1")
206 mask |
= (symbol
!= "-")
212 value
= Opcode
.Value(value
)
213 mask
= Opcode
.Mask(mask
)
215 return super().__init
__(value
=value
, mask
=mask
)
218 class PPCRecord(Dataclass
):
219 class FlagsMeta(type):
234 class Flags(tuple, metaclass
=FlagsMeta
):
235 def __new__(cls
, flags
=frozenset()):
236 flags
= frozenset(flags
)
237 diff
= (flags
- frozenset(cls
))
239 raise ValueError(flags
)
240 return super().__new
__(cls
, sorted(flags
))
244 flags
: Flags
= Flags()
246 function
: _Function
= _Function
.NONE
247 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
248 in1
: _In1Sel
= _In1Sel
.NONE
249 in2
: _In2Sel
= _In2Sel
.NONE
250 in3
: _In3Sel
= _In3Sel
.NONE
251 out
: _OutSel
= _OutSel
.NONE
252 cr_in
: _CRInSel
= _CRInSel
.NONE
253 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
254 cr_out
: _CROutSel
= _CROutSel
.NONE
255 cry_in
: _CryIn
= _CryIn
.ZERO
256 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
257 upd
: _LDSTMode
= _LDSTMode
.NONE
258 Rc
: _RCOE
= _RCOE
.NONE
259 form
: _Form
= _Form
.NONE
265 "internal op": "intop",
269 "ldst len": "ldst_len",
271 "CONDITIONS": "conditions",
274 def __lt__(self
, other
):
275 if not isinstance(other
, self
.__class
__):
276 return NotImplemented
277 lhs
= (self
.opcode
, self
.comment
)
278 rhs
= (other
.opcode
, other
.comment
)
282 def CSV(cls
, record
, opcode_cls
):
283 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
284 typemap
["opcode"] = opcode_cls
286 if record
["CR in"] == "BA_BB":
287 record
["cr_in"] = "BA"
288 record
["cr_in2"] = "BB"
290 elif record
["CR in"] == "BA_BFB":
291 record
["cr_in"] = "BA"
292 record
["cr_in2"] = "BFB"
296 for flag
in frozenset(PPCRecord
.Flags
):
297 if bool(record
.pop(flag
, "")):
299 record
["flags"] = PPCRecord
.Flags(flags
)
301 return dataclass(cls
, record
,
302 keymap
=PPCRecord
.__KEYMAP
,
307 return frozenset(self
.comment
.split("=")[-1].split("/"))
310 class PPCMultiRecord(tuple):
311 def __getattr__(self
, attr
):
314 raise AttributeError(attr
)
315 return getattr(self
[0], attr
)
318 class SVP64Record(Dataclass
):
319 class ExtraMap(tuple):
321 @_dataclasses.dataclass(eq
=True, frozen
=True)
323 seltype
: _SelType
= _SelType
.NONE
324 reg
: _Reg
= _Reg
.NONE
327 return f
"{self.seltype.value}:{self.reg.name}"
329 def __new__(cls
, value
="0"):
330 if isinstance(value
, str):
331 def transform(value
):
332 (seltype
, reg
) = value
.split(":")
333 seltype
= _SelType(seltype
)
335 return cls
.Entry(seltype
=seltype
, reg
=reg
)
340 value
= map(transform
, value
.split(";"))
342 return super().__new
__(cls
, value
)
345 return repr(list(self
))
347 def __new__(cls
, value
=tuple()):
351 return super().__new
__(cls
, map(cls
.Extra
, value
))
354 return repr({index
:self
[index
] for index
in range(0, 4)})
357 ptype
: _SVPType
= _SVPType
.NONE
358 etype
: _SVEType
= _SVEType
.NONE
359 msrc
: _SVMaskSrc
= _SVMaskSrc
.NO
# MASK_SRC is active
360 in1
: _In1Sel
= _In1Sel
.NONE
361 in2
: _In2Sel
= _In2Sel
.NONE
362 in3
: _In3Sel
= _In3Sel
.NONE
363 out
: _OutSel
= _OutSel
.NONE
364 out2
: _OutSel
= _OutSel
.NONE
365 cr_in
: _CRInSel
= _CRInSel
.NONE
366 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
367 cr_out
: _CROutSel
= _CROutSel
.NONE
368 extra
: ExtraMap
= ExtraMap()
370 mode
: _SVMode
= _SVMode
.NORMAL
374 "CONDITIONS": "conditions",
383 def CSV(cls
, record
):
384 record
["insn"] = record
["insn"].split("=")[-1]
386 for key
in frozenset({
387 "in1", "in2", "in3", "CR in",
388 "out", "out2", "CR out",
394 if record
["CR in"] == "BA_BB":
395 record
["cr_in"] = "BA"
396 record
["cr_in2"] = "BB"
398 elif record
["CR in"] == "BFA_BFB_BF":
399 record
["cr_in"] = "BFA"
400 record
["cr_in2"] = "BFB"
401 #record["cr_out"] = "BF" # only use BFA_BFB_BF when BF is a dest
403 elif record
["CR in"] == "BA_BFB": # maaamma miiiia... enough!
404 record
["cr_in"] = "BA"
405 record
["cr_in2"] = "BFB"
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
474 if sels
["cr_in"] is _CRInSel
.BA_BFB
:
475 sels
["cr_in"] = _CRIn2Sel
.BA
476 sels
["cr_in2"] = _CRIn2Sel
.BFB
477 idxs
["cr_in2"] = idxs
["cr_in"]
478 for key
in ("cr_in", "cr_in2"):
479 regs
[key
] = _Reg(sels
[key
])
480 seltype
[key
] = _SelType
.SRC
482 # should only be used when BF is also a destination
483 if sels
["cr_in"] is _CRInSel
.BFA_BFB_BF
:
484 sels
["cr_in"] = _CRIn2Sel
.BFA
485 sels
["cr_in2"] = _CRIn2Sel
.BFB
486 idxs
["cr_in2"] = idxs
["cr_in"]
487 for key
in ("cr_in", "cr_in2"):
488 regs
[key
] = _Reg(sels
[key
])
489 seltype
[key
] = _SelType
.SRC
496 "seltype": seltypes
[key
],
500 return _types
.MappingProxyType(records
)
502 extra_idx_in1
= property(lambda self
: self
.extras
["in1"]["idx"])
503 extra_idx_in2
= property(lambda self
: self
.extras
["in2"]["idx"])
504 extra_idx_in3
= property(lambda self
: self
.extras
["in3"]["idx"])
505 extra_idx_out
= property(lambda self
: self
.extras
["out"]["idx"])
506 extra_idx_out2
= property(lambda self
: self
.extras
["out2"]["idx"])
507 extra_idx_cr_in
= property(lambda self
: self
.extras
["cr_in"]["idx"])
508 extra_idx_cr_in2
= property(lambda self
: self
.extras
["cr_in2"]["idx"])
509 extra_idx_cr_out
= property(lambda self
: self
.extras
["cr_out"]["idx"])
514 for idx
in range(0, 4):
515 for entry
in self
.extra
[idx
]:
516 if entry
.seltype
is _SelType
.DST
:
517 if extra
is not None:
518 raise ValueError(self
.svp64
)
522 if _RegType(extra
.reg
) not in (_RegType
.CR_3BIT
, _RegType
.CR_5BIT
):
523 raise ValueError(self
.svp64
)
528 def extra_CR_3bit(self
):
529 return (_RegType(self
.extra_CR
.reg
) is _RegType
.CR_3BIT
)
532 class Section(Dataclass
):
533 class Path(type(_pathlib
.Path("."))):
537 def __init__(self
, value
=(0, 32)):
538 if isinstance(value
, str):
539 (start
, end
) = map(int, value
.split(":"))
542 if start
< 0 or end
< 0 or start
>= end
:
543 raise ValueError(value
)
548 return super().__init
__()
551 return (self
.__end
- self
.__start
+ 1)
554 return f
"[{self.__start}:{self.__end}]"
557 yield from range(self
.start
, (self
.end
+ 1))
559 def __reversed__(self
):
560 return tuple(reversed(tuple(self
)))
570 class Mode(_enum
.Enum
):
571 INTEGER
= _enum
.auto()
572 PATTERN
= _enum
.auto()
575 def _missing_(cls
, value
):
576 if isinstance(value
, str):
577 return cls
[value
.upper()]
578 return super()._missing
_(value
)
581 def __new__(cls
, value
=None):
582 if isinstance(value
, str):
583 if value
.upper() == "NONE":
586 value
= int(value
, 0)
590 return super().__new
__(cls
, value
)
596 return (bin(self
) if self
else "None")
598 class Opcode(IntegerOpcode
):
601 @_functools.total_ordering
602 class Priority(_enum
.Enum
):
608 def _missing_(cls
, value
):
609 if isinstance(value
, str):
610 value
= value
.upper()
614 return super()._missing
_(value
)
616 def __lt__(self
, other
):
617 if not isinstance(other
, self
.__class
__):
618 return NotImplemented
620 # NOTE: the order is inversed, LOW < NORMAL < HIGH
621 return (self
.value
> other
.value
)
627 opcode
: Opcode
= None
628 priority
: Priority
= Priority
.NORMAL
630 def __lt__(self
, other
):
631 if not isinstance(other
, self
.__class
__):
632 return NotImplemented
633 return (self
.priority
< other
.priority
)
636 def CSV(cls
, record
):
637 keymap
= {"path": "csv"}
638 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
639 if record
["opcode"] == "NONE":
640 typemap
["opcode"] = lambda _
: None
642 return dataclass(cls
, record
, typemap
=typemap
, keymap
=keymap
)
646 def __init__(self
, items
):
647 if isinstance(items
, dict):
648 items
= items
.items()
651 (name
, bitrange
) = item
652 return (name
, tuple(bitrange
.values()))
654 mapping
= dict(map(transform
, items
))
656 return super().__init
__(mapping
)
659 return hash(tuple(sorted(self
.items())))
662 yield from self
.__mapping
.items()
665 class Operands(dict):
677 def __init__(self
, insn
, operands
):
679 "b": {"target_addr": TargetAddrOperandLI
},
680 "ba": {"target_addr": TargetAddrOperandLI
},
681 "bl": {"target_addr": TargetAddrOperandLI
},
682 "bla": {"target_addr": TargetAddrOperandLI
},
683 "bc": {"target_addr": TargetAddrOperandBD
},
684 "bca": {"target_addr": TargetAddrOperandBD
},
685 "bcl": {"target_addr": TargetAddrOperandBD
},
686 "bcla": {"target_addr": TargetAddrOperandBD
},
687 "addpcis": {"D": DOperandDX
},
688 "fishmv": {"D": DOperandDX
},
689 "fmvis": {"D": DOperandDX
},
692 "SVi": NonZeroOperand
,
693 "SVd": NonZeroOperand
,
694 "SVxd": NonZeroOperand
,
695 "SVyd": NonZeroOperand
,
696 "SVzd": NonZeroOperand
,
698 "D": SignedImmediateOperand
,
702 "SIM": SignedOperand
,
703 "SVD": SignedOperand
,
704 "SVDS": SignedOperand
,
705 "RSp": GPRPairOperand
,
706 "RTp": GPRPairOperand
,
707 "FRAp": FPRPairOperand
,
708 "FRBp": FPRPairOperand
,
709 "FRSp": FPRPairOperand
,
710 "FRTp": FPRPairOperand
,
712 custom_immediates
= {
718 for operand
in operands
:
722 (name
, value
) = operand
.split("=")
723 mapping
[name
] = (StaticOperand
, (
725 ("value", int(value
)),
729 if name
.endswith(")"):
730 name
= name
.replace("(", " ").replace(")", "")
731 (imm_name
, _
, name
) = name
.partition(" ")
735 if imm_name
is not None:
736 imm_cls
= custom_immediates
.get(imm_name
, ImmediateOperand
)
738 if insn
in custom_insns
and name
in custom_insns
[insn
]:
739 cls
= custom_insns
[insn
][name
]
740 elif name
in custom_fields
:
741 cls
= custom_fields
[name
]
742 elif name
in _Reg
.__members
__:
744 if reg
in self
.__class
__.__GPR
_PAIRS
:
746 elif reg
in self
.__class
__.__FPR
_PAIRS
:
749 regtype
= _RegType
[name
]
750 if regtype
is _RegType
.GPR
:
752 elif regtype
is _RegType
.FPR
:
754 elif regtype
is _RegType
.CR_3BIT
:
756 elif regtype
is _RegType
.CR_5BIT
:
759 if imm_name
is not None:
760 mapping
[imm_name
] = (imm_cls
, (
763 mapping
[name
] = (cls
, (
767 return super().__init
__(mapping
)
770 for (cls
, kwargs
) in self
.values():
771 yield (cls
, dict(kwargs
))
774 return hash(tuple(sorted(self
.items())))
778 return tuple(filter(lambda pair
: issubclass(pair
[0], StaticOperand
), self
))
782 return tuple(filter(lambda pair
: issubclass(pair
[0], DynamicOperand
), self
))
785 class Arguments(tuple):
786 def __new__(cls
, record
, arguments
, operands
):
787 operands
= iter(tuple(operands
))
788 arguments
= iter(tuple(arguments
))
793 operand
= next(operands
)
794 except StopIteration:
798 argument
= next(arguments
)
799 except StopIteration:
800 raise ValueError("operands count mismatch")
802 if isinstance(operand
, ImmediateOperand
):
803 argument
= argument
.replace("(", " ").replace(")", "")
804 (imm_argument
, _
, argument
) = argument
.partition(" ")
806 (imm_operand
, operand
) = (operand
, next(operands
))
807 except StopIteration:
808 raise ValueError("operands count mismatch")
809 items
.append((imm_argument
, imm_operand
))
810 items
.append((argument
, operand
))
814 except StopIteration:
817 raise ValueError("operands count mismatch")
819 return super().__new
__(cls
, items
)
826 class MarkdownRecord(Dataclass
):
831 @_functools.total_ordering
832 class Record(Dataclass
):
838 svp64
: SVP64Record
= None
842 if self
.svp64
is not None:
843 return self
.svp64
.extras
845 return _types
.MappingProxyType({})
849 return self
.mdwn
.pcode
851 def __lt__(self
, other
):
852 if not isinstance(other
, Record
):
853 return NotImplemented
854 lhs
= (min(self
.opcodes
), self
.name
)
855 rhs
= (min(other
.opcodes
), other
.name
)
860 return (self
.static_operands
+ self
.dynamic_operands
)
863 def static_operands(self
):
865 operands
.append(POStaticOperand(record
=self
, value
=self
.PO
))
867 operands
.append(XOStaticOperand(
869 value
=ppc
.opcode
.value
,
870 span
=self
.section
.bitsel
,
872 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
873 operands
.append(cls(record
=self
, **kwargs
))
874 return tuple(operands
)
877 def dynamic_operands(self
):
879 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
880 operands
.append(cls(record
=self
, **kwargs
))
881 return tuple(operands
)
886 return int("".join(str(int(mapping
[bit
])) \
887 for bit
in sorted(mapping
)), 2)
889 def PO_XO(value
, mask
, opcode
, bits
):
892 for (src
, dst
) in enumerate(reversed(bits
)):
893 value
[dst
] = ((opcode
.value
& (1 << src
)) != 0)
894 mask
[dst
] = ((opcode
.mask
& (1 << src
)) != 0)
897 def PO(value
, mask
, opcode
, bits
):
898 return PO_XO(value
=value
, mask
=mask
, opcode
=opcode
, bits
=bits
)
900 def XO(value
, mask
, opcode
, bits
):
901 (value
, mask
) = PO_XO(value
=value
, mask
=mask
,
902 opcode
=opcode
, bits
=bits
)
903 for (op_cls
, op_kwargs
) in self
.mdwn
.operands
.static
:
904 operand
= op_cls(record
=self
, **op_kwargs
)
905 for (src
, dst
) in enumerate(reversed(operand
.span
)):
906 value
[dst
] = ((operand
.value
& (1 << src
)) != 0)
911 value
= {bit
:False for bit
in range(32)}
912 mask
= {bit
:False for bit
in range(32)}
913 if self
.section
.opcode
is not None:
914 (value
, mask
) = PO(value
=value
, mask
=mask
,
915 opcode
=self
.section
.opcode
, bits
=range(0, 6))
917 pairs
.append(XO(value
=value
, mask
=mask
,
918 opcode
=ppc
.opcode
, bits
=self
.section
.bitsel
))
921 for (value
, mask
) in pairs
:
922 value
= Opcode
.Value(binary(value
))
923 mask
= Opcode
.Mask(binary(mask
))
924 result
.append(Opcode(value
=value
, mask
=mask
))
930 opcode
= self
.section
.opcode
932 opcode
= self
.ppc
[0].opcode
933 if isinstance(opcode
, PatternOpcode
):
934 value
= int(opcode
.value
)
935 bits
= opcode
.value
.bit_length()
936 return int(_SelectableInt(value
=value
, bits
=bits
)[0:6])
938 return int(opcode
.value
)
942 return tuple(ppc
.opcode
for ppc
in self
.ppc
)
944 def match(self
, key
):
945 for opcode
in self
.opcodes
:
946 if opcode
.match(key
):
953 return self
.svp64
.mode
973 if self
.svp64
is None:
979 return self
.ppc
.cr_in
983 return self
.ppc
.cr_in2
987 return self
.ppc
.cr_out
989 ptype
= property(lambda self
: self
.svp64
.ptype
)
990 etype
= property(lambda self
: self
.svp64
.etype
)
992 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
993 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
994 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
995 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
996 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
997 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
998 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
999 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
1001 def __contains__(self
, key
):
1002 return self
.mdwn
.operands
.__contains
__(key
)
1004 def __getitem__(self
, key
):
1005 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
1006 return cls(record
=self
, **dict(kwargs
))
1010 if "Rc" not in self
:
1012 return self
["Rc"].value
1016 def __init__(self
, record
, name
):
1017 self
.__record
= record
1021 yield ("record", self
.record
)
1022 yield ("name", self
.__name
)
1025 return f
"{self.__class__.__name__}({self.name})"
1033 return self
.__record
1037 return self
.record
.fields
[self
.name
]
1039 def assemble(self
, insn
):
1040 raise NotImplementedError()
1042 def disassemble(self
, insn
,
1043 style
=Style
.NORMAL
, indent
=""):
1044 raise NotImplementedError()
1047 class DynamicOperand(Operand
):
1048 def assemble(self
, insn
, value
):
1050 if isinstance(value
, str):
1051 value
= int(value
, 0)
1053 raise ValueError("signed operands not allowed")
1056 def disassemble(self
, insn
,
1057 style
=Style
.NORMAL
, indent
=""):
1061 if style
>= Style
.VERBOSE
:
1062 span
= map(str, span
)
1063 yield f
"{indent}{self.name}"
1064 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1065 yield f
"{indent}{indent}{', '.join(span)}"
1067 yield str(int(value
))
1070 class SignedOperand(DynamicOperand
):
1071 def assemble(self
, insn
, value
):
1072 if isinstance(value
, str):
1073 value
= int(value
, 0)
1074 return super().assemble(value
=value
, insn
=insn
)
1076 def assemble(self
, insn
, value
):
1078 if isinstance(value
, str):
1079 value
= int(value
, 0)
1082 def disassemble(self
, insn
,
1083 style
=Style
.NORMAL
, indent
=""):
1085 value
= insn
[span
].to_signed_int()
1086 sign
= "-" if (value
< 0) else ""
1089 if style
>= Style
.VERBOSE
:
1090 span
= map(str, span
)
1091 yield f
"{indent}{self.name}"
1092 yield f
"{indent}{indent}{sign}{value}"
1093 yield f
"{indent}{indent}{', '.join(span)}"
1095 yield f
"{sign}{value}"
1098 class StaticOperand(Operand
):
1099 def __init__(self
, record
, name
, value
):
1100 self
.__value
= value
1101 return super().__init
__(record
=record
, name
=name
)
1104 yield ("value", self
.__value
)
1105 yield from super().__iter
__()
1108 return f
"{self.__class__.__name__}({self.name}, value={self.value})"
1114 def assemble(self
, insn
):
1115 insn
[self
.span
] = self
.value
1117 def disassemble(self
, insn
,
1118 style
=Style
.NORMAL
, indent
=""):
1122 if style
>= Style
.VERBOSE
:
1123 span
= map(str, span
)
1124 yield f
"{indent}{self.name}"
1125 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1126 yield f
"{indent}{indent}{', '.join(span)}"
1128 yield str(int(value
))
1131 class SpanStaticOperand(StaticOperand
):
1132 def __init__(self
, record
, name
, value
, span
):
1133 self
.__span
= tuple(span
)
1134 return super().__init
__(record
=record
, name
=name
, value
=value
)
1137 yield ("span", self
.__span
)
1138 yield from super().__iter
__()
1145 class POStaticOperand(SpanStaticOperand
):
1146 def __init__(self
, record
, value
):
1147 return super().__init
__(record
=record
, name
="PO",
1148 value
=value
, span
=range(0, 6))
1151 for (key
, value
) in super().__iter
__():
1152 if key
not in {"name", "span"}:
1156 class XOStaticOperand(SpanStaticOperand
):
1157 def __init__(self
, record
, value
, span
):
1158 bits
= record
.section
.bitsel
1159 value
= _SelectableInt(value
=value
, bits
=len(bits
))
1160 span
= dict(zip(bits
, range(len(bits
))))
1161 span_rev
= {value
:key
for (key
, value
) in span
.items()}
1163 # This part is tricky: we cannot use record.operands,
1164 # as this code is called by record.static_operands method.
1165 for (cls
, kwargs
) in record
.mdwn
.operands
:
1166 operand
= cls(record
=record
, **kwargs
)
1167 for idx
in operand
.span
:
1168 rev
= span
.pop(idx
, None)
1170 span_rev
.pop(rev
, None)
1172 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1173 span
= tuple(span
.keys())
1175 return super().__init
__(record
=record
, name
="XO",
1176 value
=value
, span
=span
)
1179 for (key
, value
) in super().__iter
__():
1180 if key
not in {"name"}:
1184 class ImmediateOperand(DynamicOperand
):
1188 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1192 class NonZeroOperand(DynamicOperand
):
1193 def assemble(self
, insn
, value
):
1194 if isinstance(value
, str):
1195 value
= int(value
, 0)
1196 if not isinstance(value
, int):
1197 raise ValueError("non-integer operand")
1199 raise ValueError("non-zero operand")
1201 return super().assemble(value
=value
, insn
=insn
)
1203 def disassemble(self
, insn
,
1204 style
=Style
.NORMAL
, indent
=""):
1208 if style
>= Style
.VERBOSE
:
1209 span
= map(str, span
)
1210 yield f
"{indent}{self.name}"
1211 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1212 yield f
"{indent}{indent}{', '.join(span)}"
1214 yield str(int(value
) + 1)
1217 class ExtendableOperand(DynamicOperand
):
1218 def sv_spec_enter(self
, value
, span
):
1219 return (value
, span
)
1221 def sv_spec(self
, insn
):
1225 span
= tuple(map(str, span
))
1227 if isinstance(insn
, SVP64Instruction
):
1228 (origin_value
, origin_span
) = (value
, span
)
1229 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1231 for extra_idx
in self
.extra_idx
:
1232 if self
.record
.etype
is _SVEType
.EXTRA3
:
1233 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1234 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1235 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1237 raise ValueError(self
.record
.etype
)
1240 vector
= bool(spec
[0])
1241 spec_span
= spec
.__class
__
1242 if self
.record
.etype
is _SVEType
.EXTRA3
:
1243 spec_span
= tuple(map(str, spec_span
[1, 2]))
1245 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1246 spec_span
= tuple(map(str, spec_span
[1,]))
1247 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1250 spec_span
= (spec_span
+ ("{0}",))
1252 spec_span
= (("{0}",) + spec_span
)
1254 raise ValueError(self
.record
.etype
)
1256 vector_shift
= (2 + (5 - value
.bits
))
1257 scalar_shift
= value
.bits
1258 spec_shift
= (5 - value
.bits
)
1260 bits
= (len(span
) + len(spec_span
))
1261 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1262 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1264 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1265 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1267 value
= ((spec
<< scalar_shift
) | value
)
1268 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1270 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1271 origin_value
=origin_value
, origin_span
=origin_span
)
1273 return (vector
, value
, span
)
1275 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1276 return (value
, span
)
1279 def extra_idx(self
):
1280 for (key
, record
) in self
.record
.svp64
.extras
.items():
1281 if record
["reg"].alias
is self
.extra_reg
.alias
:
1285 def extra_reg(self
):
1286 return _Reg(self
.name
)
1288 def remap(self
, value
, vector
):
1289 raise NotImplementedError()
1291 def assemble(self
, value
, insn
, prefix
):
1294 if isinstance(value
, str):
1295 value
= value
.lower()
1296 if value
.startswith("%"):
1298 if value
.startswith("*"):
1299 if not isinstance(insn
, SVP64Instruction
):
1300 raise ValueError(value
)
1303 if value
.startswith(prefix
):
1304 if (self
.extra_reg
.or_zero
and (value
== f
"{prefix}0")):
1305 raise ValueError(value
)
1306 value
= value
[len(prefix
):]
1307 value
= int(value
, 0)
1309 if isinstance(insn
, SVP64Instruction
):
1310 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1312 for extra_idx
in self
.extra_idx
:
1313 if self
.record
.etype
is _SVEType
.EXTRA3
:
1314 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1315 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1316 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1318 raise ValueError(self
.record
.etype
)
1320 return super().assemble(value
=value
, insn
=insn
)
1322 def disassemble(self
, insn
,
1323 style
=Style
.NORMAL
, prefix
="", indent
=""):
1324 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1326 if (self
.extra_reg
.or_zero
and (value
== 0)):
1329 if style
>= Style
.VERBOSE
:
1330 mode
= "vector" if vector
else "scalar"
1331 yield f
"{indent}{self.name} ({mode})"
1332 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1333 yield f
"{indent}{indent}{', '.join(span)}"
1334 if isinstance(insn
, SVP64Instruction
):
1335 for extra_idx
in frozenset(self
.extra_idx
):
1336 if self
.record
.etype
is _SVEType
.NONE
:
1337 yield f
"{indent}{indent}extra[none]"
1339 etype
= repr(self
.record
.etype
).lower()
1340 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1342 vector
= "*" if vector
else ""
1343 yield f
"{vector}{prefix}{int(value)}"
1346 class SimpleRegisterOperand(ExtendableOperand
):
1347 def remap(self
, value
, vector
):
1349 extra
= (value
& 0b11)
1350 value
= (value
>> 2)
1352 extra
= (value
>> 5)
1353 value
= (value
& 0b11111)
1355 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1356 # (and shrink to a single bit if ok)
1357 if self
.record
.etype
is _SVEType
.EXTRA2
:
1359 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1360 assert (extra
& 0b01) == 0, \
1361 ("vector field %s cannot fit into EXTRA2" % value
)
1362 extra
= (0b10 |
(extra
>> 1))
1364 # range is r0-r63 in increments of 1
1365 assert (extra
>> 1) == 0, \
1366 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1368 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1370 # EXTRA3 vector bit needs marking
1373 raise ValueError(self
.record
.etype
)
1375 return (value
, extra
)
1378 class GPROperand(SimpleRegisterOperand
):
1379 def assemble(self
, insn
, value
):
1380 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1382 def disassemble(self
, insn
,
1383 style
=Style
.NORMAL
, indent
=""):
1384 prefix
= "" if (style
<= Style
.SHORT
) else "r"
1385 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1386 style
=style
, indent
=indent
)
1389 class GPRPairOperand(GPROperand
):
1393 class FPROperand(SimpleRegisterOperand
):
1394 def assemble(self
, insn
, value
):
1395 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1397 def disassemble(self
, insn
,
1398 style
=Style
.NORMAL
, indent
=""):
1399 prefix
= "" if (style
<= Style
.SHORT
) else "f"
1400 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1401 style
=style
, indent
=indent
)
1404 class FPRPairOperand(FPROperand
):
1408 class ConditionRegisterFieldOperand(ExtendableOperand
):
1409 def pattern(name_pattern
):
1410 (name
, pattern
) = name_pattern
1411 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1420 CR
= r
"(?:CR|cr)([0-9]+)"
1422 BIT
= rf
"({'|'.join(CONDS.keys())})"
1423 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1424 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1425 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1426 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1427 XCR
= fr
"{CR}\.{BIT}"
1428 PATTERNS
= tuple(map(pattern
, (
1433 ("BIT+CR", (LBIT
+ CR
)),
1434 ("CR+BIT", (CR
+ RBIT
)),
1435 ("BIT+CR*N", (LBIT
+ CRN
)),
1436 ("CR*N+BIT", (CRN
+ RBIT
)),
1437 ("BIT+N*CR", (LBIT
+ NCR
)),
1438 ("N*CR+BIT", (NCR
+ RBIT
)),
1441 def remap(self
, value
, vector
, regtype
):
1442 # if 5-bit, take out the lower 2 bits (EQ/LT/GT/SO)
1443 # and reduce the value down to the CR Field number only
1444 if regtype
is _RegType
.CR_5BIT
:
1445 subvalue
= (value
& 0b11)
1448 if self
.record
.etype
is _SVEType
.EXTRA2
:
1449 # very reduced range
1451 # vector range is CR0-CR120 in increments of 8
1452 assert value
% 8 == 0, "vector CR cannot fit into EXTRA2"
1453 extra
= 0b10 |
((value
>>3)&0b1)
1456 # scalar range is CR0-CR15 in increments of 1
1457 assert value
< 16, "scalar CR cannot fit into EXTRA2"
1458 extra
= (value
>> 4)
1460 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1462 # vector range is CR0-CR124 in increments of 4
1463 assert value
% 4 == 0, "vector CR cannot fit into EXTRA3"
1464 extra
= 0b100 |
((value
>>2)&0b1)
1467 # scalar range is CR0-CR31 in increments of 1
1468 assert value
< 32, "scalar CR cannot fit into EXTRA3"
1469 extra
= (value
>> 3)
1472 # if 5-bit, restore the 2 lower 2 bits
1473 if regtype
is _RegType
.CR_5BIT
:
1474 value
= ((value
<< 2) | subvalue
)
1476 return (value
, extra
)
1478 def assemble(self
, insn
, value
):
1479 if isinstance(value
, str):
1482 if value
.startswith("*"):
1483 if not isinstance(insn
, SVP64Instruction
):
1484 raise ValueError(value
)
1488 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1489 match
= pattern
.match(value
)
1490 if match
is not None:
1491 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1492 values
= match
.groups()
1493 match
= dict(zip(keys
, values
))
1494 CR
= int(match
["CR"])
1498 N
= int(match
.get("N", "1"))
1499 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1500 value
= ((CR
* N
) + BIT
)
1507 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1509 def disassemble(self
, insn
,
1510 style
=Style
.NORMAL
, prefix
="", indent
=""):
1511 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1513 if style
>= Style
.VERBOSE
:
1514 mode
= "vector" if vector
else "scalar"
1515 yield f
"{indent}{self.name} ({mode})"
1516 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1517 yield f
"{indent}{indent}{', '.join(span)}"
1518 if isinstance(insn
, SVP64Instruction
):
1519 for extra_idx
in frozenset(self
.extra_idx
):
1520 if self
.record
.etype
is _SVEType
.NONE
:
1521 yield f
"{indent}{indent}extra[none]"
1523 etype
= repr(self
.record
.etype
).lower()
1524 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1526 vector
= "*" if vector
else ""
1527 CR
= int(value
>> 2)
1529 cond
= ("lt", "gt", "eq", "so")[CC
]
1530 if style
>= Style
.NORMAL
:
1532 if isinstance(insn
, SVP64Instruction
):
1533 yield f
"{vector}cr{CR}.{cond}"
1535 yield f
"4*cr{CR}+{cond}"
1539 yield f
"{vector}{prefix}{int(value)}"
1542 class CR3Operand(ConditionRegisterFieldOperand
):
1543 def remap(self
, value
, vector
):
1544 return super().remap(value
=value
, vector
=vector
,
1545 regtype
=_RegType
.CR_3BIT
)
1548 class CR5Operand(ConditionRegisterFieldOperand
):
1549 def remap(self
, value
, vector
):
1550 return super().remap(value
=value
, vector
=vector
,
1551 regtype
=_RegType
.CR_5BIT
)
1553 def sv_spec_enter(self
, value
, span
):
1554 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1555 return (value
, span
)
1557 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1558 value
= _selectconcat(value
, origin_value
[3:5])
1560 return (value
, span
)
1563 class EXTSOperand(SignedOperand
):
1564 field
: str # real name to report
1565 nz
: int = 0 # number of zeros
1566 fmt
: str = "d" # integer formatter
1568 def __init__(self
, record
, name
, field
, nz
=0, fmt
="d"):
1569 self
.__field
= field
1572 return super().__init
__(record
=record
, name
=name
)
1588 return self
.record
.fields
[self
.field
]
1590 def assemble(self
, insn
, value
):
1592 if isinstance(value
, str):
1593 value
= int(value
, 0)
1594 insn
[span
] = (value
>> self
.nz
)
1596 def disassemble(self
, insn
,
1597 style
=Style
.NORMAL
, indent
=""):
1599 value
= insn
[span
].to_signed_int()
1600 sign
= "-" if (value
< 0) else ""
1601 value
= (abs(value
) << self
.nz
)
1603 if style
>= Style
.VERBOSE
:
1604 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1605 zeros
= ("0" * self
.nz
)
1606 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1607 yield f
"{indent * 1}{hint}"
1608 yield f
"{indent * 2}{self.field}"
1609 yield f
"{indent * 3}{sign}{value:{self.fmt}}"
1610 yield f
"{indent * 3}{', '.join(span)}"
1612 yield f
"{sign}{value:{self.fmt}}"
1615 class TargetAddrOperand(EXTSOperand
):
1616 def __init__(self
, record
, name
, field
):
1617 return super().__init
__(record
=record
, name
=name
, field
=field
,
1621 class TargetAddrOperandLI(TargetAddrOperand
):
1622 def __init__(self
, record
, name
):
1623 return super().__init
__(record
=record
, name
=name
, field
="LI")
1626 class TargetAddrOperandBD(TargetAddrOperand
):
1627 def __init__(self
, record
, name
):
1628 return super().__init
__(record
=record
, name
=name
, field
="BD")
1631 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1632 def __init__(self
, record
, name
):
1633 return super().__init
__(record
=record
, name
=name
, field
="DS", nz
=2)
1636 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1637 def __init__(self
, record
, name
):
1638 return super().__init
__(record
=record
, name
=name
, field
="DQ", nz
=4)
1641 class DOperandDX(SignedOperand
):
1644 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1645 operands
= map(cls
, ("d0", "d1", "d2"))
1646 spans
= map(lambda operand
: operand
.span
, operands
)
1647 return sum(spans
, tuple())
1649 def disassemble(self
, insn
,
1650 style
=Style
.NORMAL
, indent
=""):
1652 value
= insn
[span
].to_signed_int()
1653 sign
= "-" if (value
< 0) else ""
1656 if style
>= Style
.VERBOSE
:
1663 for (subname
, subspan
) in mapping
.items():
1664 operand
= DynamicOperand(name
=subname
)
1666 span
= map(str, span
)
1667 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1668 yield f
"{indent}{indent}{indent}{sign}{value}"
1669 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1671 yield f
"{sign}{value}"
1674 class Instruction(_Mapping
):
1676 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1677 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1678 raise ValueError(bits
)
1680 if isinstance(value
, bytes
):
1681 if ((len(value
) * 8) != bits
):
1682 raise ValueError(f
"bit length mismatch")
1683 value
= int.from_bytes(value
, byteorder
=byteorder
)
1685 if isinstance(value
, int):
1686 value
= _SelectableInt(value
=value
, bits
=bits
)
1687 elif isinstance(value
, Instruction
):
1688 value
= value
.storage
1690 if not isinstance(value
, _SelectableInt
):
1691 raise ValueError(value
)
1694 if len(value
) != bits
:
1695 raise ValueError(value
)
1697 value
= _SelectableInt(value
=value
, bits
=bits
)
1699 return cls(storage
=value
)
1702 return hash(int(self
))
1704 def __getitem__(self
, key
):
1705 return self
.storage
.__getitem
__(key
)
1707 def __setitem__(self
, key
, value
):
1708 return self
.storage
.__setitem
__(key
, value
)
1710 def bytes(self
, byteorder
="little"):
1711 nr_bytes
= (len(self
.__class
__) // 8)
1712 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1715 def record(cls
, db
, entry
):
1718 raise KeyError(entry
)
1722 def operands(cls
, record
):
1723 yield from record
.operands
1726 def static_operands(cls
, record
):
1727 return filter(lambda operand
: isinstance(operand
, StaticOperand
),
1728 cls
.operands(record
=record
))
1731 def dynamic_operands(cls
, record
):
1732 return filter(lambda operand
: isinstance(operand
, DynamicOperand
),
1733 cls
.operands(record
=record
))
1735 def spec(self
, record
, prefix
):
1736 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1737 self
.spec_dynamic_operands(record
=record
)))
1739 static_operands
= []
1740 for (name
, value
) in self
.spec_static_operands(record
=record
):
1741 static_operands
.append(f
"{name}={value}")
1744 if dynamic_operands
:
1746 operands
+= ",".join(dynamic_operands
)
1749 operands
+= " ".join(static_operands
)
1751 return f
"{prefix}{record.name}{operands}"
1753 def spec_static_operands(self
, record
):
1754 for operand
in self
.static_operands(record
=record
):
1755 if not isinstance(operand
, (POStaticOperand
, XOStaticOperand
)):
1756 yield (operand
.name
, operand
.value
)
1758 def spec_dynamic_operands(self
, record
, style
=Style
.NORMAL
):
1762 for operand
in self
.dynamic_operands(record
=record
):
1764 value
= " ".join(operand
.disassemble(insn
=self
,
1765 style
=min(style
, Style
.NORMAL
)))
1767 name
= f
"{imm_name}({name})"
1768 value
= f
"{imm_value}({value})"
1770 if isinstance(operand
, ImmediateOperand
):
1778 def assemble(cls
, record
, arguments
=None):
1779 if arguments
is None:
1782 insn
= cls
.integer(value
=0)
1784 for operand
in cls
.static_operands(record
=record
):
1785 operand
.assemble(insn
=insn
)
1787 arguments
= Arguments(record
=record
,
1788 arguments
=arguments
, operands
=cls
.dynamic_operands(record
=record
))
1789 for (value
, operand
) in arguments
:
1790 operand
.assemble(insn
=insn
, value
=value
)
1794 def disassemble(self
, record
,
1796 style
=Style
.NORMAL
):
1797 raise NotImplementedError()
1800 class WordInstruction(Instruction
):
1801 _
: _Field
= range(0, 32)
1802 PO
: _Field
= range(0, 6)
1805 def integer(cls
, value
, byteorder
="little"):
1806 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1811 for idx
in range(32):
1812 bit
= int(self
[idx
])
1814 return "".join(map(str, bits
))
1816 def disassemble(self
, record
,
1818 style
=Style
.NORMAL
):
1819 if style
<= Style
.SHORT
:
1822 blob
= self
.bytes(byteorder
=byteorder
)
1823 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1827 yield f
"{blob}.long 0x{int(self):08x}"
1830 # awful temporary hack: workaround for ld-update
1831 # https://bugs.libre-soc.org/show_bug.cgi?id=1056#c2
1832 # XXX TODO must check that *EXTENDED* RA != extended-RT
1833 if (record
.svp64
is not None and
1834 record
.mode
== _SVMode
.LDST_IMM
and
1835 'u' in record
.name
):
1836 yield f
"{blob}.long 0x{int(self):08x}"
1840 if style
is Style
.LEGACY
:
1842 for operand
in self
.dynamic_operands(record
=record
):
1843 if isinstance(operand
, (GPRPairOperand
, FPRPairOperand
)):
1846 # unofficial == "0" means an official instruction that needs .long
1847 if style
is Style
.LEGACY
and (paired
or record
.ppc
.unofficial
!= ""):
1848 yield f
"{blob}.long 0x{int(self):08x}"
1850 operands
= tuple(map(_operator
.itemgetter(1),
1851 self
.spec_dynamic_operands(record
=record
, style
=style
)))
1853 operands
= ",".join(operands
)
1854 yield f
"{blob}{record.name} {operands}"
1856 yield f
"{blob}{record.name}"
1858 if style
>= Style
.VERBOSE
:
1860 binary
= self
.binary
1861 spec
= self
.spec(record
=record
, prefix
="")
1862 yield f
"{indent}spec"
1863 yield f
"{indent}{indent}{spec}"
1864 yield f
"{indent}pcode"
1865 for stmt
in record
.mdwn
.pcode
:
1866 yield f
"{indent}{indent}{stmt}"
1867 yield f
"{indent}binary"
1868 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1869 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1870 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1871 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1872 yield f
"{indent}opcodes"
1873 for opcode
in record
.opcodes
:
1874 yield f
"{indent}{indent}{opcode!r}"
1875 for operand
in self
.operands(record
=record
):
1876 yield from operand
.disassemble(insn
=self
,
1877 style
=style
, indent
=indent
)
1881 class PrefixedInstruction(Instruction
):
1882 class Prefix(WordInstruction
.remap(range(0, 32))):
1885 class Suffix(WordInstruction
.remap(range(32, 64))):
1888 _
: _Field
= range(64)
1894 def integer(cls
, value
, byteorder
="little"):
1895 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
1898 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
1899 def transform(value
):
1900 return WordInstruction
.integer(value
=value
,
1901 byteorder
=byteorder
)[0:32]
1903 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
1904 value
= _selectconcat(prefix
, suffix
)
1906 return super().integer(bits
=64, value
=value
)
1909 class Mode(_Mapping
):
1910 _
: _Field
= range(0, 5)
1911 sel
: _Field
= (0, 1)
1914 class ExtraRM(_Mapping
):
1915 _
: _Field
= range(0, 9)
1918 class Extra2RM(ExtraRM
):
1919 idx0
: _Field
= range(0, 2)
1920 idx1
: _Field
= range(2, 4)
1921 idx2
: _Field
= range(4, 6)
1922 idx3
: _Field
= range(6, 8)
1924 def __getitem__(self
, key
):
1930 _SVExtra
.Idx0
: self
.idx0
,
1931 _SVExtra
.Idx1
: self
.idx1
,
1932 _SVExtra
.Idx2
: self
.idx2
,
1933 _SVExtra
.Idx3
: self
.idx3
,
1936 def __setitem__(self
, key
, value
):
1937 self
[key
].assign(value
)
1940 class Extra3RM(ExtraRM
):
1941 idx0
: _Field
= range(0, 3)
1942 idx1
: _Field
= range(3, 6)
1943 idx2
: _Field
= range(6, 9)
1945 def __getitem__(self
, key
):
1950 _SVExtra
.Idx0
: self
.idx0
,
1951 _SVExtra
.Idx1
: self
.idx1
,
1952 _SVExtra
.Idx2
: self
.idx2
,
1955 def __setitem__(self
, key
, value
):
1956 self
[key
].assign(value
)
1959 class BaseRM(_Mapping
):
1960 _
: _Field
= range(24)
1961 mmode
: _Field
= (0,)
1962 mask
: _Field
= range(1, 4)
1963 elwidth
: _Field
= range(4, 6)
1964 ewsrc
: _Field
= range(6, 8)
1965 subvl
: _Field
= range(8, 10)
1966 mode
: Mode
.remap(range(19, 24))
1967 smask_extra322
: _Field
= (6,7,18,) # LDST_IDX is EXTRA332
1968 smask
: _Field
= range(16, 19) # everything else use this
1969 extra
: ExtraRM
.remap(range(10, 19))
1970 extra2
: Extra2RM
.remap(range(10, 19))
1971 extra3
: Extra3RM
.remap(range(10, 19))
1972 # XXX extra332 = (extra3[0], extra3[1], extra2[3])
1974 def specifiers(self
, record
):
1975 subvl
= int(self
.subvl
)
1983 def disassemble(self
, style
=Style
.NORMAL
):
1984 if style
>= Style
.VERBOSE
:
1986 for (name
, span
) in self
.traverse(path
="RM"):
1987 value
= self
.storage
[span
]
1989 yield f
"{indent}{int(value):0{value.bits}b}"
1990 yield f
"{indent}{', '.join(map(str, span))}"
1993 class FFRc1BaseRM(BaseRM
):
1994 def specifiers(self
, record
, mode
):
1995 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
1996 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
1997 mask
= int(_selectconcat(CR
, inv
))
1998 predicate
= PredicateBaseRM
.predicate(True, mask
)
1999 yield f
"{mode}={predicate}"
2001 yield from super().specifiers(record
=record
)
2004 class FFRc0BaseRM(BaseRM
):
2005 def specifiers(self
, record
, mode
):
2007 inv
= "~" if self
.inv
else ""
2008 yield f
"{mode}={inv}RC1"
2010 yield from super().specifiers(record
=record
)
2013 class SatBaseRM(BaseRM
):
2014 def specifiers(self
, record
):
2020 yield from super().specifiers(record
=record
)
2023 class ZZBaseRM(BaseRM
):
2024 def specifiers(self
, record
):
2028 yield from super().specifiers(record
=record
)
2031 class ZZCombinedBaseRM(BaseRM
):
2032 def specifiers(self
, record
):
2033 if self
.sz
and self
.dz
:
2040 yield from super().specifiers(record
=record
)
2043 class DZBaseRM(BaseRM
):
2044 def specifiers(self
, record
):
2048 yield from super().specifiers(record
=record
)
2051 class SZBaseRM(BaseRM
):
2052 def specifiers(self
, record
):
2056 yield from super().specifiers(record
=record
)
2059 class MRBaseRM(BaseRM
):
2060 def specifiers(self
, record
):
2066 yield from super().specifiers(record
=record
)
2069 class ElsBaseRM(BaseRM
):
2070 def specifiers(self
, record
):
2074 yield from super().specifiers(record
=record
)
2077 class WidthBaseRM(BaseRM
):
2079 def width(FP
, width
):
2088 width
= ("fp" + width
)
2091 def specifiers(self
, record
):
2092 # elwidths: use "w=" if same otherwise dw/sw
2093 # FIXME this should consider FP instructions
2095 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
2096 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2097 if record
.svp64
.mode
is _SVMode
.CROP
:
2101 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2110 yield from super().specifiers(record
=record
)
2113 class PredicateBaseRM(BaseRM
):
2115 def predicate(CR
, mask
):
2118 (False, 0b001): "1<<r3",
2119 (False, 0b010): "r3",
2120 (False, 0b011): "~r3",
2121 (False, 0b100): "r10",
2122 (False, 0b101): "~r10",
2123 (False, 0b110): "r30",
2124 (False, 0b111): "~r30",
2126 (True, 0b000): "lt",
2127 (True, 0b001): "ge",
2128 (True, 0b010): "gt",
2129 (True, 0b011): "le",
2130 (True, 0b100): "eq",
2131 (True, 0b101): "ne",
2132 (True, 0b110): "so",
2133 (True, 0b111): "ns",
2136 def specifiers(self
, record
):
2137 # predication - single and twin
2138 # use "m=" if same otherwise sm/dm
2139 CR
= (int(self
.mmode
) == 1)
2140 mask
= int(self
.mask
)
2141 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
2142 if record
.svp64
.ptype
is _SVPType
.P2
:
2143 # LDST_IDX smask moving to extra322 but not straight away (False)
2144 if False and record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2145 smask
= int(self
.smask_extra332
)
2147 smask
= int(self
.smask
)
2148 sm
= PredicateBaseRM
.predicate(CR
, smask
)
2157 yield from super().specifiers(record
=record
)
2160 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
2164 class SEABaseRM(BaseRM
):
2165 def specifiers(self
, record
):
2169 yield from super().specifiers(record
=record
)
2172 class VLiBaseRM(BaseRM
):
2173 def specifiers(self
, record
):
2177 yield from super().specifiers(record
=record
)
2180 class NormalBaseRM(PredicateWidthBaseRM
):
2183 https://libre-soc.org/openpower/sv/normal/
2188 class NormalSimpleRM(ZZCombinedBaseRM
, NormalBaseRM
):
2189 """normal: simple mode"""
2193 def specifiers(self
, record
):
2194 yield from super().specifiers(record
=record
)
2197 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
2198 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
2202 class NormalFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, NormalBaseRM
):
2203 """normal: Rc=1: ffirst CR sel"""
2206 CR
: BaseRM
.mode
[3, 4]
2208 def specifiers(self
, record
):
2209 yield from super().specifiers(record
=record
, mode
="ff")
2212 class NormalFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
2213 """normal: Rc=0: ffirst z/nonz"""
2218 def specifiers(self
, record
):
2219 yield from super().specifiers(record
=record
, mode
="ff")
2222 class NormalSatRM(SatBaseRM
, ZZCombinedBaseRM
, NormalBaseRM
):
2223 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2229 class NormalRM(NormalBaseRM
):
2230 simple
: NormalSimpleRM
2232 ffrc1
: NormalFFRc1RM
2233 ffrc0
: NormalFFRc0RM
2237 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2239 LD/ST Immediate mode
2240 https://libre-soc.org/openpower/sv/ldst/
2245 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2246 """ld/st immediate: simple mode"""
2247 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2248 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2254 def specifiers(self
, record
):
2260 yield from super().specifiers(record
=record
)
2263 class LDSTFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2264 """ld/st immediate&indexed: Rc=1: ffirst CR sel"""
2267 CR
: BaseRM
.mode
[3, 4]
2269 def specifiers(self
, record
):
2270 yield from super().specifiers(record
=record
, mode
="ff")
2273 class LDSTFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2274 """ld/st immediate&indexed: Rc=0: ffirst z/nonz"""
2279 def specifiers(self
, record
):
2280 yield from super().specifiers(record
=record
, mode
="ff")
2283 class LDSTImmRM(LDSTImmBaseRM
):
2284 simple
: LDSTImmSimpleRM
2289 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2292 https://libre-soc.org/openpower/sv/ldst/
2297 class LDSTIdxSimpleRM(SEABaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2298 """ld/st index: simple mode (includes element-strided and Signed-EA)"""
2299 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2306 def specifiers(self
, record
):
2312 yield from super().specifiers(record
=record
)
2315 class LDSTIdxRM(LDSTIdxBaseRM
):
2316 simple
: LDSTIdxSimpleRM
2322 class CROpBaseRM(BaseRM
):
2325 https://libre-soc.org/openpower/sv/cr_ops/
2330 class CROpSimpleRM(PredicateBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2331 """crop: simple mode"""
2336 def specifiers(self
, record
):
2338 yield "rg" # simple CR Mode reports /rg
2340 yield from super().specifiers(record
=record
)
2343 class CROpMRRM(MRBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2344 """crop: scalar reduce mode (mapreduce)"""
2350 class CROpFF5RM(FFRc0BaseRM
, PredicateBaseRM
, VLiBaseRM
, DZBaseRM
,
2351 SZBaseRM
, CROpBaseRM
):
2352 """crop: ffirst 5-bit mode"""
2359 def specifiers(self
, record
):
2360 yield from super().specifiers(record
=record
, mode
="ff")
2363 # FIXME: almost everything in this class contradicts the specs (it doesn't)
2364 # The modes however are swapped: 5-bit is 3-bit, 3-bit is 5-bit
2365 class CROpFF3RM(FFRc1BaseRM
, PredicateBaseRM
, VLiBaseRM
, ZZBaseRM
, CROpBaseRM
):
2366 """cr_op: ffirst 3-bit mode"""
2372 def specifiers(self
, record
):
2373 yield from super().specifiers(record
=record
, mode
="ff")
2376 class CROpRM(CROpBaseRM
):
2377 simple
: CROpSimpleRM
2383 # ********************
2385 # https://libre-soc.org/openpower/sv/branches/
2386 class BranchBaseRM(BaseRM
):
2396 def specifiers(self
, record
):
2408 raise ValueError(self
.sz
)
2420 # Branch modes lack source mask.
2421 # Therefore a custom code is needed.
2422 CR
= (int(self
.mmode
) == 1)
2423 mask
= int(self
.mask
)
2424 m
= PredicateBaseRM
.predicate(CR
, mask
)
2428 yield from super().specifiers(record
=record
)
2431 class BranchSimpleRM(BranchBaseRM
):
2432 """branch: simple mode"""
2436 class BranchVLSRM(BranchBaseRM
):
2437 """branch: VLSET mode"""
2441 def specifiers(self
, record
):
2447 }[int(self
.VSb
), int(self
.VLi
)]
2449 yield from super().specifiers(record
=record
)
2452 class BranchCTRRM(BranchBaseRM
):
2453 """branch: CTR-test mode"""
2456 def specifiers(self
, record
):
2462 yield from super().specifiers(record
=record
)
2465 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2466 """branch: CTR-test+VLSET mode"""
2470 class BranchRM(BranchBaseRM
):
2471 simple
: BranchSimpleRM
2474 ctrvls
: BranchCTRVLSRM
2485 @_dataclasses.dataclass(eq
=True, frozen
=True)
2490 def match(cls
, desc
, record
):
2491 raise NotImplementedError()
2493 def validate(self
, others
):
2496 def assemble(self
, insn
):
2497 raise NotImplementedError()
2500 @_dataclasses.dataclass(eq
=True, frozen
=True)
2501 class SpecifierWidth(Specifier
):
2505 def match(cls
, desc
, record
, etalon
):
2506 (mode
, _
, value
) = desc
.partition("=")
2508 value
= value
.strip()
2511 width
= _SVP64Width(value
)
2513 return cls(record
=record
, width
=width
)
2516 @_dataclasses.dataclass(eq
=True, frozen
=True)
2517 class SpecifierW(SpecifierWidth
):
2519 def match(cls
, desc
, record
):
2520 return super().match(desc
=desc
, record
=record
, etalon
="w")
2522 def assemble(self
, insn
):
2523 selector
= insn
.select(record
=self
.record
)
2524 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2525 selector
.ewsrc
= self
.width
.value
2526 selector
.elwidth
= self
.width
.value
2529 @_dataclasses.dataclass(eq
=True, frozen
=True)
2530 class SpecifierSW(SpecifierWidth
):
2532 def match(cls
, desc
, record
):
2533 if record
.svp64
.mode
is _SVMode
.CROP
:
2535 return super().match(desc
=desc
, record
=record
, etalon
="sw")
2537 def assemble(self
, insn
):
2538 selector
= insn
.select(record
=self
.record
)
2539 selector
.ewsrc
= self
.width
.value
2542 @_dataclasses.dataclass(eq
=True, frozen
=True)
2543 class SpecifierDW(SpecifierWidth
):
2545 def match(cls
, desc
, record
):
2546 return super().match(desc
=desc
, record
=record
, etalon
="dw")
2548 def assemble(self
, insn
):
2549 selector
= insn
.select(record
=self
.record
)
2550 selector
.elwidth
= self
.width
.value
2553 @_dataclasses.dataclass(eq
=True, frozen
=True)
2554 class SpecifierSubVL(Specifier
):
2558 def match(cls
, desc
, record
):
2560 value
= _SVP64SubVL(desc
)
2564 return cls(record
=record
, value
=value
)
2566 def assemble(self
, insn
):
2567 selector
= insn
.select(record
=self
.record
)
2568 selector
.subvl
= int(self
.value
.value
)
2571 @_dataclasses.dataclass(eq
=True, frozen
=True)
2572 class SpecifierPredicate(Specifier
):
2577 def match(cls
, desc
, record
, mode_match
, pred_match
):
2578 (mode
, _
, pred
) = desc
.partition("=")
2581 if not mode_match(mode
):
2584 pred
= _SVP64Pred(pred
.strip())
2585 if not pred_match(pred
):
2586 raise ValueError(pred
)
2588 return cls(record
=record
, mode
=mode
, pred
=pred
)
2591 @_dataclasses.dataclass(eq
=True, frozen
=True)
2592 class SpecifierFF(SpecifierPredicate
):
2594 def match(cls
, desc
, record
):
2595 return super().match(desc
=desc
, record
=record
,
2596 mode_match
=lambda mode_arg
: mode_arg
== "ff",
2597 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2602 def assemble(self
, insn
):
2603 selector
= insn
.select(record
=self
.record
)
2604 if selector
.mode
.sel
!= 0:
2605 raise ValueError("cannot override mode")
2606 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2607 selector
.mode
.sel
= 0b01
2608 # HACK: please finally provide correct logic for CRs.
2609 if self
.pred
in (_SVP64Pred
.RC1
, _SVP64Pred
.RC1_N
):
2610 selector
.mode
[2] = (self
.pred
is _SVP64Pred
.RC1_N
)
2612 selector
.mode
[2] = self
.pred
.inv
2613 selector
.mode
[3, 4] = self
.pred
.state
2615 selector
.mode
.sel
= 0b01 if self
.mode
== "ff" else 0b11
2616 selector
.inv
= self
.pred
.inv
2618 selector
.CR
= self
.pred
.state
2620 selector
.RC1
= self
.pred
.state
2623 @_dataclasses.dataclass(eq
=True, frozen
=True)
2624 class SpecifierMask(SpecifierPredicate
):
2626 def match(cls
, desc
, record
, mode
):
2627 return super().match(desc
=desc
, record
=record
,
2628 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2629 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2634 def assemble(self
, insn
):
2635 raise NotImplementedError()
2638 @_dataclasses.dataclass(eq
=True, frozen
=True)
2639 class SpecifierM(SpecifierMask
):
2641 def match(cls
, desc
, record
):
2642 return super().match(desc
=desc
, record
=record
, mode
="m")
2644 def validate(self
, others
):
2646 if isinstance(spec
, SpecifierSM
):
2647 raise ValueError("source-mask and predicate mask conflict")
2648 elif isinstance(spec
, SpecifierDM
):
2649 raise ValueError("dest-mask and predicate mask conflict")
2651 def assemble(self
, insn
):
2652 selector
= insn
.select(record
=self
.record
)
2653 selector
.mask
= int(self
.pred
)
2654 if ((self
.record
.ptype
is _SVPType
.P2
) and
2655 (self
.record
.svp64
.mode
is not _SVMode
.BRANCH
)):
2656 selector
.smask
= int(self
.pred
)
2657 # LDST_IDX smask moving to extra322 but not straight away (False)
2658 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2659 selector
.smask_extra332
= int(self
.pred
)
2661 selector
.smask
= int(self
.pred
)
2663 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2666 @_dataclasses.dataclass(eq
=True, frozen
=True)
2667 class SpecifierSM(SpecifierMask
):
2669 def match(cls
, desc
, record
):
2670 return super().match(desc
=desc
, record
=record
, mode
="sm")
2672 def validate(self
, others
):
2673 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2674 raise ValueError("source-mask on non-twin predicate")
2676 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2679 if isinstance(spec
, SpecifierDM
):
2683 raise ValueError("missing dest-mask in CR twin predication")
2684 if self
.pred
.mode
!= twin
.pred
.mode
:
2685 raise ValueError(f
"predicate masks mismatch: "
2686 f
"{self.pred!r} vs {twin.pred!r}")
2688 def assemble(self
, insn
):
2689 selector
= insn
.select(record
=self
.record
)
2690 # LDST_IDX smask moving to extra322 but not straight away (False)
2691 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2692 selector
.smask_extra332
= int(self
.pred
)
2694 selector
.smask
= int(self
.pred
)
2695 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2698 @_dataclasses.dataclass(eq
=True, frozen
=True)
2699 class SpecifierDM(SpecifierMask
):
2701 def match(cls
, desc
, record
):
2702 return super().match(desc
=desc
, record
=record
, mode
="dm")
2704 def validate(self
, others
):
2705 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2706 raise ValueError("dest-mask on non-twin predicate")
2708 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2711 if isinstance(spec
, SpecifierSM
):
2715 raise ValueError("missing source-mask in CR twin predication")
2716 if self
.pred
.mode
!= twin
.pred
.mode
:
2717 raise ValueError(f
"predicate masks mismatch: "
2718 f
"{self.pred!r} vs {twin.pred!r}")
2720 def assemble(self
, insn
):
2721 selector
= insn
.select(record
=self
.record
)
2722 selector
.mask
= int(self
.pred
)
2723 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2726 @_dataclasses.dataclass(eq
=True, frozen
=True)
2727 class SpecifierZZ(Specifier
):
2729 def match(cls
, desc
, record
):
2733 return cls(record
=record
)
2735 def validate(self
, others
):
2737 # Since zz takes precedence (overrides) sz and dz,
2738 # treat them as mutually exclusive.
2739 if isinstance(spec
, (SpecifierSZ
, SpecifierDZ
)):
2740 raise ValueError("mutually exclusive predicate masks")
2742 def assemble(self
, insn
):
2743 selector
= insn
.select(record
=self
.record
)
2744 if hasattr(selector
, "zz"): # this should be done in a different way
2751 @_dataclasses.dataclass(eq
=True, frozen
=True)
2752 class SpecifierXZ(Specifier
):
2754 hint
: str = _dataclasses
.field(repr=False)
2757 def match(cls
, desc
, record
, etalon
, hint
):
2761 return cls(desc
=desc
, record
=record
, hint
=hint
)
2763 def validate(self
, others
):
2764 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2765 raise ValueError(f
"{self.hint} on non-twin predicate")
2767 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2770 if isinstance(spec
, SpecifierXZ
):
2774 raise ValueError(f
"missing {self.hint} in CR twin predication")
2775 if self
.pred
!= twin
.pred
:
2776 raise ValueError(f
"predicate masks mismatch: "
2777 f
"{self.pred!r} vs {twin.pred!r}")
2779 def assemble(self
, insn
):
2780 selector
= insn
.select(record
=self
.record
)
2781 setattr(selector
, self
.desc
, 1)
2784 @_dataclasses.dataclass(eq
=True, frozen
=True)
2785 class SpecifierSZ(SpecifierXZ
):
2787 def match(cls
, desc
, record
):
2788 return super().match(desc
=desc
, record
=record
,
2789 etalon
="sz", hint
="source-mask")
2791 def validate(self
, others
):
2793 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2794 if isinstance(spec
, SpecifierFF
):
2795 raise ValueError("source-zero not allowed in ff mode")
2798 @_dataclasses.dataclass(eq
=True, frozen
=True)
2799 class SpecifierDZ(SpecifierXZ
):
2801 def match(cls
, desc
, record
):
2802 return super().match(desc
=desc
, record
=record
,
2803 etalon
="dz", hint
="dest-mask")
2805 def validate(self
, others
):
2807 if ((self
.record
.svp64
.mode
is not _SVMode
.CROP
) and
2808 isinstance(spec
, SpecifierFF
) and
2809 (spec
.pred
.mode
is _SVP64PredMode
.RC1
)):
2810 raise ValueError(f
"dest-zero not allowed in ff mode BO")
2813 @_dataclasses.dataclass(eq
=True, frozen
=True)
2814 class SpecifierEls(Specifier
):
2816 def match(cls
, desc
, record
):
2820 if record
.svp64
.mode
not in (_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
):
2821 raise ValueError("els is only valid in ld/st modes, not "
2822 "%s" % str(self
.record
.svp64
.mode
))
2824 return cls(record
=record
)
2826 def assemble(self
, insn
):
2827 if self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
: # stride mode
2828 insn
.prefix
.rm
.mode
[1] = 0
2830 selector
= insn
.select(record
=self
.record
)
2835 @_dataclasses.dataclass(eq
=True, frozen
=True)
2836 class SpecifierSEA(Specifier
):
2838 def match(cls
, desc
, record
):
2842 return cls(record
=record
)
2844 def validate(self
, others
):
2845 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
:
2846 raise ValueError("sea is only valid in ld/st modes, not "
2847 "%s" % str(self
.record
.svp64
.mode
))
2850 if isinstance(spec
, SpecifierFF
):
2851 raise ValueError(f
"sea cannot be used in ff mode")
2853 def assemble(self
, insn
):
2854 selector
= insn
.select(record
=self
.record
)
2855 if selector
.mode
.sel
not in (0b10, 0b00):
2856 raise ValueError("sea is only valid for normal and els modes, "
2857 "not %d" % int(selector
.mode
.sel
))
2861 @_dataclasses.dataclass(eq
=True, frozen
=True)
2862 class SpecifierSat(Specifier
):
2867 def match(cls
, desc
, record
, etalon
, sign
):
2871 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.LDST_IMM
,
2873 raise ValueError("only normal, ld/st imm and "
2874 "ld/st idx modes supported")
2876 return cls(record
=record
, desc
=desc
, sign
=sign
)
2878 def assemble(self
, insn
):
2879 selector
= insn
.select(record
=self
.record
)
2880 selector
.mode
[0] = 0b1
2881 selector
.mode
[1] = 0b0
2882 selector
.N
= int(self
.sign
)
2885 @_dataclasses.dataclass(eq
=True, frozen
=True)
2886 class SpecifierSatS(SpecifierSat
):
2888 def match(cls
, desc
, record
):
2889 return super().match(desc
=desc
, record
=record
,
2890 etalon
="sats", sign
=True)
2893 @_dataclasses.dataclass(eq
=True, frozen
=True)
2894 class SpecifierSatU(SpecifierSat
):
2896 def match(cls
, desc
, record
):
2897 return super().match(desc
=desc
, record
=record
,
2898 etalon
="satu", sign
=False)
2901 @_dataclasses.dataclass(eq
=True, frozen
=True)
2902 class SpecifierMapReduce(Specifier
):
2906 def match(cls
, record
, RG
):
2907 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2908 raise ValueError("only normal and crop modes supported")
2910 return cls(record
=record
, RG
=RG
)
2912 def assemble(self
, insn
):
2913 selector
= insn
.select(record
=self
.record
)
2914 if self
.record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2915 raise ValueError("only normal and crop modes supported")
2916 selector
.mode
[0] = 0
2917 selector
.mode
[1] = 0
2918 selector
.mode
[2] = 1
2919 selector
.RG
= self
.RG
2922 @_dataclasses.dataclass(eq
=True, frozen
=True)
2923 class SpecifierMR(SpecifierMapReduce
):
2925 def match(cls
, desc
, record
):
2929 return super().match(record
=record
, RG
=False)
2932 @_dataclasses.dataclass(eq
=True, frozen
=True)
2933 class SpecifierMRR(SpecifierMapReduce
):
2935 def match(cls
, desc
, record
):
2939 return super().match(record
=record
, RG
=True)
2942 @_dataclasses.dataclass(eq
=True, frozen
=True)
2943 class SpecifierBranch(Specifier
):
2945 def match(cls
, desc
, record
, etalon
):
2949 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
2950 raise ValueError("only branch modes supported")
2952 return cls(record
=record
)
2955 @_dataclasses.dataclass(eq
=True, frozen
=True)
2956 class SpecifierAll(SpecifierBranch
):
2958 def match(cls
, desc
, record
):
2959 return super().match(desc
=desc
, record
=record
, etalon
="all")
2961 def assemble(self
, insn
):
2962 selector
= insn
.select(record
=self
.record
)
2966 @_dataclasses.dataclass(eq
=True, frozen
=True)
2967 class SpecifierSNZ(Specifier
):
2969 def match(cls
, desc
, record
):
2973 if record
.svp64
.mode
not in (_SVMode
.BRANCH
, _SVMode
.CROP
):
2974 raise ValueError("only branch and crop modes supported")
2976 return cls(record
=record
)
2978 def assemble(self
, insn
):
2979 selector
= insn
.select(record
=self
.record
)
2980 if self
.record
.svp64
.mode
in (_SVMode
.CROP
, _SVMode
.BRANCH
):
2982 if self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
2985 raise ValueError("only branch and crop modes supported")
2988 @_dataclasses.dataclass(eq
=True, frozen
=True)
2989 class SpecifierSL(SpecifierBranch
):
2991 def match(cls
, desc
, record
):
2992 return super().match(desc
=desc
, record
=record
, etalon
="sl")
2994 def assemble(self
, insn
):
2995 selector
= insn
.select(record
=self
.record
)
2999 @_dataclasses.dataclass(eq
=True, frozen
=True)
3000 class SpecifierSLu(SpecifierBranch
):
3002 def match(cls
, desc
, record
):
3003 return super().match(desc
=desc
, record
=record
, etalon
="slu")
3005 def assemble(self
, insn
):
3006 selector
= insn
.select(record
=self
.record
)
3010 @_dataclasses.dataclass(eq
=True, frozen
=True)
3011 class SpecifierLRu(SpecifierBranch
):
3013 def match(cls
, desc
, record
):
3014 return super().match(desc
=desc
, record
=record
, etalon
="lru")
3016 def assemble(self
, insn
):
3017 selector
= insn
.select(record
=self
.record
)
3021 @_dataclasses.dataclass(eq
=True, frozen
=True)
3022 class SpecifierVSXX(SpecifierBranch
):
3027 def match(cls
, desc
, record
, etalon
, VSb
, VLi
):
3031 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3032 raise ValueError("only branch modes supported")
3034 return cls(record
=record
, VSb
=VSb
, VLi
=VLi
)
3036 def assemble(self
, insn
):
3037 selector
= insn
.select(record
=self
.record
)
3039 selector
.VSb
= int(self
.VSb
)
3040 selector
.VLi
= int(self
.VLi
)
3043 @_dataclasses.dataclass(eq
=True, frozen
=True)
3044 class SpecifierVS(SpecifierVSXX
):
3046 def match(cls
, desc
, record
):
3047 return super().match(desc
=desc
, record
=record
,
3048 etalon
="vs", VSb
=False, VLi
=False)
3051 @_dataclasses.dataclass(eq
=True, frozen
=True)
3052 class SpecifierVSi(SpecifierVSXX
):
3054 def match(cls
, desc
, record
):
3055 return super().match(desc
=desc
, record
=record
,
3056 etalon
="vsi", VSb
=False, VLi
=True)
3059 @_dataclasses.dataclass(eq
=True, frozen
=True)
3060 class SpecifierVSb(SpecifierVSXX
):
3062 def match(cls
, desc
, record
):
3063 return super().match(desc
=desc
, record
=record
,
3064 etalon
="vsb", VSb
=True, VLi
=False)
3067 @_dataclasses.dataclass(eq
=True, frozen
=True)
3068 class SpecifierVSbi(SpecifierVSXX
):
3070 def match(cls
, desc
, record
):
3071 return super().match(desc
=desc
, record
=record
,
3072 etalon
="vsbi", VSb
=True, VLi
=True)
3075 @_dataclasses.dataclass(eq
=True, frozen
=True)
3076 class SpecifierCTX(Specifier
):
3080 def match(cls
, desc
, record
, etalon
, CTi
):
3084 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3085 raise ValueError("only branch modes supported")
3087 return cls(record
=record
, CTi
=CTi
)
3089 def assemble(self
, insn
):
3090 selector
= insn
.select(record
=self
.record
)
3092 selector
.CTi
= int(self
.CTi
)
3095 @_dataclasses.dataclass(eq
=True, frozen
=True)
3096 class SpecifierCTR(SpecifierCTX
):
3098 def match(cls
, desc
, record
):
3099 return super().match(desc
=desc
, record
=record
,
3100 etalon
="ctr", CTi
=False)
3103 @_dataclasses.dataclass(eq
=True, frozen
=True)
3104 class SpecifierCTi(SpecifierCTX
):
3106 def match(cls
, desc
, record
):
3107 return super().match(desc
=desc
, record
=record
,
3108 etalon
="cti", CTi
=True)
3111 @_dataclasses.dataclass(eq
=True, frozen
=True)
3112 class SpecifierPI(Specifier
):
3114 def match(cls
, desc
, record
):
3118 if record
.svp64
.mode
not in [_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
]:
3119 raise ValueError("only ld/st imm/idx mode supported")
3121 return cls(record
=record
)
3123 def assemble(self
, insn
):
3124 selector
= insn
.select(record
=self
.record
)
3125 selector
.mode
[2] = 0b1
3129 @_dataclasses.dataclass(eq
=True, frozen
=True)
3130 class SpecifierLF(Specifier
):
3132 def match(cls
, desc
, record
):
3136 if record
.svp64
.mode
is not _SVMode
.LDST_IMM
:
3137 raise ValueError("only ld/st imm mode supported")
3139 return cls(record
=record
)
3141 def assemble(self
, insn
):
3142 selector
= insn
.select(record
=self
.record
)
3143 selector
.mode
[1] = 0
3147 @_dataclasses.dataclass(eq
=True, frozen
=True)
3148 class SpecifierVLi(Specifier
):
3150 def match(cls
, desc
, record
):
3154 return cls(record
=record
)
3156 def validate(self
, others
):
3158 if isinstance(spec
, SpecifierFF
):
3161 raise ValueError("VLi only allowed in failfirst")
3163 def assemble(self
, insn
):
3164 selector
= insn
.select(record
=self
.record
)
3165 selector
.mode
[1] = 1
3169 class Specifiers(tuple):
3204 def __new__(cls
, items
, record
):
3205 def transform(item
):
3206 for spec_cls
in cls
.SPECS
:
3207 spec
= spec_cls
.match(item
, record
=record
)
3208 if spec
is not None:
3210 raise ValueError(item
)
3212 # TODO: remove this hack
3213 items
= dict.fromkeys(items
)
3217 items
= tuple(items
)
3219 specs
= tuple(map(transform
, items
))
3220 for (index
, spec
) in enumerate(specs
):
3221 head
= specs
[:index
]
3222 tail
= specs
[index
+ 1:]
3223 spec
.validate(others
=(head
+ tail
))
3225 return super().__new
__(cls
, specs
)
3228 class SVP64OperandMeta(type):
3229 class SVP64NonZeroOperand(NonZeroOperand
):
3230 def assemble(self
, insn
, value
):
3231 if isinstance(value
, str):
3232 value
= int(value
, 0)
3233 if not isinstance(value
, int):
3234 raise ValueError("non-integer operand")
3236 # FIXME: this is really weird
3237 if self
.record
.name
in ("svstep", "svstep."):
3238 value
+= 1 # compensation
3240 return super().assemble(value
=value
, insn
=insn
)
3242 class SVP64XOStaticOperand(SpanStaticOperand
):
3243 def __init__(self
, record
, value
, span
):
3244 return super().__init
__(record
=record
, name
="XO",
3245 value
=value
, span
=span
)
3248 NonZeroOperand
: SVP64NonZeroOperand
,
3249 XOStaticOperand
: SVP64XOStaticOperand
,
3252 def __new__(metacls
, name
, bases
, ns
):
3254 for (index
, base_cls
) in enumerate(bases
):
3255 bases
[index
] = metacls
.__TRANSFORM
.get(base_cls
, base_cls
)
3257 bases
= tuple(bases
)
3259 return super().__new
__(metacls
, name
, bases
, ns
)
3262 class SVP64Operand(Operand
, metaclass
=SVP64OperandMeta
):
3265 return tuple(map(lambda bit
: (bit
+ 32), super().span
))
3269 def __init__(self
, insn
, record
):
3271 self
.__record
= record
3272 return super().__init
__()
3275 return self
.rm
.__doc
__
3278 return repr(self
.rm
)
3286 return self
.__record
3290 rm
= getattr(self
.insn
.prefix
.rm
, self
.record
.svp64
.mode
.name
.lower())
3292 # The idea behind these tables is that they are now literally
3293 # in identical format to insndb.csv and minor_xx.csv and can
3294 # be done precisely as that. The only thing to watch out for
3295 # is the insertion of Rc=1 as a "mask/value" bit and likewise
3296 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
3299 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
3300 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3301 # mode Rc mask Rc member
3303 (0b000000, 0b111000, "simple"), # simple (no Rc)
3304 (0b001000, 0b111100, "mr"), # mapreduce (no Rc)
3305 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3306 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3307 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3308 (0b001100, 0b111100, "rsvd"), # reserved
3310 mode
= int(self
.insn
.prefix
.rm
.normal
.mode
)
3311 search
= ((mode
<< 1) | self
.record
.Rc
)
3313 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
3314 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3315 # mode Rc mask Rc member
3316 # ironically/coincidentally this table is identical to NORMAL
3317 # mode except reserved in place of mr
3319 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3320 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3321 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3323 search
= ((int(self
.insn
.prefix
.rm
.ldst_imm
.mode
) << 1) |
3326 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
3327 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3328 # mode Rc mask Rc member
3330 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3331 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3332 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3334 search
= ((int(self
.insn
.prefix
.rm
.ldst_idx
.mode
) << 1) |
3337 elif self
.record
.svp64
.mode
is _SVMode
.CROP
:
3338 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
3339 # mode 3b mask 3b member
3341 (0b000000, 0b111000, "simple"), # simple
3342 (0b001000, 0b111000, "mr"), # mapreduce
3343 (0b010001, 0b010001, "ff3"), # ffirst, 3-bit CR
3344 (0b010000, 0b010000, "ff5"), # ffirst, 5-bit CR
3346 search
= ((int(self
.insn
.prefix
.rm
.crop
.mode
) << 1) |
3347 int(self
.record
.svp64
.extra_CR_3bit
))
3349 elif self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3353 (0b00, 0b11, "simple"), # simple
3354 (0b01, 0b11, "vls"), # VLset
3355 (0b10, 0b11, "ctr"), # CTR mode
3356 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
3358 # slightly weird: doesn't have a 5-bit "mode" field like others
3359 search
= int(self
.insn
.prefix
.rm
.branch
.mode
.sel
)
3362 if table
is not None:
3363 for (value
, mask
, field
) in table
:
3364 if field
.startswith("rsvd"):
3366 if ((value
& mask
) == (search
& mask
)):
3367 return getattr(rm
, field
)
3371 def __getattr__(self
, key
):
3372 if key
.startswith(f
"_{self.__class__.__name__}__"):
3373 return super().__getattribute
__(key
)
3375 return getattr(self
.rm
, key
)
3377 def __setattr__(self
, key
, value
):
3378 if key
.startswith(f
"_{self.__class__.__name__}__"):
3379 return super().__setattr
__(key
, value
)
3382 if not hasattr(rm
, key
):
3383 raise AttributeError(key
)
3385 return setattr(rm
, key
, value
)
3388 class SVP64Instruction(PrefixedInstruction
):
3389 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
3390 class Prefix(PrefixedInstruction
.Prefix
):
3392 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
3396 def select(self
, record
):
3397 return RMSelector(insn
=self
, record
=record
)
3402 for idx
in range(64):
3403 bit
= int(self
[idx
])
3405 return "".join(map(str, bits
))
3408 def assemble(cls
, record
, arguments
=None, specifiers
=None):
3409 insn
= super().assemble(record
=record
, arguments
=arguments
)
3411 specifiers
= Specifiers(items
=specifiers
, record
=record
)
3412 for specifier
in specifiers
:
3413 specifier
.assemble(insn
=insn
)
3415 insn
.prefix
.PO
= 0x1
3416 insn
.prefix
.id = 0x3
3420 def disassemble(self
, record
,
3422 style
=Style
.NORMAL
):
3424 if style
<= Style
.SHORT
:
3427 blob
= insn
.bytes(byteorder
=byteorder
)
3428 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
3431 blob_prefix
= blob(self
.prefix
)
3432 blob_suffix
= blob(self
.suffix
)
3434 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3435 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
3438 assert record
.svp64
is not None
3440 name
= f
"sv.{record.name}"
3442 rm
= self
.select(record
=record
)
3444 # convert specifiers to /x/y/z (sorted lexicographically)
3445 specifiers
= sorted(rm
.specifiers(record
=record
))
3446 if specifiers
: # if any add one extra to get the extra "/"
3447 specifiers
= ([""] + specifiers
)
3448 specifiers
= "/".join(specifiers
)
3450 # convert operands to " ,x,y,z"
3451 operands
= tuple(map(_operator
.itemgetter(1),
3452 self
.spec_dynamic_operands(record
=record
, style
=style
)))
3453 operands
= ",".join(operands
)
3454 if len(operands
) > 0: # if any separate with a space
3455 operands
= (" " + operands
)
3457 if style
<= Style
.LEGACY
:
3458 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3459 suffix
= WordInstruction
.integer(value
=int(self
.suffix
))
3460 yield from suffix
.disassemble(record
=record
,
3461 byteorder
=byteorder
, style
=style
)
3463 yield f
"{blob_prefix}{name}{specifiers}{operands}"
3465 yield f
"{blob_suffix}"
3467 if style
>= Style
.VERBOSE
:
3469 binary
= self
.binary
3470 spec
= self
.spec(record
=record
, prefix
="sv.")
3472 yield f
"{indent}spec"
3473 yield f
"{indent}{indent}{spec}"
3474 yield f
"{indent}pcode"
3475 for stmt
in record
.mdwn
.pcode
:
3476 yield f
"{indent}{indent}{stmt}"
3477 yield f
"{indent}binary"
3478 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
3479 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
3480 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
3481 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
3482 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
3483 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
3484 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
3485 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
3486 yield f
"{indent}opcodes"
3487 for opcode
in record
.opcodes
:
3488 yield f
"{indent}{indent}{opcode!r}"
3489 for operand
in self
.operands(record
=record
):
3490 yield from operand
.disassemble(insn
=self
,
3491 style
=style
, indent
=indent
)
3493 yield f
"{indent}{indent}{str(rm)}"
3494 for line
in rm
.disassemble(style
=style
):
3495 yield f
"{indent}{indent}{line}"
3499 def operands(cls
, record
):
3500 for operand
in super().operands(record
=record
):
3501 parent
= operand
.__class
__
3502 name
= f
"SVP64{parent.__name__}"
3503 bases
= (SVP64Operand
, parent
)
3504 child
= type(name
, bases
, {})
3505 yield child(**dict(operand
))
3508 def parse(stream
, factory
):
3510 return ("TODO" not in frozenset(entry
.values()))
3512 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
3513 entries
= _csv
.DictReader(lines
)
3514 entries
= filter(match
, entries
)
3515 return tuple(map(factory
, entries
))
3518 class MarkdownDatabase
:
3521 for (name
, desc
) in _ISA():
3524 (dynamic
, *static
) = desc
.regs
3525 operands
.extend(dynamic
)
3526 operands
.extend(static
)
3527 pcode
= PCode(filter(str.strip
, desc
.pcode
))
3528 operands
= Operands(insn
=name
, operands
=operands
)
3529 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
3531 self
.__db
= dict(sorted(db
.items()))
3533 return super().__init
__()
3536 yield from self
.__db
.items()
3538 def __contains__(self
, key
):
3539 return self
.__db
.__contains
__(key
)
3541 def __getitem__(self
, key
):
3542 return self
.__db
.__getitem
__(key
)
3545 class FieldsDatabase
:
3548 df
= _DecodeFields()
3550 for (form
, fields
) in df
.instrs
.items():
3551 if form
in {"DQE", "TX"}:
3555 db
[_Form
[form
]] = Fields(fields
)
3559 return super().__init
__()
3561 def __getitem__(self
, key
):
3562 return self
.__db
.__getitem
__(key
)
3566 def __init__(self
, root
, mdwndb
):
3567 # The code below groups the instructions by name:section.
3568 # There can be multiple names for the same instruction.
3569 # The point is to capture different opcodes for the same instruction.
3571 records
= _collections
.defaultdict(set)
3572 path
= (root
/ "insndb.csv")
3573 with
open(path
, "r", encoding
="UTF-8") as stream
:
3574 for section
in sorted(parse(stream
, Section
.CSV
)):
3575 path
= (root
/ section
.csv
)
3577 section
.Mode
.INTEGER
: IntegerOpcode
,
3578 section
.Mode
.PATTERN
: PatternOpcode
,
3580 factory
= _functools
.partial(PPCRecord
.CSV
,
3581 opcode_cls
=opcode_cls
)
3582 with
open(path
, "r", encoding
="UTF-8") as stream
:
3583 for insn
in parse(stream
, factory
):
3584 for name
in insn
.names
:
3585 records
[name
].add(insn
)
3586 sections
[name
] = section
3588 items
= sorted(records
.items())
3590 for (name
, multirecord
) in items
:
3591 records
[name
] = PPCMultiRecord(sorted(multirecord
))
3593 def exact_match(name
):
3594 record
= records
.get(name
)
3600 if not name
.endswith("l"):
3602 alias
= exact_match(name
[:-1])
3605 record
= records
[alias
]
3606 if "lk" not in record
.flags
:
3607 raise ValueError(record
)
3611 if not name
.endswith("a"):
3613 alias
= LK_match(name
[:-1])
3616 record
= records
[alias
]
3617 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
3618 raise ValueError(record
)
3619 if "AA" not in mdwndb
[name
].operands
:
3620 raise ValueError(record
)
3624 if not name
.endswith("."):
3626 alias
= exact_match(name
[:-1])
3629 record
= records
[alias
]
3630 if record
.Rc
is _RCOE
.NONE
:
3631 raise ValueError(record
)
3635 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
3636 for (name
, _
) in mdwndb
:
3637 if name
.startswith("sv."):
3640 for match
in matches
:
3642 if alias
is not None:
3646 section
= sections
[alias
]
3647 record
= records
[alias
]
3648 db
[name
] = (section
, record
)
3650 self
.__db
= dict(sorted(db
.items()))
3652 return super().__init
__()
3654 @_functools.lru_cache(maxsize
=512, typed
=False)
3655 def __getitem__(self
, key
):
3656 return self
.__db
.get(key
, (None, None))
3659 class SVP64Database
:
3660 def __init__(self
, root
, ppcdb
):
3662 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
3663 for (prefix
, _
, names
) in _os
.walk(root
):
3664 prefix
= _pathlib
.Path(prefix
)
3665 for name
in filter(lambda name
: pattern
.match(name
), names
):
3666 path
= (prefix
/ _pathlib
.Path(name
))
3667 with
open(path
, "r", encoding
="UTF-8") as stream
:
3668 db
.update(parse(stream
, SVP64Record
.CSV
))
3669 db
= {record
.name
:record
for record
in db
}
3671 self
.__db
= dict(sorted(db
.items()))
3672 self
.__ppcdb
= ppcdb
3674 return super().__init
__()
3676 def __getitem__(self
, key
):
3677 (_
, record
) = self
.__ppcdb
[key
]
3681 for name
in record
.names
:
3682 record
= self
.__db
.get(name
, None)
3683 if record
is not None:
3689 class Records(tuple):
3690 def __new__(cls
, records
):
3691 return super().__new
__(cls
, sorted(records
))
3695 def __init__(self
, root
):
3696 root
= _pathlib
.Path(root
)
3697 mdwndb
= MarkdownDatabase()
3698 fieldsdb
= FieldsDatabase()
3699 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
3700 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
3704 opcodes
= _collections
.defaultdict(
3705 lambda: _collections
.defaultdict(set))
3707 for (name
, mdwn
) in mdwndb
:
3708 if name
.startswith("sv."):
3710 (section
, ppc
) = ppcdb
[name
]
3713 svp64
= svp64db
[name
]
3714 fields
= fieldsdb
[ppc
.form
]
3715 record
= Record(name
=name
,
3716 section
=section
, ppc
=ppc
, svp64
=svp64
,
3717 mdwn
=mdwn
, fields
=fields
)
3719 names
[record
.name
] = record
3720 opcodes
[section
][record
.PO
].add(record
)
3722 self
.__db
= Records(db
)
3723 self
.__names
= dict(sorted(names
.items()))
3724 self
.__opcodes
= dict(sorted(opcodes
.items()))
3726 return super().__init
__()
3729 return repr(self
.__db
)
3732 yield from self
.__db
3734 @_functools.lru_cache(maxsize
=None)
3735 def __contains__(self
, key
):
3736 return self
.__getitem
__(key
) is not None
3738 @_functools.lru_cache(maxsize
=None)
3739 def __getitem__(self
, key
):
3740 if isinstance(key
, SVP64Instruction
):
3743 if isinstance(key
, Instruction
):
3746 sections
= sorted(self
.__opcodes
)
3747 for section
in sections
:
3748 group
= self
.__opcodes
[section
]
3749 for record
in group
[PO
]:
3750 if record
.match(key
=key
):
3755 elif isinstance(key
, str):
3756 return self
.__names
.get(key
)
3758 raise ValueError("instruction or name expected")
3761 class Walker(mdis
.walker
.Walker
):
3762 @mdis.dispatcher
.Hook(Database
)
3763 def dispatch_database(self
, node
):
3764 yield from self(tuple(node
))