1 import collections
as _collections
3 import dataclasses
as _dataclasses
5 import functools
as _functools
7 import operator
as _operator
8 import pathlib
as _pathlib
13 from functools
import cached_property
15 from cached_property
import cached_property
17 from openpower
.decoder
.power_enums
import (
18 Function
as _Function
,
25 CRIn2Sel
as _CRIn2Sel
,
26 CROutSel
as _CROutSel
,
28 LDSTMode
as _LDSTMode
,
33 SVMaskSrc
as _SVMaskSrc
,
38 SVP64RMMode
as _SVP64RMMode
,
39 SVExtraRegType
as _SVExtraRegType
,
40 SVExtraReg
as _SVExtraReg
,
41 SVP64SubVL
as _SVP64SubVL
,
42 SVP64Pred
as _SVP64Pred
,
43 SVP64PredMode
as _SVP64PredMode
,
44 SVP64Width
as _SVP64Width
,
46 from openpower
.decoder
.selectable_int
import (
47 SelectableInt
as _SelectableInt
,
48 selectconcat
as _selectconcat
,
50 from openpower
.decoder
.power_fields
import (
53 DecodeFields
as _DecodeFields
,
55 from openpower
.decoder
.pseudo
.pagereader
import ISA
as _ISA
58 @_functools.total_ordering
59 class Style(_enum
.Enum
):
63 VERBOSE
= _enum
.auto()
65 def __lt__(self
, other
):
66 if not isinstance(other
, self
.__class
__):
68 return (self
.value
< other
.value
)
71 @_functools.total_ordering
72 class Priority(_enum
.Enum
):
78 def _missing_(cls
, value
):
79 if isinstance(value
, str):
84 return super()._missing
_(value
)
86 def __lt__(self
, other
):
87 if not isinstance(other
, self
.__class
__):
90 # NOTE: the order is inversed, LOW < NORMAL < HIGH
91 return (self
.value
> other
.value
)
94 def dataclass(cls
, record
, keymap
=None, typemap
=None):
98 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
100 def transform(key_value
):
101 (key
, value
) = key_value
102 key
= keymap
.get(key
, key
)
103 hook
= typemap
.get(key
, lambda value
: value
)
104 if hook
is bool and value
in ("", "0"):
110 record
= dict(map(transform
, record
.items()))
111 for key
in frozenset(record
.keys()):
112 if record
[key
] == "":
118 @_functools.total_ordering
119 @_dataclasses.dataclass(eq
=True, frozen
=True)
122 def __new__(cls
, value
):
123 if isinstance(value
, str):
124 value
= int(value
, 0)
125 if not isinstance(value
, int):
126 raise ValueError(value
)
128 if value
.bit_length() > 64:
129 raise ValueError(value
)
131 return super().__new
__(cls
, value
)
134 return self
.__repr
__()
137 return f
"{self:0{self.bit_length()}b}"
139 def bit_length(self
):
140 if super().bit_length() > 32:
144 class Value(Integer
):
153 def __lt__(self
, other
):
154 if not isinstance(other
, Opcode
):
155 return NotImplemented
156 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
159 return (self
.value
& self
.mask
)
162 return int(self
).__index
__()
165 def pattern(value
, mask
, bit_length
):
166 for bit
in range(bit_length
):
167 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
169 elif (value
& (1 << (bit_length
- bit
- 1))):
174 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
176 def match(self
, key
):
177 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
180 @_functools.total_ordering
181 @_dataclasses.dataclass(eq
=True, frozen
=True)
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 @_dataclasses.dataclass(eq
=True, frozen
=True)
197 class PatternOpcode(Opcode
):
198 def __init__(self
, pattern
):
199 if not isinstance(pattern
, str):
200 raise ValueError(pattern
)
202 (value
, mask
) = (0, 0)
203 for symbol
in pattern
:
204 if symbol
not in {"0", "1", "-"}:
205 raise ValueError(pattern
)
206 value |
= (symbol
== "1")
207 mask |
= (symbol
!= "-")
213 value
= Opcode
.Value(value
)
214 mask
= Opcode
.Mask(mask
)
216 return super().__init
__(value
=value
, mask
=mask
)
219 @_dataclasses.dataclass(eq
=True, frozen
=True)
221 class FlagsMeta(type):
236 class Flags(tuple, metaclass
=FlagsMeta
):
237 def __new__(cls
, flags
=frozenset()):
238 flags
= frozenset(flags
)
239 diff
= (flags
- frozenset(cls
))
241 raise ValueError(flags
)
242 return super().__new
__(cls
, sorted(flags
))
246 flags
: Flags
= Flags()
248 function
: _Function
= _Function
.NONE
249 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
250 in1
: _In1Sel
= _In1Sel
.NONE
251 in2
: _In2Sel
= _In2Sel
.NONE
252 in3
: _In3Sel
= _In3Sel
.NONE
253 out
: _OutSel
= _OutSel
.NONE
254 cr_in
: _CRInSel
= _CRInSel
.NONE
255 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
256 cr_out
: _CROutSel
= _CROutSel
.NONE
257 cry_in
: _CryIn
= _CryIn
.ZERO
258 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
259 upd
: _LDSTMode
= _LDSTMode
.NONE
260 Rc
: _RCOE
= _RCOE
.NONE
261 form
: _Form
= _Form
.NONE
263 unofficial
: bool = False
267 "internal op": "intop",
271 "ldst len": "ldst_len",
273 "CONDITIONS": "conditions",
276 def __lt__(self
, other
):
277 if not isinstance(other
, self
.__class
__):
278 return NotImplemented
279 lhs
= (self
.opcode
, self
.comment
)
280 rhs
= (other
.opcode
, other
.comment
)
284 def CSV(cls
, record
, opcode_cls
):
285 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
286 typemap
["opcode"] = opcode_cls
288 if record
["CR in"] == "BA_BB":
289 record
["cr_in"] = "BA"
290 record
["cr_in2"] = "BB"
294 for flag
in frozenset(PPCRecord
.Flags
):
295 if bool(record
.pop(flag
, "")):
297 record
["flags"] = PPCRecord
.Flags(flags
)
299 return dataclass(cls
, record
,
300 keymap
=PPCRecord
.__KEYMAP
,
305 return frozenset(self
.comment
.split("=")[-1].split("/"))
308 class PPCMultiRecord(tuple):
309 def __getattr__(self
, attr
):
312 raise AttributeError(attr
)
313 return getattr(self
[0], attr
)
316 @_dataclasses.dataclass(eq
=True, frozen
=True)
318 class ExtraMap(tuple):
320 @_dataclasses.dataclass(eq
=True, frozen
=True)
322 regtype
: _SVExtraRegType
= _SVExtraRegType
.NONE
323 reg
: _SVExtraReg
= _SVExtraReg
.NONE
326 return f
"{self.regtype.value}:{self.reg.name}"
328 def __new__(cls
, value
="0"):
329 if isinstance(value
, str):
330 def transform(value
):
331 (regtype
, reg
) = value
.split(":")
332 regtype
= _SVExtraRegType(regtype
)
333 reg
= _SVExtraReg(reg
)
334 return cls
.Entry(regtype
=regtype
, reg
=reg
)
339 value
= map(transform
, value
.split(";"))
341 return super().__new
__(cls
, value
)
344 return repr(list(self
))
346 def __new__(cls
, value
=tuple()):
350 return super().__new
__(cls
, map(cls
.Extra
, value
))
353 return repr({index
:self
[index
] for index
in range(0, 4)})
356 ptype
: _SVPType
= _SVPType
.NONE
357 etype
: _SVEType
= _SVEType
.NONE
358 msrc
: _SVMaskSrc
= _SVMaskSrc
.NO
# MASK_SRC is active
359 in1
: _In1Sel
= _In1Sel
.NONE
360 in2
: _In2Sel
= _In2Sel
.NONE
361 in3
: _In3Sel
= _In3Sel
.NONE
362 out
: _OutSel
= _OutSel
.NONE
363 out2
: _OutSel
= _OutSel
.NONE
364 cr_in
: _CRInSel
= _CRInSel
.NONE
365 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
366 cr_out
: _CROutSel
= _CROutSel
.NONE
367 extra
: ExtraMap
= ExtraMap()
369 mode
: _SVMode
= _SVMode
.NORMAL
373 "CONDITIONS": "conditions",
382 def CSV(cls
, record
):
383 record
["insn"] = record
["insn"].split("=")[-1]
385 for key
in frozenset({
386 "in1", "in2", "in3", "CR in",
387 "out", "out2", "CR out",
393 if record
["CR in"] == "BA_BB":
394 record
["cr_in"] = "BA"
395 record
["cr_in2"] = "BB"
399 for idx
in range(0, 4):
400 extra
.append(record
.pop(f
"{idx}"))
402 record
["extra"] = cls
.ExtraMap(extra
)
404 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
406 def extra_idx(self
, key
, regtype
):
408 Find the index slot that came from the CSV file for this
409 reg (RA/RB/BA/etc) and direction (source/dest).
418 if key
not in frozenset({
419 "in1", "in2", "in3", "cr_in", "cr_in2",
420 "out", "out2", "cr_out",
424 sel
= getattr(self
, key
)
425 if sel
is _CRInSel
.BA_BB
:
426 yield _SVExtra
.Idx_1_2
429 reg
= _SVExtraReg(sel
)
430 if reg
is _SVExtraReg
.NONE
:
434 _SVExtraRegType
.DST
: {},
435 _SVExtraRegType
.SRC
: {},
437 for index
in range(0, 4):
438 for entry
in self
.extra
[index
]:
439 extra_map
[entry
.regtype
][entry
.reg
] = extra_idx
[index
]
441 for (rtype
, regs
) in extra_map
.items():
444 extra
= regs
.get(reg
, _SVExtra
.NONE
)
445 if extra
is not _SVExtra
.NONE
:
448 extra_idx_in1
= property(_functools
.partial(extra_idx
, key
="in1", regtype
=_SVExtraRegType
.SRC
))
449 extra_idx_in2
= property(_functools
.partial(extra_idx
, key
="in2", regtype
=_SVExtraRegType
.SRC
))
450 extra_idx_in3
= property(_functools
.partial(extra_idx
, key
="in3", regtype
=_SVExtraRegType
.SRC
))
451 extra_idx_out
= property(_functools
.partial(extra_idx
, key
="out", regtype
=_SVExtraRegType
.DST
))
452 extra_idx_out2
= property(_functools
.partial(extra_idx
, key
="out2", regtype
=_SVExtraRegType
.DST
))
453 extra_idx_cr_in
= property(_functools
.partial(extra_idx
, key
="cr_in", regtype
=_SVExtraRegType
.SRC
))
454 extra_idx_cr_in2
= property(_functools
.partial(extra_idx
, key
="cr_in2", regtype
=_SVExtraRegType
.SRC
))
455 extra_idx_cr_out
= property(_functools
.partial(extra_idx
, key
="cr_out", regtype
=_SVExtraRegType
.DST
))
457 @_functools.lru_cache(maxsize
=None)
458 def extra_reg(self
, key
):
459 return _SVExtraReg(getattr(self
, key
))
461 extra_reg_in1
= property(_functools
.partial(extra_reg
, key
="in1"))
462 extra_reg_in2
= property(_functools
.partial(extra_reg
, key
="in2"))
463 extra_reg_in3
= property(_functools
.partial(extra_reg
, key
="in3"))
464 extra_reg_out
= property(_functools
.partial(extra_reg
, key
="out"))
465 extra_reg_out2
= property(_functools
.partial(extra_reg
, key
="out2"))
466 extra_reg_cr_in
= property(_functools
.partial(extra_reg
, key
="cr_in"))
467 extra_reg_cr_in2
= property(_functools
.partial(extra_reg
, key
="cr_in2"))
468 extra_reg_cr_out
= property(_functools
.partial(extra_reg
, key
="cr_out"))
473 for idx
in range(0, 4):
474 for entry
in self
.extra
[idx
]:
475 if entry
.regtype
is _SVExtraRegType
.DST
:
476 if extra
is not None:
477 raise ValueError(self
.svp64
)
481 if _RegType(extra
.reg
) not in (_RegType
.CR_3BIT
, _RegType
.CR_5BIT
):
482 raise ValueError(self
.svp64
)
487 def extra_CR_3bit(self
):
488 return (_RegType(self
.extra_CR
.reg
) is _RegType
.CR_3BIT
)
492 def __init__(self
, value
=(0, 32)):
493 if isinstance(value
, str):
494 (start
, end
) = map(int, value
.split(":"))
497 if start
< 0 or end
< 0 or start
>= end
:
498 raise ValueError(value
)
503 return super().__init
__()
506 return (self
.__end
- self
.__start
+ 1)
509 return f
"[{self.__start}:{self.__end}]"
512 yield from range(self
.start
, (self
.end
+ 1))
514 def __reversed__(self
):
515 return tuple(reversed(tuple(self
)))
526 @_dataclasses.dataclass(eq
=True, frozen
=True)
528 class Mode(_enum
.Enum
):
529 INTEGER
= _enum
.auto()
530 PATTERN
= _enum
.auto()
533 def _missing_(cls
, value
):
534 if isinstance(value
, str):
535 return cls
[value
.upper()]
536 return super()._missing
_(value
)
539 def __new__(cls
, value
=None):
540 if isinstance(value
, str):
541 if value
.upper() == "NONE":
544 value
= int(value
, 0)
548 return super().__new
__(cls
, value
)
554 return (bin(self
) if self
else "None")
560 opcode
: IntegerOpcode
= None
561 priority
: Priority
= Priority
.NORMAL
563 def __lt__(self
, other
):
564 if not isinstance(other
, self
.__class
__):
565 return NotImplemented
566 return (self
.priority
< other
.priority
)
569 def CSV(cls
, record
):
570 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
571 if record
["opcode"] == "NONE":
572 typemap
["opcode"] = lambda _
: None
574 return dataclass(cls
, record
, typemap
=typemap
)
578 def __init__(self
, items
):
579 if isinstance(items
, dict):
580 items
= items
.items()
583 (name
, bitrange
) = item
584 return (name
, tuple(bitrange
.values()))
586 self
.__mapping
= dict(map(transform
, items
))
588 return super().__init
__()
591 return repr(self
.__mapping
)
594 yield from self
.__mapping
.items()
596 def __contains__(self
, key
):
597 return self
.__mapping
.__contains
__(key
)
599 def __getitem__(self
, key
):
600 return self
.__mapping
.get(key
, None)
615 def __init__(self
, insn
, operands
):
617 "b": {"target_addr": TargetAddrOperandLI
},
618 "ba": {"target_addr": TargetAddrOperandLI
},
619 "bl": {"target_addr": TargetAddrOperandLI
},
620 "bla": {"target_addr": TargetAddrOperandLI
},
621 "bc": {"target_addr": TargetAddrOperandBD
},
622 "bca": {"target_addr": TargetAddrOperandBD
},
623 "bcl": {"target_addr": TargetAddrOperandBD
},
624 "bcla": {"target_addr": TargetAddrOperandBD
},
625 "addpcis": {"D": DOperandDX
},
626 "fishmv": {"D": DOperandDX
},
627 "fmvis": {"D": DOperandDX
},
630 "SVi": NonZeroOperand
,
631 "SVd": NonZeroOperand
,
632 "SVxd": NonZeroOperand
,
633 "SVyd": NonZeroOperand
,
634 "SVzd": NonZeroOperand
,
636 "D": SignedImmediateOperand
,
640 "SIM": SignedOperand
,
641 "SVD": SignedOperand
,
642 "SVDS": SignedOperand
,
643 "RSp": GPRPairOperand
,
644 "RTp": GPRPairOperand
,
645 "FRAp": FPRPairOperand
,
646 "FRBp": FPRPairOperand
,
647 "FRSp": FPRPairOperand
,
648 "FRTp": FPRPairOperand
,
650 custom_immediates
= {
656 for operand
in operands
:
660 (name
, value
) = operand
.split("=")
661 mapping
[name
] = (StaticOperand
, {
667 if name
.endswith(")"):
668 name
= name
.replace("(", " ").replace(")", "")
669 (imm_name
, _
, name
) = name
.partition(" ")
673 if imm_name
is not None:
674 imm_cls
= custom_immediates
.get(imm_name
, ImmediateOperand
)
676 if insn
in custom_insns
and name
in custom_insns
[insn
]:
677 cls
= custom_insns
[insn
][name
]
678 elif name
in custom_fields
:
679 cls
= custom_fields
[name
]
680 elif name
in _SVExtraReg
.__members
__:
681 reg
= _SVExtraReg
[name
]
682 if reg
in self
.__class
__.__GPR
_PAIRS
:
684 elif reg
in self
.__class
__.__FPR
_PAIRS
:
687 regtype
= _RegType
[name
]
688 if regtype
is _RegType
.GPR
:
690 elif regtype
is _RegType
.FPR
:
692 elif regtype
is _RegType
.CR_3BIT
:
694 elif regtype
is _RegType
.CR_5BIT
:
697 if imm_name
is not None:
698 mapping
[imm_name
] = (imm_cls
, {"name": imm_name
})
699 mapping
[name
] = (cls
, {"name": name
})
703 for (name
, (cls
, kwargs
)) in mapping
.items():
704 kwargs
= dict(kwargs
)
705 kwargs
["name"] = name
706 if issubclass(cls
, StaticOperand
):
707 static
.append((cls
, kwargs
))
708 elif issubclass(cls
, DynamicOperand
):
709 dynamic
.append((cls
, kwargs
))
711 raise ValueError(name
)
713 self
.__mapping
= mapping
714 self
.__static
= tuple(static
)
715 self
.__dynamic
= tuple(dynamic
)
717 return super().__init
__()
720 for (_
, items
) in self
.__mapping
.items():
721 (cls
, kwargs
) = items
725 return self
.__mapping
.__repr
__()
727 def __contains__(self
, key
):
728 return self
.__mapping
.__contains
__(key
)
730 def __getitem__(self
, key
):
731 return self
.__mapping
.__getitem
__(key
)
739 return self
.__dynamic
742 class Arguments(tuple):
743 def __new__(cls
, record
, arguments
, operands
):
744 operands
= iter(tuple(operands
))
745 arguments
= iter(tuple(arguments
))
750 operand
= next(operands
)
751 except StopIteration:
755 argument
= next(arguments
)
756 except StopIteration:
757 raise ValueError("operands count mismatch")
759 if isinstance(operand
, ImmediateOperand
):
760 argument
= argument
.replace("(", " ").replace(")", "")
761 (imm_argument
, _
, argument
) = argument
.partition(" ")
763 (imm_operand
, operand
) = (operand
, next(operands
))
764 except StopIteration:
765 raise ValueError("operands count mismatch")
766 items
.append((imm_argument
, imm_operand
))
767 items
.append((argument
, operand
))
771 except StopIteration:
774 raise ValueError("operands count mismatch")
776 return super().__new
__(cls
, items
)
780 def __init__(self
, iterable
):
781 self
.__pcode
= tuple(iterable
)
782 return super().__init
__()
785 yield from self
.__pcode
788 return self
.__pcode
.__repr
__()
791 @_dataclasses.dataclass(eq
=True, frozen
=True)
792 class MarkdownRecord
:
797 @_functools.total_ordering
798 @_dataclasses.dataclass(eq
=True, frozen
=True)
805 svp64
: SVP64Record
= None
807 def __lt__(self
, other
):
808 if not isinstance(other
, Record
):
809 return NotImplemented
810 lhs
= (min(self
.opcodes
), self
.name
)
811 rhs
= (min(other
.opcodes
), other
.name
)
816 return (self
.static_operands
+ self
.dynamic_operands
)
819 def static_operands(self
):
821 operands
.append(POStaticOperand(record
=self
, value
=self
.PO
))
823 operands
.append(XOStaticOperand(
825 value
=ppc
.opcode
.value
,
826 span
=self
.section
.bitsel
,
828 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
829 operands
.append(cls(record
=self
, **kwargs
))
830 return tuple(operands
)
833 def dynamic_operands(self
):
835 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
836 operands
.append(cls(record
=self
, **kwargs
))
837 return tuple(operands
)
842 return int("".join(str(int(mapping
[bit
])) \
843 for bit
in sorted(mapping
)), 2)
845 def PO_XO(value
, mask
, opcode
, bits
):
848 for (src
, dst
) in enumerate(reversed(bits
)):
849 value
[dst
] = ((opcode
.value
& (1 << src
)) != 0)
850 mask
[dst
] = ((opcode
.mask
& (1 << src
)) != 0)
853 def PO(value
, mask
, opcode
, bits
):
854 return PO_XO(value
=value
, mask
=mask
, opcode
=opcode
, bits
=bits
)
856 def XO(value
, mask
, opcode
, bits
):
857 (value
, mask
) = PO_XO(value
=value
, mask
=mask
,
858 opcode
=opcode
, bits
=bits
)
859 for (op_cls
, op_kwargs
) in self
.mdwn
.operands
.static
:
860 operand
= op_cls(record
=self
, **op_kwargs
)
861 for (src
, dst
) in enumerate(reversed(operand
.span
)):
862 value
[dst
] = ((operand
.value
& (1 << src
)) != 0)
867 value
= {bit
:False for bit
in range(32)}
868 mask
= {bit
:False for bit
in range(32)}
869 if self
.section
.opcode
is not None:
870 (value
, mask
) = PO(value
=value
, mask
=mask
,
871 opcode
=self
.section
.opcode
, bits
=range(0, 6))
873 pairs
.append(XO(value
=value
, mask
=mask
,
874 opcode
=ppc
.opcode
, bits
=self
.section
.bitsel
))
877 for (value
, mask
) in pairs
:
878 value
= Opcode
.Value(binary(value
))
879 mask
= Opcode
.Mask(binary(mask
))
880 result
.append(Opcode(value
=value
, mask
=mask
))
886 opcode
= self
.section
.opcode
888 opcode
= self
.ppc
[0].opcode
889 if isinstance(opcode
, PatternOpcode
):
890 value
= int(opcode
.value
)
891 bits
= opcode
.value
.bit_length()
892 return int(_SelectableInt(value
=value
, bits
=bits
)[0:6])
894 return int(opcode
.value
)
898 return tuple(ppc
.opcode
for ppc
in self
.ppc
)
900 def match(self
, key
):
901 for opcode
in self
.opcodes
:
902 if opcode
.match(key
):
909 return self
.svp64
.mode
929 if self
.svp64
is None:
935 return self
.ppc
.cr_in
939 return self
.ppc
.cr_in2
943 return self
.ppc
.cr_out
945 ptype
= property(lambda self
: self
.svp64
.ptype
)
946 etype
= property(lambda self
: self
.svp64
.etype
)
948 def extra_idx(self
, key
, regtype
):
949 return self
.svp64
.extra_idx(key
, regtype
)
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
, **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_reg(self
):
1239 return _SVExtraReg(self
.name
)
1242 def extra_idx(self
):
1244 _SVExtraReg
.RSp
: _SVExtraReg
.RS
,
1245 _SVExtraReg
.RTp
: _SVExtraReg
.RT
,
1246 _SVExtraReg
.FRAp
: _SVExtraReg
.FRA
,
1247 _SVExtraReg
.FRBp
: _SVExtraReg
.FRB
,
1248 _SVExtraReg
.FRSp
: _SVExtraReg
.FRS
,
1249 _SVExtraReg
.FRTp
: _SVExtraReg
.FRT
,
1253 for key
in ("in1", "in2", "in3", "cr_in", "cr_in2"):
1254 keys
[key
] = _SVExtraRegType
.SRC
1255 for key
in ("out", "out2", "cr_out"):
1256 keys
[key
] = _SVExtraRegType
.DST
1257 regtype
= keys
.get(key
)
1261 found
= {} # prevent duplicates.
1262 for (key
, regtype
) in keys
.items():
1263 extra_reg
= self
.record
.svp64
.extra_reg(key
=key
)
1264 this_extra_reg
= pairs
.get(self
.extra_reg
, self
.extra_reg
)
1265 that_extra_reg
= pairs
.get(extra_reg
, extra_reg
)
1266 if this_extra_reg
is that_extra_reg
:
1267 bits
= tuple(self
.record
.extra_idx(key
=key
, regtype
=regtype
))
1268 if this_extra_reg
in found
:
1269 assert found
[this_extra_reg
] == bits
# check identical bits
1270 continue # skip - already found
1271 yield from bits
# yield the idx
1272 found
[this_extra_reg
] = bits
# skip next time round
1274 def remap(self
, value
, vector
):
1275 raise NotImplementedError()
1277 def assemble(self
, value
, insn
, prefix
):
1280 if isinstance(value
, str):
1281 value
= value
.lower()
1282 if value
.startswith("%"):
1284 if value
.startswith("*"):
1285 if not isinstance(insn
, SVP64Instruction
):
1286 raise ValueError(value
)
1289 if value
.startswith(prefix
):
1290 value
= value
[len(prefix
):]
1291 value
= int(value
, 0)
1293 if isinstance(insn
, SVP64Instruction
):
1294 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1296 for extra_idx
in self
.extra_idx
:
1297 if self
.record
.etype
is _SVEType
.EXTRA3
:
1298 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1299 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1300 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1302 raise ValueError(self
.record
.etype
)
1304 return super().assemble(value
=value
, insn
=insn
)
1306 def disassemble(self
, insn
,
1307 style
=Style
.NORMAL
, prefix
="", indent
=""):
1308 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1310 if style
>= Style
.VERBOSE
:
1311 mode
= "vector" if vector
else "scalar"
1312 yield f
"{indent}{self.name} ({mode})"
1313 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1314 yield f
"{indent}{indent}{', '.join(span)}"
1315 if isinstance(insn
, SVP64Instruction
):
1316 for extra_idx
in frozenset(self
.extra_idx
):
1317 if self
.record
.etype
is _SVEType
.NONE
:
1318 yield f
"{indent}{indent}extra[none]"
1320 etype
= repr(self
.record
.etype
).lower()
1321 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1323 vector
= "*" if vector
else ""
1324 yield f
"{vector}{prefix}{int(value)}"
1327 class SimpleRegisterOperand(ExtendableOperand
):
1328 def remap(self
, value
, vector
):
1330 extra
= (value
& 0b11)
1331 value
= (value
>> 2)
1333 extra
= (value
>> 5)
1334 value
= (value
& 0b11111)
1336 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1337 # (and shrink to a single bit if ok)
1338 if self
.record
.etype
is _SVEType
.EXTRA2
:
1340 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1341 assert (extra
& 0b01) == 0, \
1342 ("vector field %s cannot fit into EXTRA2" % value
)
1343 extra
= (0b10 |
(extra
>> 1))
1345 # range is r0-r63 in increments of 1
1346 assert (extra
>> 1) == 0, \
1347 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1349 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1351 # EXTRA3 vector bit needs marking
1354 raise ValueError(self
.record
.etype
)
1356 return (value
, extra
)
1359 class GPROperand(SimpleRegisterOperand
):
1360 def assemble(self
, insn
, value
):
1361 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1363 def disassemble(self
, insn
,
1364 style
=Style
.NORMAL
, indent
=""):
1365 prefix
= "" if (style
<= Style
.SHORT
) else "r"
1366 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1367 style
=style
, indent
=indent
)
1370 class GPRPairOperand(GPROperand
):
1374 class FPROperand(SimpleRegisterOperand
):
1375 def assemble(self
, insn
, value
):
1376 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1378 def disassemble(self
, insn
,
1379 style
=Style
.NORMAL
, indent
=""):
1380 prefix
= "" if (style
<= Style
.SHORT
) else "f"
1381 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1382 style
=style
, indent
=indent
)
1385 class FPRPairOperand(FPROperand
):
1389 class ConditionRegisterFieldOperand(ExtendableOperand
):
1390 def pattern(name_pattern
):
1391 (name
, pattern
) = name_pattern
1392 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1401 CR
= r
"(?:CR|cr)([0-9]+)"
1403 BIT
= rf
"({'|'.join(CONDS.keys())})"
1404 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1405 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1406 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1407 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1408 XCR
= fr
"{CR}\.{BIT}"
1409 PATTERNS
= tuple(map(pattern
, (
1414 ("BIT+CR", (LBIT
+ CR
)),
1415 ("CR+BIT", (CR
+ RBIT
)),
1416 ("BIT+CR*N", (LBIT
+ CRN
)),
1417 ("CR*N+BIT", (CRN
+ RBIT
)),
1418 ("BIT+N*CR", (LBIT
+ NCR
)),
1419 ("N*CR+BIT", (NCR
+ RBIT
)),
1422 def remap(self
, value
, vector
, regtype
):
1423 if regtype
is _RegType
.CR_5BIT
:
1424 subvalue
= (value
& 0b11)
1428 extra
= (value
& 0b1111)
1431 extra
= (value
>> 3)
1434 if self
.record
.etype
is _SVEType
.EXTRA2
:
1436 assert (extra
& 0b111) == 0, \
1437 "vector CR cannot fit into EXTRA2"
1438 extra
= (0b10 |
(extra
>> 3))
1440 assert (extra
>> 1) == 0, \
1441 "scalar CR cannot fit into EXTRA2"
1443 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1445 assert (extra
& 0b11) == 0, \
1446 "vector CR cannot fit into EXTRA3"
1447 extra
= (0b100 |
(extra
>> 2))
1449 assert (extra
>> 2) == 0, \
1450 "scalar CR cannot fit into EXTRA3"
1453 if regtype
is _RegType
.CR_5BIT
:
1454 value
= ((value
<< 2) | subvalue
)
1456 return (value
, extra
)
1458 def assemble(self
, insn
, value
):
1459 if isinstance(value
, str):
1462 if value
.startswith("*"):
1463 if not isinstance(insn
, SVP64Instruction
):
1464 raise ValueError(value
)
1468 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1469 match
= pattern
.match(value
)
1470 if match
is not None:
1471 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1472 values
= match
.groups()
1473 match
= dict(zip(keys
, values
))
1474 CR
= int(match
["CR"])
1478 N
= int(match
.get("N", "1"))
1479 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1480 value
= ((CR
* N
) + BIT
)
1487 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1489 def disassemble(self
, insn
,
1490 style
=Style
.NORMAL
, prefix
="", indent
=""):
1491 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1493 if style
>= Style
.VERBOSE
:
1494 mode
= "vector" if vector
else "scalar"
1495 yield f
"{indent}{self.name} ({mode})"
1496 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1497 yield f
"{indent}{indent}{', '.join(span)}"
1498 if isinstance(insn
, SVP64Instruction
):
1499 for extra_idx
in frozenset(self
.extra_idx
):
1500 if self
.record
.etype
is _SVEType
.NONE
:
1501 yield f
"{indent}{indent}extra[none]"
1503 etype
= repr(self
.record
.etype
).lower()
1504 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1506 vector
= "*" if vector
else ""
1507 CR
= int(value
>> 2)
1509 cond
= ("lt", "gt", "eq", "so")[CC
]
1510 if style
>= Style
.NORMAL
:
1512 if isinstance(insn
, SVP64Instruction
):
1513 yield f
"{vector}cr{CR}.{cond}"
1515 yield f
"4*cr{CR}+{cond}"
1519 yield f
"{vector}{prefix}{int(value)}"
1522 class CR3Operand(ConditionRegisterFieldOperand
):
1523 def remap(self
, value
, vector
):
1524 return super().remap(value
=value
, vector
=vector
,
1525 regtype
=_RegType
.CR_3BIT
)
1528 class CR5Operand(ConditionRegisterFieldOperand
):
1529 def remap(self
, value
, vector
):
1530 return super().remap(value
=value
, vector
=vector
,
1531 regtype
=_RegType
.CR_5BIT
)
1533 def sv_spec_enter(self
, value
, span
):
1534 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1535 return (value
, span
)
1537 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1538 value
= _selectconcat(value
, origin_value
[3:5])
1540 return (value
, span
)
1543 class EXTSOperand(SignedOperand
):
1544 field
: str # real name to report
1545 nz
: int = 0 # number of zeros
1546 fmt
: str = "d" # integer formatter
1548 def __init__(self
, record
, name
, field
, nz
=0, fmt
="d"):
1549 self
.__field
= field
1552 return super().__init
__(record
=record
, name
=name
)
1568 return self
.record
.fields
[self
.field
]
1570 def assemble(self
, insn
, value
):
1572 if isinstance(value
, str):
1573 value
= int(value
, 0)
1574 insn
[span
] = (value
>> self
.nz
)
1576 def disassemble(self
, insn
,
1577 style
=Style
.NORMAL
, indent
=""):
1579 value
= insn
[span
].to_signed_int()
1580 sign
= "-" if (value
< 0) else ""
1581 value
= (abs(value
) << self
.nz
)
1583 if style
>= Style
.VERBOSE
:
1584 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1585 zeros
= ("0" * self
.nz
)
1586 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1587 yield f
"{indent * 1}{hint}"
1588 yield f
"{indent * 2}{self.field}"
1589 yield f
"{indent * 3}{sign}{value:{self.fmt}}"
1590 yield f
"{indent * 3}{', '.join(span)}"
1592 yield f
"{sign}{value:{self.fmt}}"
1595 class TargetAddrOperand(EXTSOperand
):
1596 def __init__(self
, record
, name
, field
):
1597 return super().__init
__(record
=record
, name
=name
, field
=field
,
1601 class TargetAddrOperandLI(TargetAddrOperand
):
1602 def __init__(self
, record
, name
):
1603 return super().__init
__(record
=record
, name
=name
, field
="LI")
1606 class TargetAddrOperandBD(TargetAddrOperand
):
1607 def __init__(self
, record
, name
):
1608 return super().__init
__(record
=record
, name
=name
, field
="BD")
1611 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1612 def __init__(self
, record
, name
):
1613 return super().__init
__(record
=record
, name
=name
, field
="DS", nz
=2)
1616 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1617 def __init__(self
, record
, name
):
1618 return super().__init
__(record
=record
, name
=name
, field
="DQ", nz
=4)
1621 class DOperandDX(SignedOperand
):
1624 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1625 operands
= map(cls
, ("d0", "d1", "d2"))
1626 spans
= map(lambda operand
: operand
.span
, operands
)
1627 return sum(spans
, tuple())
1629 def disassemble(self
, insn
,
1630 style
=Style
.NORMAL
, indent
=""):
1632 value
= insn
[span
].to_signed_int()
1633 sign
= "-" if (value
< 0) else ""
1636 if style
>= Style
.VERBOSE
:
1643 for (subname
, subspan
) in mapping
.items():
1644 operand
= DynamicOperand(name
=subname
)
1646 span
= map(str, span
)
1647 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1648 yield f
"{indent}{indent}{indent}{sign}{value}"
1649 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1651 yield f
"{sign}{value}"
1654 class Instruction(_Mapping
):
1656 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1657 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1658 raise ValueError(bits
)
1660 if isinstance(value
, bytes
):
1661 if ((len(value
) * 8) != bits
):
1662 raise ValueError(f
"bit length mismatch")
1663 value
= int.from_bytes(value
, byteorder
=byteorder
)
1665 if isinstance(value
, int):
1666 value
= _SelectableInt(value
=value
, bits
=bits
)
1667 elif isinstance(value
, Instruction
):
1668 value
= value
.storage
1670 if not isinstance(value
, _SelectableInt
):
1671 raise ValueError(value
)
1674 if len(value
) != bits
:
1675 raise ValueError(value
)
1677 value
= _SelectableInt(value
=value
, bits
=bits
)
1679 return cls(storage
=value
)
1682 return hash(int(self
))
1684 def __getitem__(self
, key
):
1685 return self
.storage
.__getitem
__(key
)
1687 def __setitem__(self
, key
, value
):
1688 return self
.storage
.__setitem
__(key
, value
)
1690 def bytes(self
, byteorder
="little"):
1691 nr_bytes
= (len(self
.__class
__) // 8)
1692 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1695 def record(cls
, db
, entry
):
1698 raise KeyError(entry
)
1702 def operands(cls
, record
):
1703 yield from record
.operands
1706 def static_operands(cls
, record
):
1707 return filter(lambda operand
: isinstance(operand
, StaticOperand
),
1708 cls
.operands(record
=record
))
1711 def dynamic_operands(cls
, record
):
1712 return filter(lambda operand
: isinstance(operand
, DynamicOperand
),
1713 cls
.operands(record
=record
))
1715 def spec(self
, record
, prefix
):
1716 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1717 self
.spec_dynamic_operands(record
=record
)))
1719 static_operands
= []
1720 for (name
, value
) in self
.spec_static_operands(record
=record
):
1721 static_operands
.append(f
"{name}={value}")
1724 if dynamic_operands
:
1726 operands
+= ",".join(dynamic_operands
)
1729 operands
+= " ".join(static_operands
)
1731 return f
"{prefix}{record.name}{operands}"
1733 def spec_static_operands(self
, record
):
1734 for operand
in self
.static_operands(record
=record
):
1735 if not isinstance(operand
, (POStaticOperand
, XOStaticOperand
)):
1736 yield (operand
.name
, operand
.value
)
1738 def spec_dynamic_operands(self
, record
, style
=Style
.NORMAL
):
1742 for operand
in self
.dynamic_operands(record
=record
):
1744 value
= " ".join(operand
.disassemble(insn
=self
,
1745 style
=min(style
, Style
.NORMAL
)))
1747 name
= f
"{imm_name}({name})"
1748 value
= f
"{imm_value}({value})"
1750 if isinstance(operand
, ImmediateOperand
):
1758 def assemble(cls
, record
, arguments
=None):
1759 if arguments
is None:
1762 insn
= cls
.integer(value
=0)
1764 for operand
in cls
.static_operands(record
=record
):
1765 operand
.assemble(insn
=insn
)
1767 arguments
= Arguments(record
=record
,
1768 arguments
=arguments
, operands
=cls
.dynamic_operands(record
=record
))
1769 for (value
, operand
) in arguments
:
1770 operand
.assemble(insn
=insn
, value
=value
)
1774 def disassemble(self
, record
,
1776 style
=Style
.NORMAL
):
1777 raise NotImplementedError()
1780 class WordInstruction(Instruction
):
1781 _
: _Field
= range(0, 32)
1782 PO
: _Field
= range(0, 6)
1785 def integer(cls
, value
, byteorder
="little"):
1786 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1791 for idx
in range(32):
1792 bit
= int(self
[idx
])
1794 return "".join(map(str, bits
))
1796 def disassemble(self
, record
,
1798 style
=Style
.NORMAL
):
1799 if style
<= Style
.SHORT
:
1802 blob
= self
.bytes(byteorder
=byteorder
)
1803 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1807 yield f
"{blob}.long 0x{int(self):08x}"
1810 # awful temporary hack: workaround for ld-update
1811 # https://bugs.libre-soc.org/show_bug.cgi?id=1056#c2
1812 # XXX TODO must check that *EXTENDED* RA != extended-RT
1813 if (record
.svp64
is not None and
1814 record
.mode
== _SVMode
.LDST_IMM
and
1815 'u' in record
.name
):
1816 yield f
"{blob}.long 0x{int(self):08x}"
1820 if style
is Style
.LEGACY
:
1822 for operand
in self
.dynamic_operands(record
=record
):
1823 if isinstance(operand
, (GPRPairOperand
, FPRPairOperand
)):
1826 if style
is Style
.LEGACY
and (paired
or record
.ppc
.unofficial
):
1827 yield f
"{blob}.long 0x{int(self):08x}"
1829 operands
= tuple(map(_operator
.itemgetter(1),
1830 self
.spec_dynamic_operands(record
=record
, style
=style
)))
1832 operands
= ",".join(operands
)
1833 yield f
"{blob}{record.name} {operands}"
1835 yield f
"{blob}{record.name}"
1837 if style
>= Style
.VERBOSE
:
1839 binary
= self
.binary
1840 spec
= self
.spec(record
=record
, prefix
="")
1841 yield f
"{indent}spec"
1842 yield f
"{indent}{indent}{spec}"
1843 yield f
"{indent}pcode"
1844 for stmt
in record
.mdwn
.pcode
:
1845 yield f
"{indent}{indent}{stmt}"
1846 yield f
"{indent}binary"
1847 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1848 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1849 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1850 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1851 yield f
"{indent}opcodes"
1852 for opcode
in record
.opcodes
:
1853 yield f
"{indent}{indent}{opcode!r}"
1854 for operand
in self
.operands(record
=record
):
1855 yield from operand
.disassemble(insn
=self
,
1856 style
=style
, indent
=indent
)
1860 class PrefixedInstruction(Instruction
):
1861 class Prefix(WordInstruction
.remap(range(0, 32))):
1864 class Suffix(WordInstruction
.remap(range(32, 64))):
1867 _
: _Field
= range(64)
1873 def integer(cls
, value
, byteorder
="little"):
1874 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
1877 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
1878 def transform(value
):
1879 return WordInstruction
.integer(value
=value
,
1880 byteorder
=byteorder
)[0:32]
1882 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
1883 value
= _selectconcat(prefix
, suffix
)
1885 return super().integer(bits
=64, value
=value
)
1888 class Mode(_Mapping
):
1889 _
: _Field
= range(0, 5)
1890 sel
: _Field
= (0, 1)
1893 class Extra(_Mapping
):
1894 _
: _Field
= range(0, 9)
1897 class Extra2(Extra
):
1898 idx0
: _Field
= range(0, 2)
1899 idx1
: _Field
= range(2, 4)
1900 idx2
: _Field
= range(4, 6)
1901 idx3
: _Field
= range(6, 8)
1903 def __getitem__(self
, key
):
1909 _SVExtra
.Idx0
: self
.idx0
,
1910 _SVExtra
.Idx1
: self
.idx1
,
1911 _SVExtra
.Idx2
: self
.idx2
,
1912 _SVExtra
.Idx3
: self
.idx3
,
1915 def __setitem__(self
, key
, value
):
1916 self
[key
].assign(value
)
1919 class Extra3(Extra
):
1920 idx0
: _Field
= range(0, 3)
1921 idx1
: _Field
= range(3, 6)
1922 idx2
: _Field
= range(6, 9)
1924 def __getitem__(self
, key
):
1929 _SVExtra
.Idx0
: self
.idx0
,
1930 _SVExtra
.Idx1
: self
.idx1
,
1931 _SVExtra
.Idx2
: self
.idx2
,
1934 def __setitem__(self
, key
, value
):
1935 self
[key
].assign(value
)
1938 class BaseRM(_Mapping
):
1939 _
: _Field
= range(24)
1940 mmode
: _Field
= (0,)
1941 mask
: _Field
= range(1, 4)
1942 elwidth
: _Field
= range(4, 6)
1943 ewsrc
: _Field
= range(6, 8)
1944 subvl
: _Field
= range(8, 10)
1945 mode
: Mode
.remap(range(19, 24))
1946 smask
: _Field
= range(16, 19)
1947 extra
: Extra
.remap(range(10, 19))
1948 extra2
: Extra2
.remap(range(10, 19))
1949 extra3
: Extra3
.remap(range(10, 19))
1951 def specifiers(self
, record
):
1952 subvl
= int(self
.subvl
)
1960 def disassemble(self
, style
=Style
.NORMAL
):
1961 if style
>= Style
.VERBOSE
:
1963 for (name
, span
) in self
.traverse(path
="RM"):
1964 value
= self
.storage
[span
]
1966 yield f
"{indent}{int(value):0{value.bits}b}"
1967 yield f
"{indent}{', '.join(map(str, span))}"
1970 class FFRc1BaseRM(BaseRM
):
1971 def specifiers(self
, record
, mode
):
1972 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
1973 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
1974 mask
= int(_selectconcat(CR
, inv
))
1975 predicate
= PredicateBaseRM
.predicate(True, mask
)
1976 yield f
"{mode}={predicate}"
1978 yield from super().specifiers(record
=record
)
1981 class FFRc0BaseRM(BaseRM
):
1982 def specifiers(self
, record
, mode
):
1984 inv
= "~" if self
.inv
else ""
1985 yield f
"{mode}={inv}RC1"
1987 yield from super().specifiers(record
=record
)
1990 class SatBaseRM(BaseRM
):
1991 def specifiers(self
, record
):
1997 yield from super().specifiers(record
=record
)
2000 class ZZBaseRM(BaseRM
):
2001 def specifiers(self
, record
):
2005 yield from super().specifiers(record
=record
)
2008 class ZZCombinedBaseRM(BaseRM
):
2009 def specifiers(self
, record
):
2010 if self
.sz
and self
.dz
:
2017 yield from super().specifiers(record
=record
)
2020 class DZBaseRM(BaseRM
):
2021 def specifiers(self
, record
):
2025 yield from super().specifiers(record
=record
)
2028 class SZBaseRM(BaseRM
):
2029 def specifiers(self
, record
):
2033 yield from super().specifiers(record
=record
)
2036 class MRBaseRM(BaseRM
):
2037 def specifiers(self
, record
):
2043 yield from super().specifiers(record
=record
)
2046 class ElsBaseRM(BaseRM
):
2047 def specifiers(self
, record
):
2051 yield from super().specifiers(record
=record
)
2054 class WidthBaseRM(BaseRM
):
2056 def width(FP
, width
):
2065 width
= ("fp" + width
)
2068 def specifiers(self
, record
):
2069 # elwidths: use "w=" if same otherwise dw/sw
2070 # FIXME this should consider FP instructions
2072 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
2073 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2074 if record
.svp64
.mode
is _SVMode
.CROP
:
2078 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2087 yield from super().specifiers(record
=record
)
2090 class PredicateBaseRM(BaseRM
):
2092 def predicate(CR
, mask
):
2095 (False, 0b001): "1<<r3",
2096 (False, 0b010): "r3",
2097 (False, 0b011): "~r3",
2098 (False, 0b100): "r10",
2099 (False, 0b101): "~r10",
2100 (False, 0b110): "r30",
2101 (False, 0b111): "~r30",
2103 (True, 0b000): "lt",
2104 (True, 0b001): "ge",
2105 (True, 0b010): "gt",
2106 (True, 0b011): "le",
2107 (True, 0b100): "eq",
2108 (True, 0b101): "ne",
2109 (True, 0b110): "so",
2110 (True, 0b111): "ns",
2113 def specifiers(self
, record
):
2114 # predication - single and twin
2115 # use "m=" if same otherwise sm/dm
2116 CR
= (int(self
.mmode
) == 1)
2117 mask
= int(self
.mask
)
2118 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
2119 if record
.svp64
.ptype
is _SVPType
.P2
:
2120 smask
= int(self
.smask
)
2121 sm
= PredicateBaseRM
.predicate(CR
, smask
)
2130 yield from super().specifiers(record
=record
)
2133 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
2137 class SEABaseRM(BaseRM
):
2138 def specifiers(self
, record
):
2142 yield from super().specifiers(record
=record
)
2145 class VLiBaseRM(BaseRM
):
2146 def specifiers(self
, record
):
2150 yield from super().specifiers(record
=record
)
2153 class NormalBaseRM(PredicateWidthBaseRM
):
2156 https://libre-soc.org/openpower/sv/normal/
2161 class NormalSimpleRM(ZZCombinedBaseRM
, NormalBaseRM
):
2162 """normal: simple mode"""
2166 def specifiers(self
, record
):
2167 yield from super().specifiers(record
=record
)
2170 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
2171 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
2175 class NormalFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, NormalBaseRM
):
2176 """normal: Rc=1: ffirst CR sel"""
2179 CR
: BaseRM
.mode
[3, 4]
2181 def specifiers(self
, record
):
2182 yield from super().specifiers(record
=record
, mode
="ff")
2185 class NormalFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
2186 """normal: Rc=0: ffirst z/nonz"""
2191 def specifiers(self
, record
):
2192 yield from super().specifiers(record
=record
, mode
="ff")
2195 class NormalSatRM(SatBaseRM
, ZZCombinedBaseRM
, NormalBaseRM
):
2196 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2202 class NormalRM(NormalBaseRM
):
2203 simple
: NormalSimpleRM
2205 ffrc1
: NormalFFRc1RM
2206 ffrc0
: NormalFFRc0RM
2210 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2212 LD/ST Immediate mode
2213 https://libre-soc.org/openpower/sv/ldst/
2218 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2219 """ld/st immediate: simple mode"""
2220 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2221 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2227 def specifiers(self
, record
):
2233 yield from super().specifiers(record
=record
)
2236 class LDSTFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2237 """ld/st immediate&indexed: Rc=1: ffirst CR sel"""
2240 CR
: BaseRM
.mode
[3, 4]
2242 def specifiers(self
, record
):
2243 yield from super().specifiers(record
=record
, mode
="ff")
2246 class LDSTFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2247 """ld/st immediate&indexed: Rc=0: ffirst z/nonz"""
2252 def specifiers(self
, record
):
2253 yield from super().specifiers(record
=record
, mode
="ff")
2256 class LDSTImmRM(LDSTImmBaseRM
):
2257 simple
: LDSTImmSimpleRM
2262 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2265 https://libre-soc.org/openpower/sv/ldst/
2270 class LDSTIdxSimpleRM(SEABaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2271 """ld/st index: simple mode (includes element-strided and Signed-EA)"""
2272 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2279 def specifiers(self
, record
):
2285 yield from super().specifiers(record
=record
)
2288 class LDSTIdxRM(LDSTIdxBaseRM
):
2289 simple
: LDSTIdxSimpleRM
2295 class CROpBaseRM(BaseRM
):
2298 https://libre-soc.org/openpower/sv/cr_ops/
2303 class CROpSimpleRM(PredicateBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2304 """crop: simple mode"""
2309 def specifiers(self
, record
):
2311 yield "rg" # simple CR Mode reports /rg
2313 yield from super().specifiers(record
=record
)
2316 class CROpMRRM(MRBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2317 """crop: scalar reduce mode (mapreduce)"""
2323 class CROpFF5RM(FFRc0BaseRM
, PredicateBaseRM
, VLiBaseRM
, DZBaseRM
,
2324 SZBaseRM
, CROpBaseRM
):
2325 """crop: ffirst 5-bit mode"""
2332 def specifiers(self
, record
):
2333 yield from super().specifiers(record
=record
, mode
="ff")
2336 # FIXME: almost everything in this class contradicts the specs (it doesn't)
2337 # The modes however are swapped: 5-bit is 3-bit, 3-bit is 5-bit
2338 class CROpFF3RM(FFRc1BaseRM
, PredicateBaseRM
, VLiBaseRM
, ZZBaseRM
, CROpBaseRM
):
2339 """cr_op: ffirst 3-bit mode"""
2345 def specifiers(self
, record
):
2346 yield from super().specifiers(record
=record
, mode
="ff")
2349 class CROpRM(CROpBaseRM
):
2350 simple
: CROpSimpleRM
2356 # ********************
2358 # https://libre-soc.org/openpower/sv/branches/
2359 class BranchBaseRM(BaseRM
):
2369 def specifiers(self
, record
):
2381 raise ValueError(self
.sz
)
2393 # Branch modes lack source mask.
2394 # Therefore a custom code is needed.
2395 CR
= (int(self
.mmode
) == 1)
2396 mask
= int(self
.mask
)
2397 m
= PredicateBaseRM
.predicate(CR
, mask
)
2401 yield from super().specifiers(record
=record
)
2404 class BranchSimpleRM(BranchBaseRM
):
2405 """branch: simple mode"""
2409 class BranchVLSRM(BranchBaseRM
):
2410 """branch: VLSET mode"""
2414 def specifiers(self
, record
):
2420 }[int(self
.VSb
), int(self
.VLi
)]
2422 yield from super().specifiers(record
=record
)
2425 class BranchCTRRM(BranchBaseRM
):
2426 """branch: CTR-test mode"""
2429 def specifiers(self
, record
):
2435 yield from super().specifiers(record
=record
)
2438 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2439 """branch: CTR-test+VLSET mode"""
2443 class BranchRM(BranchBaseRM
):
2444 simple
: BranchSimpleRM
2447 ctrvls
: BranchCTRVLSRM
2458 @_dataclasses.dataclass(eq
=True, frozen
=True)
2463 def match(cls
, desc
, record
):
2464 raise NotImplementedError()
2466 def validate(self
, others
):
2469 def assemble(self
, insn
):
2470 raise NotImplementedError()
2473 @_dataclasses.dataclass(eq
=True, frozen
=True)
2474 class SpecifierWidth(Specifier
):
2478 def match(cls
, desc
, record
, etalon
):
2479 (mode
, _
, value
) = desc
.partition("=")
2481 value
= value
.strip()
2484 width
= _SVP64Width(value
)
2486 return cls(record
=record
, width
=width
)
2489 @_dataclasses.dataclass(eq
=True, frozen
=True)
2490 class SpecifierW(SpecifierWidth
):
2492 def match(cls
, desc
, record
):
2493 return super().match(desc
=desc
, record
=record
, etalon
="w")
2495 def assemble(self
, insn
):
2496 selector
= insn
.select(record
=self
.record
)
2497 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2498 selector
.ewsrc
= self
.width
.value
2499 selector
.elwidth
= self
.width
.value
2502 @_dataclasses.dataclass(eq
=True, frozen
=True)
2503 class SpecifierSW(SpecifierWidth
):
2505 def match(cls
, desc
, record
):
2506 if record
.svp64
.mode
is _SVMode
.CROP
:
2508 return super().match(desc
=desc
, record
=record
, etalon
="sw")
2510 def assemble(self
, insn
):
2511 selector
= insn
.select(record
=self
.record
)
2512 selector
.ewsrc
= self
.width
.value
2515 @_dataclasses.dataclass(eq
=True, frozen
=True)
2516 class SpecifierDW(SpecifierWidth
):
2518 def match(cls
, desc
, record
):
2519 return super().match(desc
=desc
, record
=record
, etalon
="dw")
2521 def assemble(self
, insn
):
2522 selector
= insn
.select(record
=self
.record
)
2523 selector
.elwidth
= self
.width
.value
2526 @_dataclasses.dataclass(eq
=True, frozen
=True)
2527 class SpecifierSubVL(Specifier
):
2531 def match(cls
, desc
, record
):
2533 value
= _SVP64SubVL(desc
)
2537 return cls(record
=record
, value
=value
)
2539 def assemble(self
, insn
):
2540 selector
= insn
.select(record
=self
.record
)
2541 selector
.subvl
= int(self
.value
.value
)
2544 @_dataclasses.dataclass(eq
=True, frozen
=True)
2545 class SpecifierPredicate(Specifier
):
2550 def match(cls
, desc
, record
, mode_match
, pred_match
):
2551 (mode
, _
, pred
) = desc
.partition("=")
2554 if not mode_match(mode
):
2557 pred
= _SVP64Pred(pred
.strip())
2558 if not pred_match(pred
):
2559 raise ValueError(pred
)
2561 return cls(record
=record
, mode
=mode
, pred
=pred
)
2564 @_dataclasses.dataclass(eq
=True, frozen
=True)
2565 class SpecifierFF(SpecifierPredicate
):
2567 def match(cls
, desc
, record
):
2568 return super().match(desc
=desc
, record
=record
,
2569 mode_match
=lambda mode_arg
: mode_arg
== "ff",
2570 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2575 def assemble(self
, insn
):
2576 selector
= insn
.select(record
=self
.record
)
2577 if selector
.mode
.sel
!= 0:
2578 raise ValueError("cannot override mode")
2579 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2580 selector
.mode
.sel
= 0b01
2581 # HACK: please finally provide correct logic for CRs.
2582 if self
.pred
in (_SVP64Pred
.RC1
, _SVP64Pred
.RC1_N
):
2583 selector
.mode
[2] = (self
.pred
is _SVP64Pred
.RC1_N
)
2585 selector
.mode
[2] = self
.pred
.inv
2586 selector
.mode
[3, 4] = self
.pred
.state
2588 selector
.mode
.sel
= 0b01 if self
.mode
== "ff" else 0b11
2589 selector
.inv
= self
.pred
.inv
2591 selector
.CR
= self
.pred
.state
2593 selector
.RC1
= self
.pred
.state
2596 @_dataclasses.dataclass(eq
=True, frozen
=True)
2597 class SpecifierMask(SpecifierPredicate
):
2599 def match(cls
, desc
, record
, mode
):
2600 return super().match(desc
=desc
, record
=record
,
2601 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2602 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2607 def assemble(self
, insn
):
2608 raise NotImplementedError()
2611 @_dataclasses.dataclass(eq
=True, frozen
=True)
2612 class SpecifierM(SpecifierMask
):
2614 def match(cls
, desc
, record
):
2615 return super().match(desc
=desc
, record
=record
, mode
="m")
2617 def validate(self
, others
):
2619 if isinstance(spec
, SpecifierSM
):
2620 raise ValueError("source-mask and predicate mask conflict")
2621 elif isinstance(spec
, SpecifierDM
):
2622 raise ValueError("dest-mask and predicate mask conflict")
2624 def assemble(self
, insn
):
2625 selector
= insn
.select(record
=self
.record
)
2626 selector
.mask
= int(self
.pred
)
2627 if ((self
.record
.ptype
is _SVPType
.P2
) and
2628 (self
.record
.svp64
.mode
is not _SVMode
.BRANCH
)):
2629 selector
.smask
= int(self
.pred
)
2630 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2633 @_dataclasses.dataclass(eq
=True, frozen
=True)
2634 class SpecifierSM(SpecifierMask
):
2636 def match(cls
, desc
, record
):
2637 return super().match(desc
=desc
, record
=record
, mode
="sm")
2639 def validate(self
, others
):
2640 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2641 raise ValueError("source-mask on non-twin predicate")
2643 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2646 if isinstance(spec
, SpecifierDM
):
2650 raise ValueError("missing dest-mask in CR twin predication")
2651 if self
.pred
.mode
!= twin
.pred
.mode
:
2652 raise ValueError(f
"predicate masks mismatch: "
2653 f
"{self.pred!r} vs {twin.pred!r}")
2655 def assemble(self
, insn
):
2656 selector
= insn
.select(record
=self
.record
)
2657 selector
.smask
= int(self
.pred
)
2658 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2661 @_dataclasses.dataclass(eq
=True, frozen
=True)
2662 class SpecifierDM(SpecifierMask
):
2664 def match(cls
, desc
, record
):
2665 return super().match(desc
=desc
, record
=record
, mode
="dm")
2667 def validate(self
, others
):
2668 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2669 raise ValueError("dest-mask on non-twin predicate")
2671 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2674 if isinstance(spec
, SpecifierSM
):
2678 raise ValueError("missing source-mask in CR twin predication")
2679 if self
.pred
.mode
!= twin
.pred
.mode
:
2680 raise ValueError(f
"predicate masks mismatch: "
2681 f
"{self.pred!r} vs {twin.pred!r}")
2683 def assemble(self
, insn
):
2684 selector
= insn
.select(record
=self
.record
)
2685 selector
.mask
= int(self
.pred
)
2686 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2689 @_dataclasses.dataclass(eq
=True, frozen
=True)
2690 class SpecifierZZ(Specifier
):
2692 def match(cls
, desc
, record
):
2696 return cls(record
=record
)
2698 def validate(self
, others
):
2700 # Since zz takes precedence (overrides) sz and dz,
2701 # treat them as mutually exclusive.
2702 if isinstance(spec
, (SpecifierSZ
, SpecifierDZ
)):
2703 raise ValueError("mutually exclusive predicate masks")
2705 def assemble(self
, insn
):
2706 selector
= insn
.select(record
=self
.record
)
2707 if hasattr(selector
, "zz"): # this should be done in a different way
2714 @_dataclasses.dataclass(eq
=True, frozen
=True)
2715 class SpecifierXZ(Specifier
):
2717 hint
: str = _dataclasses
.field(repr=False)
2720 def match(cls
, desc
, record
, etalon
, hint
):
2724 return cls(desc
=desc
, record
=record
, hint
=hint
)
2726 def validate(self
, others
):
2727 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2728 raise ValueError(f
"{self.hint} on non-twin predicate")
2730 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2733 if isinstance(spec
, SpecifierXZ
):
2737 raise ValueError(f
"missing {self.hint} in CR twin predication")
2738 if self
.pred
!= twin
.pred
:
2739 raise ValueError(f
"predicate masks mismatch: "
2740 f
"{self.pred!r} vs {twin.pred!r}")
2742 def assemble(self
, insn
):
2743 selector
= insn
.select(record
=self
.record
)
2744 setattr(selector
, self
.desc
, 1)
2747 @_dataclasses.dataclass(eq
=True, frozen
=True)
2748 class SpecifierSZ(SpecifierXZ
):
2750 def match(cls
, desc
, record
):
2751 return super().match(desc
=desc
, record
=record
,
2752 etalon
="sz", hint
="source-mask")
2754 def validate(self
, others
):
2756 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2757 if isinstance(spec
, SpecifierFF
):
2758 raise ValueError("source-zero not allowed in ff mode")
2761 @_dataclasses.dataclass(eq
=True, frozen
=True)
2762 class SpecifierDZ(SpecifierXZ
):
2764 def match(cls
, desc
, record
):
2765 return super().match(desc
=desc
, record
=record
,
2766 etalon
="dz", hint
="dest-mask")
2768 def validate(self
, others
):
2770 if ((self
.record
.svp64
.mode
is not _SVMode
.CROP
) and
2771 isinstance(spec
, SpecifierFF
) and
2772 (spec
.pred
.mode
is _SVP64PredMode
.RC1
)):
2773 raise ValueError(f
"dest-zero not allowed in ff mode BO")
2776 @_dataclasses.dataclass(eq
=True, frozen
=True)
2777 class SpecifierEls(Specifier
):
2779 def match(cls
, desc
, record
):
2783 if record
.svp64
.mode
not in (_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
):
2784 raise ValueError("els is only valid in ld/st modes, not "
2785 "%s" % str(self
.record
.svp64
.mode
))
2787 return cls(record
=record
)
2789 def assemble(self
, insn
):
2790 if self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
: # stride mode
2791 insn
.prefix
.rm
.mode
[1] = 0
2793 selector
= insn
.select(record
=self
.record
)
2798 @_dataclasses.dataclass(eq
=True, frozen
=True)
2799 class SpecifierSEA(Specifier
):
2801 def match(cls
, desc
, record
):
2805 return cls(record
=record
)
2807 def validate(self
, others
):
2808 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
:
2809 raise ValueError("sea is only valid in ld/st modes, not "
2810 "%s" % str(self
.record
.svp64
.mode
))
2813 if isinstance(spec
, SpecifierFF
):
2814 raise ValueError(f
"sea cannot be used in ff mode")
2816 def assemble(self
, insn
):
2817 selector
= insn
.select(record
=self
.record
)
2818 if selector
.mode
.sel
not in (0b10, 0b00):
2819 raise ValueError("sea is only valid for normal and els modes, "
2820 "not %d" % int(selector
.mode
.sel
))
2824 @_dataclasses.dataclass(eq
=True, frozen
=True)
2825 class SpecifierSat(Specifier
):
2830 def match(cls
, desc
, record
, etalon
, sign
):
2834 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.LDST_IMM
,
2836 raise ValueError("only normal, ld/st imm and "
2837 "ld/st idx modes supported")
2839 return cls(record
=record
, desc
=desc
, sign
=sign
)
2841 def assemble(self
, insn
):
2842 selector
= insn
.select(record
=self
.record
)
2843 selector
.mode
[0] = 0b1
2844 selector
.mode
[1] = 0b0
2845 selector
.N
= int(self
.sign
)
2848 @_dataclasses.dataclass(eq
=True, frozen
=True)
2849 class SpecifierSatS(SpecifierSat
):
2851 def match(cls
, desc
, record
):
2852 return super().match(desc
=desc
, record
=record
,
2853 etalon
="sats", sign
=True)
2856 @_dataclasses.dataclass(eq
=True, frozen
=True)
2857 class SpecifierSatU(SpecifierSat
):
2859 def match(cls
, desc
, record
):
2860 return super().match(desc
=desc
, record
=record
,
2861 etalon
="satu", sign
=False)
2864 @_dataclasses.dataclass(eq
=True, frozen
=True)
2865 class SpecifierMapReduce(Specifier
):
2869 def match(cls
, record
, RG
):
2870 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2871 raise ValueError("only normal and crop modes supported")
2873 return cls(record
=record
, RG
=RG
)
2875 def assemble(self
, insn
):
2876 selector
= insn
.select(record
=self
.record
)
2877 if self
.record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
2878 raise ValueError("only normal and crop modes supported")
2879 selector
.mode
[0] = 0
2880 selector
.mode
[1] = 0
2881 selector
.mode
[2] = 1
2882 selector
.RG
= self
.RG
2885 @_dataclasses.dataclass(eq
=True, frozen
=True)
2886 class SpecifierMR(SpecifierMapReduce
):
2888 def match(cls
, desc
, record
):
2892 return super().match(record
=record
, RG
=False)
2895 @_dataclasses.dataclass(eq
=True, frozen
=True)
2896 class SpecifierMRR(SpecifierMapReduce
):
2898 def match(cls
, desc
, record
):
2902 return super().match(record
=record
, RG
=True)
2905 @_dataclasses.dataclass(eq
=True, frozen
=True)
2906 class SpecifierBranch(Specifier
):
2908 def match(cls
, desc
, record
, etalon
):
2912 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
2913 raise ValueError("only branch modes supported")
2915 return cls(record
=record
)
2918 @_dataclasses.dataclass(eq
=True, frozen
=True)
2919 class SpecifierAll(SpecifierBranch
):
2921 def match(cls
, desc
, record
):
2922 return super().match(desc
=desc
, record
=record
, etalon
="all")
2924 def assemble(self
, insn
):
2925 selector
= insn
.select(record
=self
.record
)
2929 @_dataclasses.dataclass(eq
=True, frozen
=True)
2930 class SpecifierSNZ(Specifier
):
2932 def match(cls
, desc
, record
):
2936 if record
.svp64
.mode
not in (_SVMode
.BRANCH
, _SVMode
.CROP
):
2937 raise ValueError("only branch and crop modes supported")
2939 return cls(record
=record
)
2941 def assemble(self
, insn
):
2942 selector
= insn
.select(record
=self
.record
)
2943 if self
.record
.svp64
.mode
in (_SVMode
.CROP
, _SVMode
.BRANCH
):
2945 if self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
2948 raise ValueError("only branch and crop modes supported")
2951 @_dataclasses.dataclass(eq
=True, frozen
=True)
2952 class SpecifierSL(SpecifierBranch
):
2954 def match(cls
, desc
, record
):
2955 return super().match(desc
=desc
, record
=record
, etalon
="sl")
2957 def assemble(self
, insn
):
2958 selector
= insn
.select(record
=self
.record
)
2962 @_dataclasses.dataclass(eq
=True, frozen
=True)
2963 class SpecifierSLu(SpecifierBranch
):
2965 def match(cls
, desc
, record
):
2966 return super().match(desc
=desc
, record
=record
, etalon
="slu")
2968 def assemble(self
, insn
):
2969 selector
= insn
.select(record
=self
.record
)
2973 @_dataclasses.dataclass(eq
=True, frozen
=True)
2974 class SpecifierLRu(SpecifierBranch
):
2976 def match(cls
, desc
, record
):
2977 return super().match(desc
=desc
, record
=record
, etalon
="lru")
2979 def assemble(self
, insn
):
2980 selector
= insn
.select(record
=self
.record
)
2984 @_dataclasses.dataclass(eq
=True, frozen
=True)
2985 class SpecifierVSXX(SpecifierBranch
):
2990 def match(cls
, desc
, record
, etalon
, VSb
, VLi
):
2994 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
2995 raise ValueError("only branch modes supported")
2997 return cls(record
=record
, VSb
=VSb
, VLi
=VLi
)
2999 def assemble(self
, insn
):
3000 selector
= insn
.select(record
=self
.record
)
3002 selector
.VSb
= int(self
.VSb
)
3003 selector
.VLi
= int(self
.VLi
)
3006 @_dataclasses.dataclass(eq
=True, frozen
=True)
3007 class SpecifierVS(SpecifierVSXX
):
3009 def match(cls
, desc
, record
):
3010 return super().match(desc
=desc
, record
=record
,
3011 etalon
="vs", VSb
=False, VLi
=False)
3014 @_dataclasses.dataclass(eq
=True, frozen
=True)
3015 class SpecifierVSi(SpecifierVSXX
):
3017 def match(cls
, desc
, record
):
3018 return super().match(desc
=desc
, record
=record
,
3019 etalon
="vsi", VSb
=False, VLi
=True)
3022 @_dataclasses.dataclass(eq
=True, frozen
=True)
3023 class SpecifierVSb(SpecifierVSXX
):
3025 def match(cls
, desc
, record
):
3026 return super().match(desc
=desc
, record
=record
,
3027 etalon
="vsb", VSb
=True, VLi
=False)
3030 @_dataclasses.dataclass(eq
=True, frozen
=True)
3031 class SpecifierVSbi(SpecifierVSXX
):
3033 def match(cls
, desc
, record
):
3034 return super().match(desc
=desc
, record
=record
,
3035 etalon
="vsbi", VSb
=True, VLi
=True)
3038 @_dataclasses.dataclass(eq
=True, frozen
=True)
3039 class SpecifierCTX(Specifier
):
3043 def match(cls
, desc
, record
, etalon
, CTi
):
3047 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3048 raise ValueError("only branch modes supported")
3050 return cls(record
=record
, CTi
=CTi
)
3052 def assemble(self
, insn
):
3053 selector
= insn
.select(record
=self
.record
)
3055 selector
.CTi
= int(self
.CTi
)
3058 @_dataclasses.dataclass(eq
=True, frozen
=True)
3059 class SpecifierCTR(SpecifierCTX
):
3061 def match(cls
, desc
, record
):
3062 return super().match(desc
=desc
, record
=record
,
3063 etalon
="ctr", CTi
=False)
3066 @_dataclasses.dataclass(eq
=True, frozen
=True)
3067 class SpecifierCTi(SpecifierCTX
):
3069 def match(cls
, desc
, record
):
3070 return super().match(desc
=desc
, record
=record
,
3071 etalon
="cti", CTi
=True)
3074 @_dataclasses.dataclass(eq
=True, frozen
=True)
3075 class SpecifierPI(Specifier
):
3077 def match(cls
, desc
, record
):
3081 if record
.svp64
.mode
not in [_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
]:
3082 raise ValueError("only ld/st imm/idx mode supported")
3084 return cls(record
=record
)
3086 def assemble(self
, insn
):
3087 selector
= insn
.select(record
=self
.record
)
3088 selector
.mode
[2] = 0b1
3092 @_dataclasses.dataclass(eq
=True, frozen
=True)
3093 class SpecifierLF(Specifier
):
3095 def match(cls
, desc
, record
):
3099 if record
.svp64
.mode
is not _SVMode
.LDST_IMM
:
3100 raise ValueError("only ld/st imm mode supported")
3102 return cls(record
=record
)
3104 def assemble(self
, insn
):
3105 selector
= insn
.select(record
=self
.record
)
3106 selector
.mode
[1] = 0
3110 @_dataclasses.dataclass(eq
=True, frozen
=True)
3111 class SpecifierVLi(Specifier
):
3113 def match(cls
, desc
, record
):
3117 return cls(record
=record
)
3119 def validate(self
, others
):
3121 if isinstance(spec
, SpecifierFF
):
3124 raise ValueError("VLi only allowed in failfirst")
3126 def assemble(self
, insn
):
3127 selector
= insn
.select(record
=self
.record
)
3128 selector
.mode
[1] = 1
3132 class Specifiers(tuple):
3167 def __new__(cls
, items
, record
):
3168 def transform(item
):
3169 for spec_cls
in cls
.SPECS
:
3170 spec
= spec_cls
.match(item
, record
=record
)
3171 if spec
is not None:
3173 raise ValueError(item
)
3175 # TODO: remove this hack
3176 items
= dict.fromkeys(items
)
3180 items
= tuple(items
)
3182 specs
= tuple(map(transform
, items
))
3183 for (index
, spec
) in enumerate(specs
):
3184 head
= specs
[:index
]
3185 tail
= specs
[index
+ 1:]
3186 spec
.validate(others
=(head
+ tail
))
3188 return super().__new
__(cls
, specs
)
3191 class SVP64OperandMeta(type):
3192 class SVP64NonZeroOperand(NonZeroOperand
):
3193 def assemble(self
, insn
, value
):
3194 if isinstance(value
, str):
3195 value
= int(value
, 0)
3196 if not isinstance(value
, int):
3197 raise ValueError("non-integer operand")
3199 # FIXME: this is really weird
3200 if self
.record
.name
in ("svstep", "svstep."):
3201 value
+= 1 # compensation
3203 return super().assemble(value
=value
, insn
=insn
)
3205 class SVP64XOStaticOperand(SpanStaticOperand
):
3206 def __init__(self
, record
, value
, span
):
3207 return super().__init
__(record
=record
, name
="XO",
3208 value
=value
, span
=span
)
3211 NonZeroOperand
: SVP64NonZeroOperand
,
3212 XOStaticOperand
: SVP64XOStaticOperand
,
3215 def __new__(metacls
, name
, bases
, ns
):
3217 for (index
, base_cls
) in enumerate(bases
):
3218 bases
[index
] = metacls
.__TRANSFORM
.get(base_cls
, base_cls
)
3220 bases
= tuple(bases
)
3222 return super().__new
__(metacls
, name
, bases
, ns
)
3225 class SVP64Operand(Operand
, metaclass
=SVP64OperandMeta
):
3228 return tuple(map(lambda bit
: (bit
+ 32), super().span
))
3232 def __init__(self
, insn
, record
):
3234 self
.__record
= record
3235 return super().__init
__()
3238 return self
.rm
.__doc
__
3241 return repr(self
.rm
)
3249 return self
.__record
3253 rm
= getattr(self
.insn
.prefix
.rm
, self
.record
.svp64
.mode
.name
.lower())
3255 # The idea behind these tables is that they are now literally
3256 # in identical format to insndb.csv and minor_xx.csv and can
3257 # be done precisely as that. The only thing to watch out for
3258 # is the insertion of Rc=1 as a "mask/value" bit and likewise
3259 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
3262 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
3263 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3264 # mode Rc mask Rc member
3266 (0b000000, 0b111000, "simple"), # simple (no Rc)
3267 (0b001000, 0b111100, "mr"), # mapreduce (no Rc)
3268 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3269 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3270 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3271 (0b001100, 0b111100, "rsvd"), # reserved
3273 mode
= int(self
.insn
.prefix
.rm
.normal
.mode
)
3274 search
= ((mode
<< 1) | self
.record
.Rc
)
3276 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
3277 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3278 # mode Rc mask Rc member
3279 # ironically/coincidentally this table is identical to NORMAL
3280 # mode except reserved in place of mr
3282 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3283 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3284 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3286 search
= ((int(self
.insn
.prefix
.rm
.ldst_imm
.mode
) << 1) |
3289 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
3290 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3291 # mode Rc mask Rc member
3293 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3294 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3295 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3297 search
= ((int(self
.insn
.prefix
.rm
.ldst_idx
.mode
) << 1) |
3300 elif self
.record
.svp64
.mode
is _SVMode
.CROP
:
3301 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
3302 # mode 3b mask 3b member
3304 (0b000000, 0b111000, "simple"), # simple
3305 (0b001000, 0b111000, "mr"), # mapreduce
3306 (0b010001, 0b010001, "ff3"), # ffirst, 3-bit CR
3307 (0b010000, 0b010000, "ff5"), # ffirst, 5-bit CR
3309 search
= ((int(self
.insn
.prefix
.rm
.crop
.mode
) << 1) |
3310 int(self
.record
.svp64
.extra_CR_3bit
))
3312 elif self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3316 (0b00, 0b11, "simple"), # simple
3317 (0b01, 0b11, "vls"), # VLset
3318 (0b10, 0b11, "ctr"), # CTR mode
3319 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
3321 # slightly weird: doesn't have a 5-bit "mode" field like others
3322 search
= int(self
.insn
.prefix
.rm
.branch
.mode
.sel
)
3325 if table
is not None:
3326 for (value
, mask
, field
) in table
:
3327 if field
.startswith("rsvd"):
3329 if ((value
& mask
) == (search
& mask
)):
3330 return getattr(rm
, field
)
3334 def __getattr__(self
, key
):
3335 if key
.startswith(f
"_{self.__class__.__name__}__"):
3336 return super().__getattribute
__(key
)
3338 return getattr(self
.rm
, key
)
3340 def __setattr__(self
, key
, value
):
3341 if key
.startswith(f
"_{self.__class__.__name__}__"):
3342 return super().__setattr
__(key
, value
)
3345 if not hasattr(rm
, key
):
3346 raise AttributeError(key
)
3348 return setattr(rm
, key
, value
)
3351 class SVP64Instruction(PrefixedInstruction
):
3352 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
3353 class Prefix(PrefixedInstruction
.Prefix
):
3355 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
3359 def select(self
, record
):
3360 return RMSelector(insn
=self
, record
=record
)
3365 for idx
in range(64):
3366 bit
= int(self
[idx
])
3368 return "".join(map(str, bits
))
3371 def assemble(cls
, record
, arguments
=None, specifiers
=None):
3372 insn
= super().assemble(record
=record
, arguments
=arguments
)
3374 specifiers
= Specifiers(items
=specifiers
, record
=record
)
3375 for specifier
in specifiers
:
3376 specifier
.assemble(insn
=insn
)
3378 insn
.prefix
.PO
= 0x1
3379 insn
.prefix
.id = 0x3
3383 def disassemble(self
, record
,
3385 style
=Style
.NORMAL
):
3387 if style
<= Style
.SHORT
:
3390 blob
= insn
.bytes(byteorder
=byteorder
)
3391 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
3394 blob_prefix
= blob(self
.prefix
)
3395 blob_suffix
= blob(self
.suffix
)
3397 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3398 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
3401 assert record
.svp64
is not None
3403 name
= f
"sv.{record.name}"
3405 rm
= self
.select(record
=record
)
3407 # convert specifiers to /x/y/z (sorted lexicographically)
3408 specifiers
= sorted(rm
.specifiers(record
=record
))
3409 if specifiers
: # if any add one extra to get the extra "/"
3410 specifiers
= ([""] + specifiers
)
3411 specifiers
= "/".join(specifiers
)
3413 # convert operands to " ,x,y,z"
3414 operands
= tuple(map(_operator
.itemgetter(1),
3415 self
.spec_dynamic_operands(record
=record
, style
=style
)))
3416 operands
= ",".join(operands
)
3417 if len(operands
) > 0: # if any separate with a space
3418 operands
= (" " + operands
)
3420 if style
<= Style
.LEGACY
:
3421 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3422 suffix
= WordInstruction
.integer(value
=int(self
.suffix
))
3423 yield from suffix
.disassemble(record
=record
,
3424 byteorder
=byteorder
, style
=style
)
3426 yield f
"{blob_prefix}{name}{specifiers}{operands}"
3428 yield f
"{blob_suffix}"
3430 if style
>= Style
.VERBOSE
:
3432 binary
= self
.binary
3433 spec
= self
.spec(record
=record
, prefix
="sv.")
3435 yield f
"{indent}spec"
3436 yield f
"{indent}{indent}{spec}"
3437 yield f
"{indent}pcode"
3438 for stmt
in record
.mdwn
.pcode
:
3439 yield f
"{indent}{indent}{stmt}"
3440 yield f
"{indent}binary"
3441 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
3442 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
3443 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
3444 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
3445 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
3446 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
3447 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
3448 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
3449 yield f
"{indent}opcodes"
3450 for opcode
in record
.opcodes
:
3451 yield f
"{indent}{indent}{opcode!r}"
3452 for operand
in self
.operands(record
=record
):
3453 yield from operand
.disassemble(insn
=self
,
3454 style
=style
, indent
=indent
)
3456 yield f
"{indent}{indent}{str(rm)}"
3457 for line
in rm
.disassemble(style
=style
):
3458 yield f
"{indent}{indent}{line}"
3462 def operands(cls
, record
):
3463 for operand
in super().operands(record
=record
):
3464 parent
= operand
.__class
__
3465 name
= f
"SVP64{parent.__name__}"
3466 bases
= (SVP64Operand
, parent
)
3467 child
= type(name
, bases
, {})
3468 yield child(**dict(operand
))
3471 def parse(stream
, factory
):
3473 return ("TODO" not in frozenset(entry
.values()))
3475 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
3476 entries
= _csv
.DictReader(lines
)
3477 entries
= filter(match
, entries
)
3478 return tuple(map(factory
, entries
))
3481 class MarkdownDatabase
:
3484 for (name
, desc
) in _ISA():
3487 (dynamic
, *static
) = desc
.regs
3488 operands
.extend(dynamic
)
3489 operands
.extend(static
)
3490 pcode
= PCode(iterable
=filter(str.strip
, desc
.pcode
))
3491 operands
= Operands(insn
=name
, operands
=operands
)
3492 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
3494 self
.__db
= dict(sorted(db
.items()))
3496 return super().__init
__()
3499 yield from self
.__db
.items()
3501 def __contains__(self
, key
):
3502 return self
.__db
.__contains
__(key
)
3504 def __getitem__(self
, key
):
3505 return self
.__db
.__getitem
__(key
)
3508 class FieldsDatabase
:
3511 df
= _DecodeFields()
3513 for (form
, fields
) in df
.instrs
.items():
3514 if form
in {"DQE", "TX"}:
3518 db
[_Form
[form
]] = Fields(fields
)
3522 return super().__init
__()
3524 def __getitem__(self
, key
):
3525 return self
.__db
.__getitem
__(key
)
3529 def __init__(self
, root
, mdwndb
):
3530 # The code below groups the instructions by name:section.
3531 # There can be multiple names for the same instruction.
3532 # The point is to capture different opcodes for the same instruction.
3534 records
= _collections
.defaultdict(set)
3535 path
= (root
/ "insndb.csv")
3536 with
open(path
, "r", encoding
="UTF-8") as stream
:
3537 for section
in sorted(parse(stream
, Section
.CSV
)):
3538 path
= (root
/ section
.path
)
3540 section
.Mode
.INTEGER
: IntegerOpcode
,
3541 section
.Mode
.PATTERN
: PatternOpcode
,
3543 factory
= _functools
.partial(
3544 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
3545 with
open(path
, "r", encoding
="UTF-8") as stream
:
3546 for insn
in parse(stream
, factory
):
3547 for name
in insn
.names
:
3548 records
[name
].add(insn
)
3549 sections
[name
] = section
3551 items
= sorted(records
.items())
3553 for (name
, multirecord
) in items
:
3554 records
[name
] = PPCMultiRecord(sorted(multirecord
))
3556 def exact_match(name
):
3557 record
= records
.get(name
)
3563 if not name
.endswith("l"):
3565 alias
= exact_match(name
[:-1])
3568 record
= records
[alias
]
3569 if "lk" not in record
.flags
:
3570 raise ValueError(record
)
3574 if not name
.endswith("a"):
3576 alias
= LK_match(name
[:-1])
3579 record
= records
[alias
]
3580 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
3581 raise ValueError(record
)
3582 if "AA" not in mdwndb
[name
].operands
:
3583 raise ValueError(record
)
3587 if not name
.endswith("."):
3589 alias
= exact_match(name
[:-1])
3592 record
= records
[alias
]
3593 if record
.Rc
is _RCOE
.NONE
:
3594 raise ValueError(record
)
3598 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
3599 for (name
, _
) in mdwndb
:
3600 if name
.startswith("sv."):
3603 for match
in matches
:
3605 if alias
is not None:
3609 section
= sections
[alias
]
3610 record
= records
[alias
]
3611 db
[name
] = (section
, record
)
3613 self
.__db
= dict(sorted(db
.items()))
3615 return super().__init
__()
3617 @_functools.lru_cache(maxsize
=512, typed
=False)
3618 def __getitem__(self
, key
):
3619 return self
.__db
.get(key
, (None, None))
3622 class SVP64Database
:
3623 def __init__(self
, root
, ppcdb
):
3625 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
3626 for (prefix
, _
, names
) in _os
.walk(root
):
3627 prefix
= _pathlib
.Path(prefix
)
3628 for name
in filter(lambda name
: pattern
.match(name
), names
):
3629 path
= (prefix
/ _pathlib
.Path(name
))
3630 with
open(path
, "r", encoding
="UTF-8") as stream
:
3631 db
.update(parse(stream
, SVP64Record
.CSV
))
3632 db
= {record
.name
:record
for record
in db
}
3634 self
.__db
= dict(sorted(db
.items()))
3635 self
.__ppcdb
= ppcdb
3637 return super().__init
__()
3639 def __getitem__(self
, key
):
3640 (_
, record
) = self
.__ppcdb
[key
]
3644 for name
in record
.names
:
3645 record
= self
.__db
.get(name
, None)
3646 if record
is not None:
3653 def __init__(self
, root
):
3654 root
= _pathlib
.Path(root
)
3655 mdwndb
= MarkdownDatabase()
3656 fieldsdb
= FieldsDatabase()
3657 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
3658 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
3662 opcodes
= _collections
.defaultdict(
3663 lambda: _collections
.defaultdict(set))
3665 for (name
, mdwn
) in mdwndb
:
3666 if name
.startswith("sv."):
3668 (section
, ppc
) = ppcdb
[name
]
3671 svp64
= svp64db
[name
]
3672 fields
= fieldsdb
[ppc
.form
]
3673 record
= Record(name
=name
,
3674 section
=section
, ppc
=ppc
, svp64
=svp64
,
3675 mdwn
=mdwn
, fields
=fields
)
3677 names
[record
.name
] = record
3678 opcodes
[section
][record
.PO
].add(record
)
3680 self
.__db
= sorted(db
)
3681 self
.__names
= dict(sorted(names
.items()))
3682 self
.__opcodes
= dict(sorted(opcodes
.items()))
3684 return super().__init
__()
3687 return repr(self
.__db
)
3690 yield from self
.__db
3692 @_functools.lru_cache(maxsize
=None)
3693 def __contains__(self
, key
):
3694 return self
.__getitem
__(key
) is not None
3696 @_functools.lru_cache(maxsize
=None)
3697 def __getitem__(self
, key
):
3698 if isinstance(key
, SVP64Instruction
):
3701 if isinstance(key
, Instruction
):
3704 sections
= sorted(self
.__opcodes
)
3705 for section
in sections
:
3706 group
= self
.__opcodes
[section
]
3707 for record
in group
[PO
]:
3708 if record
.match(key
=key
):
3713 elif isinstance(key
, str):
3714 return self
.__names
.get(key
)
3716 raise ValueError("instruction or name expected")