1 import collections
as _collections
3 import dataclasses
as _dataclasses
5 import functools
as _functools
6 import itertools
as _itertools
8 import operator
as _operator
9 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 SVmask_src
as _SVmask_src
,
38 SVP64RMMode
as _SVP64RMMode
,
39 SVExtraRegType
as _SVExtraRegType
,
40 SVExtraReg
as _SVExtraReg
,
41 SVP64Predicate
as _SVP64Predicate
,
42 SVP64PredicateType
as _SVP64PredicateType
,
44 from openpower
.decoder
.selectable_int
import (
45 SelectableInt
as _SelectableInt
,
46 selectconcat
as _selectconcat
,
48 from openpower
.decoder
.power_fields
import (
51 DecodeFields
as _DecodeFields
,
53 from openpower
.decoder
.pseudo
.pagereader
import ISA
as _ISA
56 @_functools.total_ordering
57 class Verbosity(_enum
.Enum
):
60 VERBOSE
= _enum
.auto()
62 def __lt__(self
, other
):
63 if not isinstance(other
, self
.__class
__):
65 return (self
.value
< other
.value
)
68 @_functools.total_ordering
69 class Priority(_enum
.Enum
):
75 def _missing_(cls
, value
):
76 if isinstance(value
, str):
81 return super()._missing
_(value
)
83 def __lt__(self
, other
):
84 if not isinstance(other
, self
.__class
__):
87 # NOTE: the order is inversed, LOW < NORMAL < HIGH
88 return (self
.value
> other
.value
)
91 def dataclass(cls
, record
, keymap
=None, typemap
=None):
95 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
97 def transform(key_value
):
98 (key
, value
) = key_value
99 key
= keymap
.get(key
, key
)
100 hook
= typemap
.get(key
, lambda value
: value
)
101 if hook
is bool and value
in ("", "0"):
107 record
= dict(map(transform
, record
.items()))
108 for key
in frozenset(record
.keys()):
109 if record
[key
] == "":
115 @_functools.total_ordering
116 @_dataclasses.dataclass(eq
=True, frozen
=True)
119 def __new__(cls
, value
):
120 if isinstance(value
, str):
121 value
= int(value
, 0)
122 if not isinstance(value
, int):
123 raise ValueError(value
)
125 if value
.bit_length() > 64:
126 raise ValueError(value
)
128 return super().__new
__(cls
, value
)
131 return self
.__repr
__()
134 return f
"{self:0{self.bit_length()}b}"
136 def bit_length(self
):
137 if super().bit_length() > 32:
141 class Value(Integer
):
150 def __lt__(self
, other
):
151 if not isinstance(other
, Opcode
):
152 return NotImplemented
153 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
156 def pattern(value
, mask
, bit_length
):
157 for bit
in range(bit_length
):
158 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
160 elif (value
& (1 << (bit_length
- bit
- 1))):
165 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
167 def match(self
, key
):
168 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
171 class IntegerOpcode(Opcode
):
172 def __init__(self
, value
):
173 if value
.startswith("0b"):
174 mask
= int(("1" * len(value
[2:])), 2)
178 value
= Opcode
.Value(value
)
179 mask
= Opcode
.Mask(mask
)
181 return super().__init
__(value
=value
, mask
=mask
)
184 class PatternOpcode(Opcode
):
185 def __init__(self
, pattern
):
186 if not isinstance(pattern
, str):
187 raise ValueError(pattern
)
189 (value
, mask
) = (0, 0)
190 for symbol
in pattern
:
191 if symbol
not in {"0", "1", "-"}:
192 raise ValueError(pattern
)
193 value |
= (symbol
== "1")
194 mask |
= (symbol
!= "-")
200 value
= Opcode
.Value(value
)
201 mask
= Opcode
.Mask(mask
)
203 return super().__init
__(value
=value
, mask
=mask
)
206 @_dataclasses.dataclass(eq
=True, frozen
=True)
208 class FlagsMeta(type):
223 class Flags(frozenset, metaclass
=FlagsMeta
):
224 def __new__(cls
, flags
=frozenset()):
225 flags
= frozenset(flags
)
226 diff
= (flags
- frozenset(cls
))
228 raise ValueError(flags
)
229 return super().__new
__(cls
, flags
)
233 flags
: Flags
= Flags()
235 function
: _Function
= _Function
.NONE
236 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
237 in1
: _In1Sel
= _In1Sel
.RA
238 in2
: _In2Sel
= _In2Sel
.NONE
239 in3
: _In3Sel
= _In3Sel
.NONE
240 out
: _OutSel
= _OutSel
.NONE
241 cr_in
: _CRInSel
= _CRInSel
.NONE
242 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
243 cr_out
: _CROutSel
= _CROutSel
.NONE
244 cry_in
: _CryIn
= _CryIn
.ZERO
245 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
246 upd
: _LDSTMode
= _LDSTMode
.NONE
247 Rc
: _RCOE
= _RCOE
.NONE
248 form
: _Form
= _Form
.NONE
250 unofficial
: bool = False
254 "internal op": "intop",
258 "ldst len": "ldst_len",
260 "CONDITIONS": "conditions",
263 def __lt__(self
, other
):
264 if not isinstance(other
, self
.__class
__):
265 return NotImplemented
266 lhs
= (self
.opcode
, self
.comment
)
267 rhs
= (other
.opcode
, other
.comment
)
271 def CSV(cls
, record
, opcode_cls
):
272 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
273 typemap
["opcode"] = opcode_cls
275 if record
["CR in"] == "BA_BB":
276 record
["cr_in"] = "BA"
277 record
["cr_in2"] = "BB"
281 for flag
in frozenset(PPCRecord
.Flags
):
282 if bool(record
.pop(flag
, "")):
284 record
["flags"] = PPCRecord
.Flags(flags
)
286 return dataclass(cls
, record
,
287 keymap
=PPCRecord
.__KEYMAP
,
292 return frozenset(self
.comment
.split("=")[-1].split("/"))
295 class PPCMultiRecord(tuple):
296 def __getattr__(self
, attr
):
298 raise AttributeError(attr
)
299 return getattr(self
[0], attr
)
302 @_dataclasses.dataclass(eq
=True, frozen
=True)
304 class ExtraMap(tuple):
306 @_dataclasses.dataclass(eq
=True, frozen
=True)
308 regtype
: _SVExtraRegType
= _SVExtraRegType
.NONE
309 reg
: _SVExtraReg
= _SVExtraReg
.NONE
312 return f
"{self.regtype.value}:{self.reg.name}"
314 def __new__(cls
, value
="0"):
315 if isinstance(value
, str):
316 def transform(value
):
317 (regtype
, reg
) = value
.split(":")
318 regtype
= _SVExtraRegType(regtype
)
319 reg
= _SVExtraReg(reg
)
320 return cls
.Entry(regtype
=regtype
, reg
=reg
)
325 value
= map(transform
, value
.split(";"))
327 return super().__new
__(cls
, value
)
330 return repr(list(self
))
332 def __new__(cls
, value
=tuple()):
336 return super().__new
__(cls
, map(cls
.Extra
, value
))
339 return repr({index
:self
[index
] for index
in range(0, 4)})
342 ptype
: _SVPtype
= _SVPtype
.NONE
343 etype
: _SVEtype
= _SVEtype
.NONE
344 msrc
: _SVmask_src
= _SVmask_src
.NO
# MASK_SRC is active
345 in1
: _In1Sel
= _In1Sel
.NONE
346 in2
: _In2Sel
= _In2Sel
.NONE
347 in3
: _In3Sel
= _In3Sel
.NONE
348 out
: _OutSel
= _OutSel
.NONE
349 out2
: _OutSel
= _OutSel
.NONE
350 cr_in
: _CRInSel
= _CRInSel
.NONE
351 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
352 cr_out
: _CROutSel
= _CROutSel
.NONE
353 extra
: ExtraMap
= ExtraMap()
355 mode
: _SVMode
= _SVMode
.NORMAL
359 "CONDITIONS": "conditions",
368 def CSV(cls
, record
):
369 for key
in frozenset({
370 "in1", "in2", "in3", "CR in",
371 "out", "out2", "CR out",
377 if record
["CR in"] == "BA_BB":
378 record
["cr_in"] = "BA"
379 record
["cr_in2"] = "BB"
383 for idx
in range(0, 4):
384 extra
.append(record
.pop(f
"{idx}"))
386 record
["extra"] = cls
.ExtraMap(extra
)
388 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
390 @_functools.lru_cache(maxsize
=None)
391 def extra_idx(self
, key
):
399 if key
not in frozenset({
400 "in1", "in2", "in3", "cr_in", "cr_in2",
401 "out", "out2", "cr_out",
405 sel
= getattr(self
, key
)
406 if sel
is _CRInSel
.BA_BB
:
407 return _SVExtra
.Idx_1_2
408 reg
= _SVExtraReg(sel
)
409 if reg
is _SVExtraReg
.NONE
:
413 _SVExtraRegType
.SRC
: {},
414 _SVExtraRegType
.DST
: {},
416 for index
in range(0, 4):
417 for entry
in self
.extra
[index
]:
418 extra_map
[entry
.regtype
][entry
.reg
] = extra_idx
[index
]
420 for regtype
in (_SVExtraRegType
.SRC
, _SVExtraRegType
.DST
):
421 extra
= extra_map
[regtype
].get(reg
, _SVExtra
.NONE
)
422 if extra
is not _SVExtra
.NONE
:
427 extra_idx_in1
= property(_functools
.partial(extra_idx
, key
="in1"))
428 extra_idx_in2
= property(_functools
.partial(extra_idx
, key
="in2"))
429 extra_idx_in3
= property(_functools
.partial(extra_idx
, key
="in3"))
430 extra_idx_out
= property(_functools
.partial(extra_idx
, key
="out"))
431 extra_idx_out2
= property(_functools
.partial(extra_idx
, key
="out2"))
432 extra_idx_cr_in
= property(_functools
.partial(extra_idx
, key
="cr_in"))
433 extra_idx_cr_in2
= property(_functools
.partial(extra_idx
, key
="cr_in2"))
434 extra_idx_cr_out
= property(_functools
.partial(extra_idx
, key
="cr_out"))
436 @_functools.lru_cache(maxsize
=None)
437 def extra_reg(self
, key
):
438 return _SVExtraReg(getattr(self
, key
))
440 extra_reg_in1
= property(_functools
.partial(extra_reg
, key
="in1"))
441 extra_reg_in2
= property(_functools
.partial(extra_reg
, key
="in2"))
442 extra_reg_in3
= property(_functools
.partial(extra_reg
, key
="in3"))
443 extra_reg_out
= property(_functools
.partial(extra_reg
, key
="out"))
444 extra_reg_out2
= property(_functools
.partial(extra_reg
, key
="out2"))
445 extra_reg_cr_in
= property(_functools
.partial(extra_reg
, key
="cr_in"))
446 extra_reg_cr_in2
= property(_functools
.partial(extra_reg
, key
="cr_in2"))
447 extra_reg_cr_out
= property(_functools
.partial(extra_reg
, key
="cr_out"))
452 for idx
in range(0, 4):
453 for entry
in self
.svp64
.extra
[idx
]:
454 if entry
.regtype
is _SVExtraRegType
.DST
:
455 if regtype
is not None:
456 raise ValueError(self
.svp64
)
457 regtype
= _RegType(entry
.reg
)
458 if regtype
not in (_RegType
.CR_5BIT
, _RegType
.CR_3BIT
):
459 raise ValueError(self
.svp64
)
460 return (regtype
is _RegType
.CR_3BIT
)
464 def __init__(self
, value
=(0, 32)):
465 if isinstance(value
, str):
466 (start
, end
) = map(int, value
.split(":"))
469 if start
< 0 or end
< 0 or start
>= end
:
470 raise ValueError(value
)
475 return super().__init
__()
478 return (self
.__end
- self
.__start
+ 1)
481 return f
"[{self.__start}:{self.__end}]"
484 yield from range(self
.start
, (self
.end
+ 1))
486 def __reversed__(self
):
487 return tuple(reversed(tuple(self
)))
498 @_dataclasses.dataclass(eq
=True, frozen
=True)
500 class Mode(_enum
.Enum
):
501 INTEGER
= _enum
.auto()
502 PATTERN
= _enum
.auto()
505 def _missing_(cls
, value
):
506 if isinstance(value
, str):
507 return cls
[value
.upper()]
508 return super()._missing
_(value
)
511 def __new__(cls
, value
=None):
512 if isinstance(value
, str):
513 if value
.upper() == "NONE":
516 value
= int(value
, 0)
520 return super().__new
__(cls
, value
)
526 return (bin(self
) if self
else "None")
532 opcode
: IntegerOpcode
= None
533 priority
: Priority
= Priority
.NORMAL
535 def __lt__(self
, other
):
536 if not isinstance(other
, self
.__class
__):
537 return NotImplemented
538 return (self
.priority
< other
.priority
)
541 def CSV(cls
, record
):
542 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
543 if record
["opcode"] == "NONE":
544 typemap
["opcode"] = lambda _
: None
546 return dataclass(cls
, record
, typemap
=typemap
)
550 def __init__(self
, items
):
551 if isinstance(items
, dict):
552 items
= items
.items()
555 (name
, bitrange
) = item
556 return (name
, tuple(bitrange
.values()))
558 self
.__mapping
= dict(map(transform
, items
))
560 return super().__init
__()
563 return repr(self
.__mapping
)
566 yield from self
.__mapping
.items()
568 def __contains__(self
, key
):
569 return self
.__mapping
.__contains
__(key
)
571 def __getitem__(self
, key
):
572 return self
.__mapping
.get(key
, None)
576 def __init__(self
, insn
, iterable
):
578 "b": {"target_addr": TargetAddrOperandLI
},
579 "ba": {"target_addr": TargetAddrOperandLI
},
580 "bl": {"target_addr": TargetAddrOperandLI
},
581 "bla": {"target_addr": TargetAddrOperandLI
},
582 "bc": {"target_addr": TargetAddrOperandBD
},
583 "bca": {"target_addr": TargetAddrOperandBD
},
584 "bcl": {"target_addr": TargetAddrOperandBD
},
585 "bcla": {"target_addr": TargetAddrOperandBD
},
586 "addpcis": {"D": DOperandDX
},
587 "fishmv": {"D": DOperandDX
},
588 "fmvis": {"D": DOperandDX
},
591 "SVi": NonZeroOperand
,
592 "SVd": NonZeroOperand
,
593 "SVxd": NonZeroOperand
,
594 "SVyd": NonZeroOperand
,
595 "SVzd": NonZeroOperand
,
597 "D": SignedImmediateOperand
,
601 "SIM": SignedOperand
,
602 "SVD": SignedOperand
,
603 "SVDS": SignedOperand
,
605 custom_immediates
= {
611 for operand
in iterable
:
615 (name
, value
) = operand
.split("=")
616 mapping
[name
] = (StaticOperand
, {
622 if name
.endswith(")"):
623 name
= name
.replace("(", " ").replace(")", "")
624 (immediate
, _
, name
) = name
.partition(" ")
628 if immediate
is not None:
629 cls
= custom_immediates
.get(immediate
, ImmediateOperand
)
631 if insn
in custom_insns
and name
in custom_insns
[insn
]:
632 cls
= custom_insns
[insn
][name
]
633 elif name
in custom_fields
:
634 cls
= custom_fields
[name
]
636 if name
in _RegType
.__members
__:
637 regtype
= _RegType
[name
]
638 if regtype
is _RegType
.GPR
:
640 elif regtype
is _RegType
.FPR
:
642 if regtype
is _RegType
.CR_5BIT
:
644 if regtype
is _RegType
.CR_3BIT
:
647 mapping
[name
] = (cls
, {"name": name
})
651 for (name
, (cls
, kwargs
)) in mapping
.items():
652 kwargs
= dict(kwargs
)
653 kwargs
["name"] = name
654 if issubclass(cls
, StaticOperand
):
655 static
.append((cls
, kwargs
))
656 elif issubclass(cls
, DynamicOperand
):
657 dynamic
.append((cls
, kwargs
))
659 raise ValueError(name
)
661 self
.__mapping
= mapping
662 self
.__static
= tuple(static
)
663 self
.__dynamic
= tuple(dynamic
)
665 return super().__init
__()
668 for (_
, items
) in self
.__mapping
.items():
669 (cls
, kwargs
) = items
673 return self
.__mapping
.__repr
__()
675 def __contains__(self
, key
):
676 return self
.__mapping
.__contains
__(key
)
678 def __getitem__(self
, key
):
679 return self
.__mapping
.__getitem
__(key
)
687 return self
.__dynamic
691 def __init__(self
, iterable
):
692 self
.__pcode
= tuple(iterable
)
693 return super().__init
__()
696 yield from self
.__pcode
699 return self
.__pcode
.__repr
__()
702 @_dataclasses.dataclass(eq
=True, frozen
=True)
703 class MarkdownRecord
:
708 @_functools.total_ordering
709 @_dataclasses.dataclass(eq
=True, frozen
=True)
716 svp64
: SVP64Record
= None
718 def __lt__(self
, other
):
719 if not isinstance(other
, Record
):
720 return NotImplemented
721 lhs
= (min(self
.opcodes
), self
.name
)
722 rhs
= (min(other
.opcodes
), other
.name
)
727 PO
= self
.section
.opcode
729 assert len(self
.ppc
) == 1
730 PO
= self
.ppc
[0].opcode
732 return POStaticOperand(record
=self
,
733 name
="PO", value
=int(PO
.value
), mask
=int(PO
.mask
))
739 PO
= self
.section
.opcode
745 return XOStaticOperand(record
=self
,
746 name
="XO", value
=0, mask
=0)
748 return XOStaticOperand(record
=self
,
749 name
="XO", value
=int(XO
.value
), mask
=int(XO
.mask
))
751 return tuple(dict.fromkeys(map(XO
, self
.ppc
)))
754 def static_operands(self
):
757 operands
.append(self
.PO
)
758 operands
.extend(self
.XO
)
760 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
761 operands
.append(cls(record
=self
, **kwargs
))
763 return tuple(operands
)
766 def dynamic_operands(self
):
769 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
770 operands
.append(cls(record
=self
, **kwargs
))
772 return tuple(operands
)
777 if self
.svp64
is not None:
779 origin_value
= ([0] * bits
)
780 origin_mask
= ([0] * bits
)
782 for operand
in ((self
.PO
,) + tuple(self
.static_operands
)):
783 for (src
, dst
) in enumerate(reversed(operand
.span
)):
784 origin_value
[dst
] = int((operand
.value
& (1 << src
)) != 0)
788 value
= list(origin_value
)
789 mask
= list(origin_mask
)
790 for (src
, dst
) in enumerate(reversed(XO
.span
)):
791 value
[dst
] = int((XO
.value
& (1 << src
)) != 0)
794 value
= Opcode
.Value(int(("".join(map(str, value
))), 2))
795 mask
= Opcode
.Mask(int(("".join(map(str, mask
))), 2))
797 return Opcode(value
=value
, mask
=mask
)
799 return tuple(dict.fromkeys(map(opcode
, self
.XO
)))
801 def match(self
, key
):
802 for opcode
in self
.opcodes
:
803 if opcode
.match(key
):
810 return self
.svp64
.mode
830 if self
.svp64
is None:
836 return self
.ppc
.cr_in
840 return self
.ppc
.cr_in2
844 return self
.ppc
.cr_out
846 ptype
= property(lambda self
: self
.svp64
.ptype
)
847 etype
= property(lambda self
: self
.svp64
.etype
)
849 def extra_idx(self
, key
):
850 return self
.svp64
.extra_idx(key
)
852 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
853 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
854 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
855 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
856 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
857 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
858 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
859 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
861 def __contains__(self
, key
):
862 return self
.mdwn
.operands
.__contains
__(key
)
864 def __getitem__(self
, key
):
865 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
866 return cls(record
=self
, **kwargs
)
872 return self
["Rc"].value
875 @_dataclasses.dataclass(eq
=True, frozen
=True)
878 record
: Record
= _dataclasses
.field(repr=False)
880 def __post_init__(self
):
885 span
= self
.record
.fields
[self
.name
]
886 if self
.record
.svp64
is not None:
887 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
890 def assemble(self
, value
, insn
):
892 if isinstance(value
, str):
893 value
= int(value
, 0)
895 raise ValueError("signed operands not allowed")
898 def disassemble(self
, insn
,
899 verbosity
=Verbosity
.NORMAL
, indent
=""):
900 raise NotImplementedError
903 @_dataclasses.dataclass(eq
=True, frozen
=True)
904 class DynamicOperand(Operand
):
905 def disassemble(self
, insn
,
906 verbosity
=Verbosity
.NORMAL
, indent
=""):
910 if verbosity
>= Verbosity
.VERBOSE
:
911 span
= map(str, span
)
912 yield f
"{indent}{self.name}"
913 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
914 yield f
"{indent}{indent}{', '.join(span)}"
916 yield str(int(value
))
919 @_dataclasses.dataclass(eq
=True, frozen
=True)
920 class SignedOperand(DynamicOperand
):
921 def assemble(self
, value
, insn
):
922 if isinstance(value
, str):
923 value
= int(value
, 0)
924 return super().assemble(value
=value
, insn
=insn
)
926 def disassemble(self
, insn
,
927 verbosity
=Verbosity
.NORMAL
, indent
=""):
931 if verbosity
>= Verbosity
.VERBOSE
:
932 span
= map(str, span
)
933 yield f
"{indent}{self.name}"
934 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
935 yield f
"{indent}{indent}{', '.join(span)}"
937 yield str(value
.to_signed_int())
940 @_dataclasses.dataclass(eq
=True, frozen
=True)
941 class StaticOperand(Operand
):
944 def assemble(self
, insn
):
945 return super().assemble(value
=self
.value
, insn
=insn
)
947 def disassemble(self
, insn
,
948 verbosity
=Verbosity
.NORMAL
, indent
=""):
952 if verbosity
>= Verbosity
.VERBOSE
:
953 span
= map(str, span
)
954 yield f
"{indent}{self.name}"
955 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
956 yield f
"{indent}{indent}{', '.join(span)}"
958 yield str(int(value
))
961 @_dataclasses.dataclass(eq
=True, frozen
=True)
962 class POStaticOperand(StaticOperand
):
967 span
= tuple(range(0, 6))
968 if self
.record
.svp64
is not None:
969 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
973 @_dataclasses.dataclass(eq
=True, frozen
=True)
974 class XOStaticOperand(StaticOperand
):
977 def __post_init__(self
):
978 if self
.record
.section
.opcode
is None:
979 assert self
.value
== 0
980 assert self
.mask
== 0
981 object.__setattr
__(self
, "span", ())
984 bits
= self
.record
.section
.bitsel
985 value
= _SelectableInt(value
=self
.value
, bits
=len(bits
))
986 span
= dict(zip(bits
, range(len(bits
))))
987 span_rev
= {value
:key
for (key
, value
) in span
.items()}
989 # This part is tricky: we could have used self.record.static_operands,
990 # but this would cause an infinite recursion, since this code is called
991 # from the self.record.static_operands method already.
993 operands
.extend(self
.record
.mdwn
.operands
.static
)
994 operands
.extend(self
.record
.mdwn
.operands
.dynamic
)
995 for (cls
, kwargs
) in operands
:
996 operand
= cls(record
=self
.record
, **kwargs
)
997 for idx
in operand
.span
:
998 rev
= span
.pop(idx
, None)
1000 span_rev
.pop(rev
, None)
1002 # This part is simpler: we drop bits which are not in the mask.
1003 for bit
in tuple(span
.values()):
1004 rev
= (len(bits
) - bit
- 1)
1005 if ((self
.mask
& (1 << bit
)) == 0):
1006 idx
= span_rev
.pop(rev
, None)
1010 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1011 span
= tuple(span
.keys())
1012 if self
.record
.svp64
is not None:
1013 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
1015 object.__setattr
__(self
, "value", value
)
1016 object.__setattr
__(self
, "span", span
)
1018 return super().__post
_init
__()
1021 @_dataclasses.dataclass(eq
=True, frozen
=True)
1022 class ImmediateOperand(DynamicOperand
):
1026 @_dataclasses.dataclass(eq
=True, frozen
=True)
1027 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1031 @_dataclasses.dataclass(eq
=True, frozen
=True)
1032 class NonZeroOperand(DynamicOperand
):
1033 def assemble(self
, value
, insn
):
1034 if isinstance(value
, str):
1035 value
= int(value
, 0)
1036 if not isinstance(value
, int):
1037 raise ValueError("non-integer operand")
1039 return super().assemble(value
=value
, insn
=insn
)
1041 def disassemble(self
, insn
,
1042 verbosity
=Verbosity
.NORMAL
, indent
=""):
1046 if verbosity
>= Verbosity
.VERBOSE
:
1047 span
= map(str, span
)
1048 yield f
"{indent}{self.name}"
1049 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1050 yield f
"{indent}{indent}{', '.join(span)}"
1052 yield str(int(value
) + 1)
1055 @_dataclasses.dataclass(eq
=True, frozen
=True)
1056 class ExtendableOperand(DynamicOperand
):
1057 def sv_spec_enter(self
, value
, span
):
1058 return (value
, span
)
1060 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1061 return (value
, span
)
1063 def spec(self
, insn
):
1067 span
= tuple(map(str, span
))
1069 if isinstance(insn
, SVP64Instruction
):
1070 (origin_value
, origin_span
) = (value
, span
)
1071 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1073 extra_idx
= self
.extra_idx
1074 if extra_idx
is _SVExtra
.NONE
:
1075 return (vector
, value
, span
)
1077 if self
.record
.etype
is _SVEtype
.EXTRA3
:
1078 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1079 elif self
.record
.etype
is _SVEtype
.EXTRA2
:
1080 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1082 raise ValueError(self
.record
.etype
)
1085 vector
= bool(spec
[0])
1086 spec_span
= spec
.__class
__
1087 if self
.record
.etype
is _SVEtype
.EXTRA3
:
1088 spec_span
= tuple(map(str, spec_span
[1, 2]))
1090 elif self
.record
.etype
is _SVEtype
.EXTRA2
:
1091 spec_span
= tuple(map(str, spec_span
[1,]))
1092 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1095 spec_span
= (spec_span
+ ("{0}",))
1097 spec_span
= (("{0}",) + spec_span
)
1099 raise ValueError(self
.record
.etype
)
1101 vector_shift
= (2 + (5 - value
.bits
))
1102 scalar_shift
= value
.bits
1103 spec_shift
= (5 - value
.bits
)
1105 bits
= (len(span
) + len(spec_span
))
1106 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1107 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1109 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1110 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1112 value
= ((spec
<< scalar_shift
) | value
)
1113 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1115 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1116 origin_value
=origin_value
, origin_span
=origin_span
)
1118 return (vector
, value
, span
)
1121 def extra_reg(self
):
1122 return _SVExtraReg(self
.name
)
1125 def extra_idx(self
):
1126 for key
in frozenset({
1127 "in1", "in2", "in3", "cr_in", "cr_in2",
1128 "out", "out2", "cr_out",
1130 extra_reg
= self
.record
.svp64
.extra_reg(key
=key
)
1131 if extra_reg
is self
.extra_reg
:
1132 return self
.record
.extra_idx(key
=key
)
1134 return _SVExtra
.NONE
1136 def remap(self
, value
, vector
):
1137 raise NotImplementedError
1139 def assemble(self
, value
, insn
, prefix
):
1142 if isinstance(value
, str):
1143 value
= value
.lower()
1144 if value
.startswith("%"):
1146 if value
.startswith("*"):
1147 if not isinstance(insn
, SVP64Instruction
):
1148 raise ValueError(value
)
1151 if value
.startswith(prefix
):
1152 value
= value
[len(prefix
):]
1153 value
= int(value
, 0)
1155 if isinstance(insn
, SVP64Instruction
):
1156 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1158 extra_idx
= self
.extra_idx
1159 if extra_idx
is _SVExtra
.NONE
:
1160 raise ValueError(self
.record
)
1162 if self
.record
.etype
is _SVEtype
.EXTRA3
:
1163 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1164 elif self
.record
.etype
is _SVEtype
.EXTRA2
:
1165 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1167 raise ValueError(self
.record
.etype
)
1169 return super().assemble(value
=value
, insn
=insn
)
1171 return super().assemble(value
=value
, insn
=insn
)
1173 def disassemble(self
, insn
,
1174 verbosity
=Verbosity
.NORMAL
, prefix
="", indent
=""):
1175 (vector
, value
, span
) = self
.spec(insn
=insn
)
1177 if verbosity
>= Verbosity
.VERBOSE
:
1178 mode
= "vector" if vector
else "scalar"
1179 yield f
"{indent}{self.name} ({mode})"
1180 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1181 yield f
"{indent}{indent}{', '.join(span)}"
1182 if isinstance(insn
, SVP64Instruction
):
1183 extra_idx
= self
.extra_idx
1184 if self
.record
.etype
is _SVEtype
.NONE
:
1185 yield f
"{indent}{indent}extra[none]"
1187 etype
= repr(self
.record
.etype
).lower()
1188 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1190 vector
= "*" if vector
else ""
1191 yield f
"{vector}{prefix}{int(value)}"
1194 @_dataclasses.dataclass(eq
=True, frozen
=True)
1195 class SimpleRegisterOperand(ExtendableOperand
):
1196 def remap(self
, value
, vector
):
1198 extra
= (value
& 0b11)
1199 value
= (value
>> 2)
1201 extra
= (value
>> 5)
1202 value
= (value
& 0b11111)
1204 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1205 # (and shrink to a single bit if ok)
1206 if self
.record
.etype
is _SVEtype
.EXTRA2
:
1208 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1209 assert (extra
& 0b01) == 0, \
1210 ("vector field %s cannot fit into EXTRA2" % value
)
1211 extra
= (0b10 |
(extra
>> 1))
1213 # range is r0-r63 in increments of 1
1214 assert (extra
>> 1) == 0, \
1215 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1217 elif self
.record
.etype
is _SVEtype
.EXTRA3
:
1219 # EXTRA3 vector bit needs marking
1222 raise ValueError(self
.record
.etype
)
1224 return (value
, extra
)
1227 @_dataclasses.dataclass(eq
=True, frozen
=True)
1228 class GPROperand(SimpleRegisterOperand
):
1229 def assemble(self
, value
, insn
):
1230 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1232 def disassemble(self
, insn
,
1233 verbosity
=Verbosity
.NORMAL
, indent
=""):
1234 prefix
= "" if (verbosity
<= Verbosity
.SHORT
) else "r"
1235 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1236 verbosity
=verbosity
, indent
=indent
)
1239 @_dataclasses.dataclass(eq
=True, frozen
=True)
1240 class FPROperand(SimpleRegisterOperand
):
1241 def assemble(self
, value
, insn
):
1242 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1244 def disassemble(self
, insn
,
1245 verbosity
=Verbosity
.NORMAL
, indent
=""):
1246 prefix
= "" if (verbosity
<= Verbosity
.SHORT
) else "f"
1247 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1248 verbosity
=verbosity
, indent
=indent
)
1251 @_dataclasses.dataclass(eq
=True, frozen
=True)
1252 class ConditionRegisterFieldOperand(ExtendableOperand
):
1253 def pattern(name_pattern
):
1254 (name
, pattern
) = name_pattern
1255 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1264 CR
= r
"(?:CR|cr)([0-9]+)"
1266 BIT
= rf
"({'|'.join(CONDS.keys())})"
1267 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1268 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1269 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1270 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1271 XCR
= fr
"{CR}\.{BIT}"
1272 PATTERNS
= tuple(map(pattern
, (
1277 ("BIT+CR", (LBIT
+ CR
)),
1278 ("CR+BIT", (CR
+ RBIT
)),
1279 ("BIT+CR*N", (LBIT
+ CRN
)),
1280 ("CR*N+BIT", (CRN
+ RBIT
)),
1281 ("BIT+N*CR", (LBIT
+ NCR
)),
1282 ("N*CR+BIT", (NCR
+ RBIT
)),
1285 def remap(self
, value
, vector
, regtype
):
1286 if regtype
is _RegType
.CR_5BIT
:
1287 subvalue
= (value
& 0x3)
1291 extra
= (value
& 0xf)
1294 extra
= (value
>> 3)
1297 if self
.record
.etype
is _SVEtype
.EXTRA2
:
1299 assert (extra
& 0x7) == 0, \
1300 "vector CR cannot fit into EXTRA2"
1301 extra
= (0x2 |
(extra
>> 3))
1303 assert (extra
>> 1) == 0, \
1304 "scalar CR cannot fit into EXTRA2"
1306 elif self
.record
.etype
is _SVEtype
.EXTRA3
:
1308 assert (extra
& 0x3) == 0, \
1309 "vector CR cannot fit into EXTRA3"
1310 extra
= (0x4 |
(extra
>> 2))
1312 assert (extra
>> 2) == 0, \
1313 "scalar CR cannot fit into EXTRA3"
1316 if regtype
is _RegType
.CR_5BIT
:
1317 value
= ((value
<< 2) | subvalue
)
1319 return (value
, extra
)
1321 def assemble(self
, value
, insn
):
1322 if isinstance(value
, str):
1325 if value
.startswith("*"):
1326 if not isinstance(insn
, SVP64Instruction
):
1327 raise ValueError(value
)
1331 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1332 match
= pattern
.match(value
)
1333 if match
is not None:
1334 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1335 values
= match
.groups()
1336 match
= dict(zip(keys
, values
))
1337 CR
= int(match
["CR"])
1341 N
= int(match
.get("N", "1"))
1342 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1343 value
= ((CR
* N
) + BIT
)
1346 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1348 def disassemble(self
, insn
,
1349 verbosity
=Verbosity
.NORMAL
, prefix
="", indent
=""):
1350 (vector
, value
, span
) = self
.spec(insn
=insn
)
1352 if verbosity
>= Verbosity
.VERBOSE
:
1353 mode
= "vector" if vector
else "scalar"
1354 yield f
"{indent}{self.name} ({mode})"
1355 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1356 yield f
"{indent}{indent}{', '.join(span)}"
1357 if isinstance(insn
, SVP64Instruction
):
1358 extra_idx
= self
.extra_idx
1359 if self
.record
.etype
is _SVEtype
.NONE
:
1360 yield f
"{indent}{indent}extra[none]"
1362 etype
= repr(self
.record
.etype
).lower()
1363 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1365 vector
= "*" if vector
else ""
1366 cr
= int(value
>> 2)
1368 cond
= ("lt", "gt", "eq", "so")[cc
]
1369 if verbosity
>= Verbosity
.NORMAL
:
1371 if isinstance(insn
, SVP64Instruction
):
1372 yield f
"{vector}cr{cr}.{cond}"
1374 yield f
"4*cr{cr}+{cond}"
1378 yield f
"{vector}{prefix}{int(value)}"
1381 @_dataclasses.dataclass(eq
=True, frozen
=True)
1382 class CR3Operand(ConditionRegisterFieldOperand
):
1383 def remap(self
, value
, vector
):
1384 return super().remap(value
=value
, vector
=vector
,
1385 regtype
=_RegType
.CR_3BIT
)
1388 @_dataclasses.dataclass(eq
=True, frozen
=True)
1389 class CR5Operand(ConditionRegisterFieldOperand
):
1390 def remap(self
, value
, vector
):
1391 return super().remap(value
=value
, vector
=vector
,
1392 regtype
=_RegType
.CR_5BIT
)
1394 def sv_spec_enter(self
, value
, span
):
1395 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1396 return (value
, span
)
1398 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1399 value
= _selectconcat(value
, origin_value
[3:5])
1401 return (value
, span
)
1404 @_dataclasses.dataclass(eq
=True, frozen
=True)
1405 class EXTSOperand(DynamicOperand
):
1406 field
: str # real name to report
1407 nz
: int = 0 # number of zeros
1408 fmt
: str = "d" # integer formatter
1410 def __post_init__(self
):
1412 object.__setattr
__(self
, "field", self
.name
)
1416 span
= self
.record
.fields
[self
.field
]
1417 if self
.record
.svp64
is not None:
1418 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
1421 def disassemble(self
, insn
,
1422 verbosity
=Verbosity
.NORMAL
, indent
=""):
1426 if verbosity
>= Verbosity
.VERBOSE
:
1427 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1428 zeros
= ("0" * self
.nz
)
1429 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1430 yield f
"{indent * 1}{hint}"
1431 yield f
"{indent * 2}{self.field}"
1432 yield f
"{indent * 3}{int(value):0{value.bits}b}{zeros}"
1433 yield f
"{indent * 3}{', '.join(span)}"
1435 value
= _selectconcat(value
,
1436 _SelectableInt(value
=0, bits
=self
.nz
)).to_signed_int()
1437 yield f
"{value:{self.fmt}}"
1440 @_dataclasses.dataclass(eq
=True, frozen
=True)
1441 class TargetAddrOperand(EXTSOperand
):
1446 @_dataclasses.dataclass(eq
=True, frozen
=True)
1447 class TargetAddrOperandLI(TargetAddrOperand
):
1451 @_dataclasses.dataclass(eq
=True, frozen
=True)
1452 class TargetAddrOperandBD(TargetAddrOperand
):
1456 @_dataclasses.dataclass(eq
=True, frozen
=True)
1457 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1462 @_dataclasses.dataclass(eq
=True, frozen
=True)
1463 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1468 @_dataclasses.dataclass(eq
=True, frozen
=True)
1469 class DOperandDX(SignedOperand
):
1472 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1473 operands
= map(cls
, ("d0", "d1", "d2"))
1474 spans
= map(lambda operand
: operand
.span
, operands
)
1475 span
= sum(spans
, tuple())
1476 if self
.record
.svp64
is not None:
1477 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
1480 def disassemble(self
, insn
,
1481 verbosity
=Verbosity
.NORMAL
, indent
=""):
1485 if verbosity
>= Verbosity
.VERBOSE
:
1492 for (subname
, subspan
) in mapping
.items():
1493 operand
= DynamicOperand(name
=subname
)
1496 span
= map(str, span
)
1497 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1498 yield f
"{indent}{indent}{indent}{int(value):0{value.bits}b}"
1499 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1501 yield str(value
.to_signed_int())
1504 class Instruction(_Mapping
):
1506 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1507 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1508 raise ValueError(bits
)
1510 if isinstance(value
, bytes
):
1511 if ((len(value
) * 8) != bits
):
1512 raise ValueError(f
"bit length mismatch")
1513 value
= int.from_bytes(value
, byteorder
=byteorder
)
1515 if isinstance(value
, int):
1516 value
= _SelectableInt(value
=value
, bits
=bits
)
1517 elif isinstance(value
, Instruction
):
1518 value
= value
.storage
1520 if not isinstance(value
, _SelectableInt
):
1521 raise ValueError(value
)
1524 if len(value
) != bits
:
1525 raise ValueError(value
)
1527 value
= _SelectableInt(value
=value
, bits
=bits
)
1529 return cls(storage
=value
)
1532 return hash(int(self
))
1534 def __getitem__(self
, key
):
1535 return self
.storage
.__getitem
__(key
)
1537 def __setitem__(self
, key
, value
):
1538 return self
.storage
.__setitem
__(key
, value
)
1540 def bytes(self
, byteorder
="little"):
1541 nr_bytes
= (len(self
.__class
__) // 8)
1542 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1544 def record(self
, db
):
1547 raise KeyError(self
)
1550 def spec(self
, db
, prefix
):
1551 record
= self
.record(db
=db
)
1553 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1554 self
.dynamic_operands(db
=db
)))
1556 static_operands
= []
1557 for (name
, value
) in self
.static_operands(db
=db
):
1558 static_operands
.append(f
"{name}={value}")
1561 if dynamic_operands
:
1563 operands
+= ",".join(dynamic_operands
)
1566 operands
+= " ".join(static_operands
)
1568 return f
"{prefix}{record.name}{operands}"
1570 def dynamic_operands(self
, db
, verbosity
=Verbosity
.NORMAL
):
1571 record
= self
.record(db
=db
)
1576 for operand
in record
.dynamic_operands
:
1578 value
= " ".join(operand
.disassemble(insn
=self
,
1579 verbosity
=min(verbosity
, Verbosity
.NORMAL
)))
1581 name
= f
"{imm_name}({name})"
1582 value
= f
"{imm_value}({value})"
1584 if isinstance(operand
, ImmediateOperand
):
1591 def static_operands(self
, db
):
1592 record
= self
.record(db
=db
)
1593 for operand
in record
.static_operands
:
1594 yield (operand
.name
, operand
.value
)
1597 def assemble(cls
, db
, opcode
, arguments
=None):
1598 raise NotImplementedError(f
"{cls.__name__}.assemble")
1600 def disassemble(self
, db
,
1602 verbosity
=Verbosity
.NORMAL
):
1603 raise NotImplementedError
1606 class WordInstruction(Instruction
):
1607 _
: _Field
= range(0, 32)
1608 PO
: _Field
= range(0, 6)
1611 def integer(cls
, value
, byteorder
="little"):
1612 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1617 for idx
in range(32):
1618 bit
= int(self
[idx
])
1620 return "".join(map(str, bits
))
1623 def assemble(cls
, db
, opcode
, arguments
=None):
1624 if arguments
is None:
1628 insn
= cls
.integer(value
=0)
1629 for operand
in record
.static_operands
:
1630 operand
.assemble(insn
=insn
)
1632 dynamic_operands
= tuple(record
.dynamic_operands
)
1633 if len(dynamic_operands
) != len(arguments
):
1634 raise ValueError("operands count mismatch")
1635 for (value
, operand
) in zip(arguments
, dynamic_operands
):
1636 operand
.assemble(value
=value
, insn
=insn
)
1640 def disassemble(self
, db
,
1642 verbosity
=Verbosity
.NORMAL
):
1643 if verbosity
<= Verbosity
.SHORT
:
1646 blob
= self
.bytes(byteorder
=byteorder
)
1647 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1652 yield f
"{blob}.long 0x{int(self):08x}"
1655 operands
= tuple(map(_operator
.itemgetter(1),
1656 self
.dynamic_operands(db
=db
, verbosity
=verbosity
)))
1658 operands
= ",".join(operands
)
1659 yield f
"{blob}{record.name} {operands}"
1661 yield f
"{blob}{record.name}"
1663 if verbosity
>= Verbosity
.VERBOSE
:
1665 binary
= self
.binary
1666 spec
= self
.spec(db
=db
, prefix
="")
1667 yield f
"{indent}spec"
1668 yield f
"{indent}{indent}{spec}"
1669 yield f
"{indent}pcode"
1670 for stmt
in record
.mdwn
.pcode
:
1671 yield f
"{indent}{indent}{stmt}"
1672 yield f
"{indent}binary"
1673 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1674 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1675 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1676 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1677 yield f
"{indent}opcodes"
1678 for opcode
in record
.opcodes
:
1679 yield f
"{indent}{indent}{opcode!r}"
1680 for (cls
, kwargs
) in record
.mdwn
.operands
:
1681 operand
= cls(record
=record
, **kwargs
)
1682 yield from operand
.disassemble(insn
=self
,
1683 verbosity
=verbosity
, indent
=indent
)
1687 class PrefixedInstruction(Instruction
):
1688 class Prefix(WordInstruction
.remap(range(0, 32))):
1691 class Suffix(WordInstruction
.remap(range(32, 64))):
1694 _
: _Field
= range(64)
1700 def integer(cls
, value
, byteorder
="little"):
1701 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
1704 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
1705 def transform(value
):
1706 return WordInstruction
.integer(value
=value
,
1707 byteorder
=byteorder
)[0:32]
1709 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
1710 value
= _selectconcat(prefix
, suffix
)
1712 return super().integer(bits
=64, value
=value
)
1715 class Mode(_Mapping
):
1716 _
: _Field
= range(0, 5)
1717 sel
: _Field
= (0, 1)
1720 class Extra(_Mapping
):
1721 _
: _Field
= range(0, 9)
1724 class Extra2(Extra
):
1725 idx0
: _Field
= range(0, 2)
1726 idx1
: _Field
= range(2, 4)
1727 idx2
: _Field
= range(4, 6)
1728 idx3
: _Field
= range(6, 8)
1730 def __getitem__(self
, key
):
1736 _SVExtra
.Idx0
: self
.idx0
,
1737 _SVExtra
.Idx1
: self
.idx1
,
1738 _SVExtra
.Idx2
: self
.idx2
,
1739 _SVExtra
.Idx3
: self
.idx3
,
1742 def __setitem__(self
, key
, value
):
1743 self
[key
].assign(value
)
1746 class Extra3(Extra
):
1747 idx0
: _Field
= range(0, 3)
1748 idx1
: _Field
= range(3, 6)
1749 idx2
: _Field
= range(6, 9)
1751 def __getitem__(self
, key
):
1756 _SVExtra
.Idx0
: self
.idx0
,
1757 _SVExtra
.Idx1
: self
.idx1
,
1758 _SVExtra
.Idx2
: self
.idx2
,
1761 def __setitem__(self
, key
, value
):
1762 self
[key
].assign(value
)
1765 class BaseRM(_Mapping
):
1766 _
: _Field
= range(24)
1767 mmode
: _Field
= (0,)
1768 mask
: _Field
= range(1, 4)
1769 elwidth
: _Field
= range(4, 6)
1770 ewsrc
: _Field
= range(6, 8)
1771 subvl
: _Field
= range(8, 10)
1772 mode
: Mode
.remap(range(19, 24))
1773 smask
: _Field
= range(16, 19)
1774 extra
: Extra
.remap(range(10, 19))
1775 extra2
: Extra2
.remap(range(10, 19))
1776 extra3
: Extra3
.remap(range(10, 19))
1778 def specifiers(self
, record
):
1779 subvl
= int(self
.subvl
)
1787 def disassemble(self
, verbosity
=Verbosity
.NORMAL
):
1788 if verbosity
>= Verbosity
.VERBOSE
:
1790 for (name
, span
) in self
.traverse(path
="RM"):
1791 value
= self
.storage
[span
]
1793 yield f
"{indent}{int(value):0{value.bits}b}"
1794 yield f
"{indent}{', '.join(map(str, span))}"
1797 class FFPRRc1BaseRM(BaseRM
):
1798 def specifiers(self
, record
, mode
):
1799 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
1800 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
1801 mask
= int(_selectconcat(CR
, inv
))
1802 predicate
= PredicateBaseRM
.predicate(True, mask
)
1803 yield f
"{mode}={predicate}"
1805 yield from super().specifiers(record
=record
)
1808 class FFPRRc0BaseRM(BaseRM
):
1809 def specifiers(self
, record
, mode
):
1811 inv
= "~" if self
.inv
else ""
1812 yield f
"{mode}={inv}RC1"
1814 yield from super().specifiers(record
=record
)
1817 class SatBaseRM(BaseRM
):
1818 def specifiers(self
, record
):
1824 yield from super().specifiers(record
=record
)
1827 class ZZBaseRM(BaseRM
):
1828 def specifiers(self
, record
):
1832 yield from super().specifiers(record
=record
)
1835 class DZBaseRM(BaseRM
):
1836 def specifiers(self
, record
):
1840 yield from super().specifiers(record
=record
)
1843 class SZBaseRM(BaseRM
):
1844 def specifiers(self
, record
):
1848 yield from super().specifiers(record
=record
)
1851 class MRBaseRM(BaseRM
):
1852 def specifiers(self
, record
):
1858 yield from super().specifiers(record
=record
)
1861 class ElsBaseRM(BaseRM
):
1862 def specifiers(self
, record
):
1866 yield from super().specifiers(record
=record
)
1869 class WidthBaseRM(BaseRM
):
1871 def width(FP
, width
):
1880 width
= ("fp" + width
)
1883 def specifiers(self
, record
):
1884 # elwidths: use "w=" if same otherwise dw/sw
1885 # FIXME this should consider FP instructions
1887 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
1888 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
1897 yield from super().specifiers(record
=record
)
1900 class PredicateBaseRM(BaseRM
):
1902 def predicate(CR
, mask
):
1905 (False, 0b001): "1<<r3",
1906 (False, 0b010): "r3",
1907 (False, 0b011): "~r3",
1908 (False, 0b100): "r10",
1909 (False, 0b101): "~r10",
1910 (False, 0b110): "r30",
1911 (False, 0b111): "~r30",
1913 (True, 0b000): "lt",
1914 (True, 0b001): "ge",
1915 (True, 0b010): "gt",
1916 (True, 0b011): "le",
1917 (True, 0b100): "eq",
1918 (True, 0b101): "ne",
1919 (True, 0b110): "so",
1920 (True, 0b111): "ns",
1923 def specifiers(self
, record
):
1924 # predication - single and twin
1925 # use "m=" if same otherwise sm/dm
1926 CR
= (int(self
.mmode
) == 1)
1927 mask
= int(self
.mask
)
1928 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
1929 if record
.svp64
.ptype
is _SVPtype
.P2
:
1930 smask
= int(self
.smask
)
1931 sm
= PredicateBaseRM
.predicate(CR
, smask
)
1940 yield from super().specifiers(record
=record
)
1943 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
1947 class SEABaseRM(BaseRM
):
1948 def specifiers(self
, record
):
1952 yield from super().specifiers(record
=record
)
1955 class VLiBaseRM(BaseRM
):
1956 def specifiers(self
, record
):
1960 yield from super().specifiers(record
=record
)
1963 class NormalBaseRM(PredicateWidthBaseRM
):
1966 https://libre-soc.org/openpower/sv/normal/
1971 class NormalSimpleRM(DZBaseRM
, SZBaseRM
, NormalBaseRM
):
1972 """normal: simple mode"""
1976 def specifiers(self
, record
):
1977 yield from super().specifiers(record
=record
)
1980 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
1981 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
1985 class NormalFFRc1RM(FFPRRc1BaseRM
, NormalBaseRM
):
1986 """normal: Rc=1: ffirst CR sel"""
1988 CR
: BaseRM
.mode
[3, 4]
1990 def specifiers(self
, record
):
1991 yield from super().specifiers(record
=record
, mode
="ff")
1994 class NormalFFRc0RM(FFPRRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
1995 """normal: Rc=0: ffirst z/nonz"""
2000 def specifiers(self
, record
):
2001 yield from super().specifiers(record
=record
, mode
="ff")
2004 class NormalSatRM(SatBaseRM
, DZBaseRM
, SZBaseRM
, NormalBaseRM
):
2005 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2011 class NormalPRRc1RM(FFPRRc1BaseRM
, NormalBaseRM
):
2012 """normal: Rc=1: pred-result CR sel"""
2014 CR
: BaseRM
.mode
[3, 4]
2016 def specifiers(self
, record
):
2017 yield from super().specifiers(record
=record
, mode
="pr")
2020 class NormalPRRc0RM(FFPRRc0BaseRM
, ZZBaseRM
, NormalBaseRM
):
2021 """normal: Rc=0: pred-result z/nonz"""
2028 def specifiers(self
, record
):
2029 yield from super().specifiers(record
=record
, mode
="pr")
2032 class NormalRM(NormalBaseRM
):
2033 simple
: NormalSimpleRM
2035 ffrc1
: NormalFFRc1RM
2036 ffrc0
: NormalFFRc0RM
2038 prrc1
: NormalPRRc1RM
2039 prrc0
: NormalPRRc0RM
2042 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2044 LD/ST Immediate mode
2045 https://libre-soc.org/openpower/sv/ldst/
2050 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2051 """ld/st immediate: simple mode"""
2058 class LDSTImmPostRM(LDSTImmBaseRM
):
2059 """ld/st immediate: postinc mode (and load-fault)"""
2060 pi
: BaseRM
.mode
[3] # Post-Increment Mode
2061 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2063 def specifiers(self
, record
):
2070 class LDSTImmFFRc1RM(FFPRRc1BaseRM
, LDSTImmBaseRM
):
2071 """ld/st immediate: Rc=1: ffirst CR sel"""
2073 CR
: BaseRM
.mode
[3, 4]
2075 def specifiers(self
, record
):
2076 yield from super().specifiers(record
=record
, mode
="ff")
2079 class LDSTImmFFRc0RM(FFPRRc0BaseRM
, ElsBaseRM
, LDSTImmBaseRM
):
2080 """ld/st immediate: Rc=0: ffirst z/nonz"""
2085 def specifiers(self
, record
):
2086 yield from super().specifiers(record
=record
, mode
="ff")
2089 class LDSTImmSatRM(ElsBaseRM
, SatBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2090 """ld/st immediate: sat mode: N=0/1 u/s"""
2098 class LDSTImmPRRc1RM(FFPRRc1BaseRM
, LDSTImmBaseRM
):
2099 """ld/st immediate: Rc=1: pred-result CR sel"""
2101 CR
: BaseRM
.mode
[3, 4]
2103 def specifiers(self
, record
):
2104 yield from super().specifiers(record
=record
, mode
="pr")
2107 class LDSTImmPRRc0RM(FFPRRc0BaseRM
, ElsBaseRM
, LDSTImmBaseRM
):
2108 """ld/st immediate: Rc=0: pred-result z/nonz"""
2113 def specifiers(self
, record
):
2114 yield from super().specifiers(record
=record
, mode
="pr")
2117 class LDSTImmRM(LDSTImmBaseRM
):
2118 simple
: LDSTImmSimpleRM
2120 ffrc1
: LDSTImmFFRc1RM
2121 ffrc0
: LDSTImmFFRc0RM
2123 prrc1
: LDSTImmPRRc1RM
2124 prrc0
: LDSTImmPRRc0RM
2127 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2130 https://libre-soc.org/openpower/sv/ldst/
2135 class LDSTIdxSimpleRM(SEABaseRM
, DZBaseRM
, SZBaseRM
, LDSTIdxBaseRM
):
2136 """ld/st index: simple mode"""
2142 class LDSTIdxStrideRM(SEABaseRM
, DZBaseRM
, SZBaseRM
, LDSTIdxBaseRM
):
2143 """ld/st index: strided (scalar only source)"""
2148 def specifiers(self
, record
):
2151 yield from super().specifiers(record
=record
)
2154 class LDSTIdxSatRM(SatBaseRM
, DZBaseRM
, SZBaseRM
, LDSTIdxBaseRM
):
2155 """ld/st index: sat mode: N=0/1 u/s"""
2161 class LDSTIdxPRRc1RM(LDSTIdxBaseRM
):
2162 """ld/st index: Rc=1: pred-result CR sel"""
2164 CR
: BaseRM
.mode
[3, 4]
2166 def specifiers(self
, record
):
2167 yield from super().specifiers(record
=record
, mode
="pr")
2170 class LDSTIdxPRRc0RM(FFPRRc0BaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2171 """ld/st index: Rc=0: pred-result z/nonz"""
2178 def specifiers(self
, record
):
2179 yield from super().specifiers(record
=record
, mode
="pr")
2182 class LDSTIdxRM(LDSTIdxBaseRM
):
2183 simple
: LDSTIdxSimpleRM
2184 stride
: LDSTIdxStrideRM
2186 prrc1
: LDSTIdxPRRc1RM
2187 prrc0
: LDSTIdxPRRc0RM
2191 class CROpBaseRM(BaseRM
):
2194 https://libre-soc.org/openpower/sv/cr_ops/
2199 class CROpSimpleRM(PredicateBaseRM
, DZBaseRM
, SZBaseRM
, CROpBaseRM
):
2200 """cr_op: simple mode"""
2205 def specifiers(self
, record
):
2207 yield "rg" # simple CR Mode reports /rg
2209 yield from super().specifiers(record
=record
)
2211 class CROpMRRM(MRBaseRM
, DZBaseRM
, SZBaseRM
, CROpBaseRM
):
2212 """cr_op: scalar reduce mode (mapreduce), SUBVL=1"""
2218 class CROpFF3RM(FFPRRc1BaseRM
, VLiBaseRM
, ZZBaseRM
, PredicateBaseRM
, CROpBaseRM
):
2219 """cr_op: ffirst 3-bit mode"""
2227 def specifiers(self
, record
):
2228 yield from super().specifiers(record
=record
, mode
="ff")
2231 class CROpFF5RM(FFPRRc0BaseRM
, PredicateBaseRM
,
2232 VLiBaseRM
, DZBaseRM
, SZBaseRM
, CROpBaseRM
):
2233 """cr_op: ffirst 5-bit mode"""
2236 RC1
: BaseRM
[19] # cheat: set RC=1 based on ffirst mode being set
2240 def specifiers(self
, record
):
2241 yield from super().specifiers(record
=record
, mode
="ff")
2244 class CROpRM(CROpBaseRM
):
2245 simple
: CROpSimpleRM
2251 # ********************
2253 # https://libre-soc.org/openpower/sv/branches/
2254 class BranchBaseRM(BaseRM
):
2264 def specifiers(self
, record
):
2276 raise ValueError(self
.sz
)
2288 # Branch modes lack source mask.
2289 # Therefore a custom code is needed.
2290 CR
= (int(self
.mmode
) == 1)
2291 mask
= int(self
.mask
)
2292 m
= PredicateBaseRM
.predicate(CR
, mask
)
2296 yield from super().specifiers(record
=record
)
2299 class BranchSimpleRM(BranchBaseRM
):
2300 """branch: simple mode"""
2304 class BranchVLSRM(BranchBaseRM
):
2305 """branch: VLSET mode"""
2309 def specifiers(self
, record
):
2315 }[int(self
.VSb
), int(self
.VLi
)]
2317 yield from super().specifiers(record
=record
)
2320 class BranchCTRRM(BranchBaseRM
):
2321 """branch: CTR-test mode"""
2324 def specifiers(self
, record
):
2330 yield from super().specifiers(record
=record
)
2333 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2334 """branch: CTR-test+VLSET mode"""
2338 class BranchRM(BranchBaseRM
):
2339 simple
: BranchSimpleRM
2342 ctrvls
: BranchCTRVLSRM
2352 def select(self
, record
):
2356 # the idea behind these tables is that they are now literally
2357 # in identical format to insndb.csv and minor_xx.csv and can
2358 # be done precisely as that. the only thing to watch out for
2359 # is the insertion of Rc=1 as a "mask/value" bit and likewise
2360 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
2363 if record
.svp64
.mode
is _SVMode
.NORMAL
:
2364 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
2365 # mode Rc mask Rc member
2367 (0b000000, 0b111000, "simple"), # simple (no Rc)
2368 (0b001000, 0b111000, "mr"), # mapreduce (no Rc)
2369 (0b010001, 0b110001, "ffrc1"), # ffirst, Rc=1
2370 (0b010000, 0b110001, "ffrc0"), # ffirst, Rc=0
2371 (0b100000, 0b110000, "sat"), # saturation (no Rc)
2372 (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
2373 (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
2376 search
= ((int(rm
.mode
) << 1) | Rc
)
2378 elif record
.svp64
.mode
is _SVMode
.LDST_IMM
:
2379 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
2380 # mode Rc mask Rc member
2381 # ironically/coincidentally this table is identical to NORMAL
2382 # mode except reserved in place of mr
2384 (0b000000, 0b111000, "simple"), # simple (no Rc)
2385 (0b001000, 0b111000, "post"), # post (no Rc)
2386 (0b010001, 0b110001, "ffrc1"), # ffirst, Rc=1
2387 (0b010000, 0b110001, "ffrc0"), # ffirst, Rc=0
2388 (0b100000, 0b110000, "sat"), # saturation (no Rc)
2389 (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
2390 (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
2393 search
= ((int(rm
.mode
) << 1) | Rc
)
2395 elif record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2396 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
2397 # mode Rc mask Rc member
2399 (0b000000, 0b110000, "simple"), # simple (no Rc)
2400 (0b010000, 0b110000, "stride"), # strided, (no Rc)
2401 (0b100000, 0b110000, "sat"), # saturation (no Rc)
2402 (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
2403 (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
2406 search
= ((int(rm
.mode
) << 1) | Rc
)
2408 elif record
.svp64
.mode
is _SVMode
.CROP
:
2409 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
2410 # mode 3b mask 3b member
2412 (0b000000, 0b111000, "simple"), # simple
2413 (0b001000, 0b111000, "mr"), # mapreduce
2414 (0b100001, 0b100001, "ff3"), # ffirst, 3-bit CR
2415 (0b100000, 0b100000, "ff5"), # ffirst, 5-bit CR
2418 search
= ((int(rm
.mode
) << 1) |
int(record
.svp64
.cr_3bit
))
2420 elif record
.svp64
.mode
is _SVMode
.BRANCH
:
2424 (0b00, 0b11, "simple"), # simple
2425 (0b01, 0b11, "vls"), # VLset
2426 (0b10, 0b11, "ctr"), # CTR mode
2427 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
2429 # slightly weird: doesn't have a 5-bit "mode" field like others
2431 search
= int(rm
.mode
.sel
)
2434 if table
is not None:
2435 for (value
, mask
, member
) in table
:
2436 if ((value
& mask
) == (search
& mask
)):
2437 rm
= getattr(rm
, member
)
2440 if rm
.__class
__ is self
.__class
__:
2441 raise ValueError(self
)
2446 @_dataclasses.dataclass(eq
=True, frozen
=True)
2451 def match(cls
, desc
, record
):
2452 raise NotImplementedError
2454 def assemble(self
, insn
):
2455 raise NotImplementedError
2458 @_dataclasses.dataclass(eq
=True, frozen
=True)
2459 class SpecifierWidth(Specifier
):
2464 def match(cls
, desc
, record
):
2465 (mode
, _
, value
) = desc
.partition("=")
2467 value
= value
.strip()
2468 if mode
not in ("w", "sw", "dw"):
2470 if value
not in ("8", "16", "32"):
2471 raise ValueError(value
)
2473 value
= {"8": 3, "16": 2, "32": 1}[value
]
2475 return cls(record
=record
, mode
=mode
, value
=value
)
2477 def assemble(self
, insn
):
2478 if self
.mode
== "sw":
2479 insn
.prefix
.rm
.ewsrc
= self
.value
2480 elif self
.mode
== "dw":
2481 insn
.prefix
.rm
.elwidth
= self
.value
2483 insn
.prefix
.rm
.ewsrc
= self
.value
2484 insn
.prefix
.rm
.elwidth
= self
.value
2487 @_dataclasses.dataclass(eq
=True, frozen
=True)
2488 class SpecifierSubVL(Specifier
):
2492 def match(cls
, desc
, record
):
2493 value
= {"vec2": 1, "vec3": 2, "vec4": 3}.get(desc
)
2497 return cls(record
=record
, value
=value
)
2499 def assemble(self
, insn
):
2500 insn
.prefix
.rm
.subvl
= self
.value
2503 @_dataclasses.dataclass(eq
=True, frozen
=True)
2504 class SpecifierPredicate(Specifier
):
2506 pred
: _SVP64Predicate
2509 def match(cls
, desc
, record
, mode_match
, pred_match
):
2510 (mode
, _
, pred
) = desc
.partition("=")
2513 if not mode_match(mode
):
2516 pred
= _SVP64Predicate(pred
.strip())
2517 if not pred_match(pred
):
2518 raise ValueError(pred
)
2520 return cls(record
=record
, mode
=mode
, pred
=pred
)
2523 @_dataclasses.dataclass(eq
=True, frozen
=True)
2524 class SpecifierFFPR(SpecifierPredicate
):
2526 def match(cls
, desc
, record
, mode
):
2527 return super().match(desc
=desc
, record
=record
,
2528 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2529 pred_match
=lambda pred_arg
: _SVP64PredicateType(pred_arg
) in (
2530 _SVP64PredicateType
.CR
,
2531 _SVP64PredicateType
.RC1
,
2534 def assemble(self
, insn
):
2536 if rm
.mode
.sel
!= 0:
2537 raise ValueError("cannot override mode")
2539 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2540 if self
.mode
== "pr":
2541 raise ValueError("crop: 'pr' mode not supported")
2543 if self
.record
.svp64
.cr_3bit
:
2548 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
2550 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
2552 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2554 if self
.mode
== "ff":
2555 raise ValueError("ld/st idx: 'ff' mode not supported")
2557 raise ValueError(f
"{self.mode!r} not supported")
2559 # These 2-bit values should have bits swapped
2561 return (((value
& 0b10) >> 1) |
((value
& 0b01) << 1))
2564 "ff": bitswap(_SVP64RMMode
.FFIRST
.value
),
2565 "pr": bitswap(_SVP64RMMode
.PREDRES
.value
),
2568 Rc
= int(self
.record
.Rc
)
2569 rm
= getattr(rm
, f
"{self.mode}rc{Rc}")
2570 rm
.inv
= self
.pred
.inv
2572 rm
.CR
= self
.pred
.state
2574 rm
.RC1
= self
.pred
.state
2577 @_dataclasses.dataclass(eq
=True, frozen
=True)
2578 class SpecifierFF(SpecifierFFPR
):
2580 def match(cls
, desc
, record
):
2581 return super().match(desc
=desc
, record
=record
, mode
="ff")
2584 @_dataclasses.dataclass(eq
=True, frozen
=True)
2585 class SpecifierPR(SpecifierFFPR
):
2587 def match(cls
, desc
, record
):
2588 return super().match(desc
=desc
, record
=record
, mode
="pr")
2591 @_dataclasses.dataclass(eq
=True, frozen
=True)
2592 class SpecifierMask(SpecifierPredicate
):
2594 def match(cls
, desc
, record
, mode
):
2595 return super().match(desc
=desc
, record
=record
,
2596 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2597 pred_match
=lambda pred_arg
: _SVP64PredicateType(pred_arg
) in (
2598 _SVP64PredicateType
.INTEGER
,
2599 _SVP64PredicateType
.CR
,
2602 def assemble(self
, insn
):
2603 raise NotImplementedError
2606 @_dataclasses.dataclass(eq
=True, frozen
=True)
2607 class SpecifierM(SpecifierMask
):
2609 def match(cls
, desc
, record
):
2610 return super().match(desc
=desc
, record
=record
, mode
="m")
2612 def assemble(self
, insn
):
2613 insn
.prefix
.rm
.mask
= self
.pred
.mask
2616 @_dataclasses.dataclass(eq
=True, frozen
=True)
2617 class SpecifierSM(SpecifierMask
):
2619 def match(cls
, desc
, record
):
2620 return super().match(desc
=desc
, record
=record
, mode
="sm")
2622 def assemble(self
, insn
):
2623 insn
.prefix
.rm
.smask
= self
.pred
.mask
2626 @_dataclasses.dataclass(eq
=True, frozen
=True)
2627 class SpecifierDM(SpecifierMask
):
2629 def match(cls
, desc
, record
):
2630 return super().match(desc
=desc
, record
=record
, mode
="dm")
2632 def assemble(self
, insn
):
2633 insn
.prefix
.rm
.mask
= self
.pred
.mask
2636 class SVP64Instruction(PrefixedInstruction
):
2637 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
2638 class Prefix(PrefixedInstruction
.Prefix
):
2640 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
2644 def record(self
, db
):
2645 record
= db
[self
.suffix
]
2647 raise KeyError(self
)
2653 for idx
in range(64):
2654 bit
= int(self
[idx
])
2656 return "".join(map(str, bits
))
2659 def specifier(cls
, desc
, record
):
2670 for spec_cls
in specifiers
:
2671 match
= spec_cls
.match(desc
, record
=record
)
2672 if match
is not None:
2675 raise ValueError(desc
)
2678 def assemble(cls
, db
, opcode
, arguments
=None, specifiers
=None):
2679 if arguments
is None:
2681 if specifiers
is None:
2685 insn
= cls
.integer(value
=0)
2687 specifier
= lambda desc
: cls
.specifier(desc
=desc
, record
=record
)
2688 for spec
in map(specifier
, specifiers
):
2689 spec
.assemble(insn
=insn
)
2691 for operand
in record
.static_operands
:
2692 operand
.assemble(insn
=insn
)
2694 dynamic_operands
= tuple(record
.dynamic_operands
)
2695 if len(dynamic_operands
) != len(arguments
):
2696 raise ValueError("operands count mismatch")
2697 for (value
, operand
) in zip(arguments
, dynamic_operands
):
2698 operand
.assemble(value
=value
, insn
=insn
)
2700 insn
.prefix
.PO
= 0x1
2701 insn
.prefix
.id = 0x3
2705 def disassemble(self
, db
,
2707 verbosity
=Verbosity
.NORMAL
):
2709 if verbosity
<= Verbosity
.SHORT
:
2712 blob
= insn
.bytes(byteorder
=byteorder
)
2713 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
2716 record
= self
.record(db
=db
)
2717 blob_prefix
= blob(self
.prefix
)
2718 blob_suffix
= blob(self
.suffix
)
2719 if record
is None or record
.svp64
is None:
2720 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
2721 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
2724 name
= f
"sv.{record.name}"
2726 rm
= self
.prefix
.rm
.select(record
=record
)
2728 # convert specifiers to /x/y/z (sorted lexicographically)
2729 specifiers
= sorted(rm
.specifiers(record
=record
))
2730 if specifiers
: # if any add one extra to get the extra "/"
2731 specifiers
= ([""] + specifiers
)
2732 specifiers
= "/".join(specifiers
)
2734 # convert operands to " ,x,y,z"
2735 operands
= tuple(map(_operator
.itemgetter(1),
2736 self
.dynamic_operands(db
=db
, verbosity
=verbosity
)))
2737 operands
= ",".join(operands
)
2738 if len(operands
) > 0: # if any separate with a space
2739 operands
= (" " + operands
)
2741 yield f
"{blob_prefix}{name}{specifiers}{operands}"
2743 yield f
"{blob_suffix}"
2745 if verbosity
>= Verbosity
.VERBOSE
:
2747 binary
= self
.binary
2748 spec
= self
.spec(db
=db
, prefix
="sv.")
2750 yield f
"{indent}spec"
2751 yield f
"{indent}{indent}{spec}"
2752 yield f
"{indent}pcode"
2753 for stmt
in record
.mdwn
.pcode
:
2754 yield f
"{indent}{indent}{stmt}"
2755 yield f
"{indent}binary"
2756 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
2757 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
2758 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
2759 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
2760 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
2761 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
2762 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
2763 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
2764 yield f
"{indent}opcodes"
2765 for opcode
in record
.opcodes
:
2766 yield f
"{indent}{indent}{opcode!r}"
2767 for (cls
, kwargs
) in record
.mdwn
.operands
:
2768 operand
= cls(record
=record
, **kwargs
)
2769 yield from operand
.disassemble(insn
=self
,
2770 verbosity
=verbosity
, indent
=indent
)
2772 yield f
"{indent}{indent}{rm.__doc__}"
2773 for line
in rm
.disassemble(verbosity
=verbosity
):
2774 yield f
"{indent}{indent}{line}"
2778 def parse(stream
, factory
):
2780 return ("TODO" not in frozenset(entry
.values()))
2782 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
2783 entries
= _csv
.DictReader(lines
)
2784 entries
= filter(match
, entries
)
2785 return tuple(map(factory
, entries
))
2788 class MarkdownDatabase
:
2791 for (name
, desc
) in _ISA():
2794 (dynamic
, *static
) = desc
.regs
2795 operands
.extend(dynamic
)
2796 operands
.extend(static
)
2797 pcode
= PCode(iterable
=desc
.pcode
)
2798 operands
= Operands(insn
=name
, iterable
=operands
)
2799 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
2801 self
.__db
= dict(sorted(db
.items()))
2803 return super().__init
__()
2806 yield from self
.__db
.items()
2808 def __contains__(self
, key
):
2809 return self
.__db
.__contains
__(key
)
2811 def __getitem__(self
, key
):
2812 return self
.__db
.__getitem
__(key
)
2815 class FieldsDatabase
:
2818 df
= _DecodeFields()
2820 for (form
, fields
) in df
.instrs
.items():
2821 if form
in {"DQE", "TX"}:
2825 db
[_Form
[form
]] = Fields(fields
)
2829 return super().__init
__()
2831 def __getitem__(self
, key
):
2832 return self
.__db
.__getitem
__(key
)
2836 def __init__(self
, root
, mdwndb
):
2837 # The code below groups the instructions by name:section.
2838 # There can be multiple names for the same instruction.
2839 # The point is to capture different opcodes for the same instruction.
2840 dd
= _collections
.defaultdict
2842 records
= _collections
.defaultdict(set)
2843 path
= (root
/ "insndb.csv")
2844 with
open(path
, "r", encoding
="UTF-8") as stream
:
2845 for section
in sorted(parse(stream
, Section
.CSV
)):
2846 path
= (root
/ section
.path
)
2848 section
.Mode
.INTEGER
: IntegerOpcode
,
2849 section
.Mode
.PATTERN
: PatternOpcode
,
2851 factory
= _functools
.partial(
2852 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
2853 with
open(path
, "r", encoding
="UTF-8") as stream
:
2854 for insn
in parse(stream
, factory
):
2855 for name
in insn
.names
:
2856 records
[name
].add(insn
)
2857 sections
[name
] = section
2859 items
= sorted(records
.items())
2861 for (name
, multirecord
) in items
:
2862 records
[name
] = PPCMultiRecord(sorted(multirecord
))
2864 def exact_match(name
):
2865 record
= records
.get(name
)
2871 if not name
.endswith("l"):
2873 alias
= exact_match(name
[:-1])
2876 record
= records
[alias
]
2877 if "lk" not in record
.flags
:
2878 raise ValueError(record
)
2882 if not name
.endswith("a"):
2884 alias
= LK_match(name
[:-1])
2887 record
= records
[alias
]
2888 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
2889 raise ValueError(record
)
2890 if "AA" not in mdwndb
[name
].operands
:
2891 raise ValueError(record
)
2895 if not name
.endswith("."):
2897 alias
= exact_match(name
[:-1])
2900 record
= records
[alias
]
2901 if record
.Rc
is _RCOE
.NONE
:
2902 raise ValueError(record
)
2906 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
2907 for (name
, _
) in mdwndb
:
2908 if name
.startswith("sv."):
2911 for match
in matches
:
2913 if alias
is not None:
2917 section
= sections
[alias
]
2918 record
= records
[alias
]
2919 db
[name
] = (section
, record
)
2921 self
.__db
= dict(sorted(db
.items()))
2923 return super().__init
__()
2925 @_functools.lru_cache(maxsize
=512, typed
=False)
2926 def __getitem__(self
, key
):
2927 return self
.__db
.get(key
, (None, None))
2930 class SVP64Database
:
2931 def __init__(self
, root
, ppcdb
):
2933 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
2934 for (prefix
, _
, names
) in _os
.walk(root
):
2935 prefix
= _pathlib
.Path(prefix
)
2936 for name
in filter(lambda name
: pattern
.match(name
), names
):
2937 path
= (prefix
/ _pathlib
.Path(name
))
2938 with
open(path
, "r", encoding
="UTF-8") as stream
:
2939 db
.update(parse(stream
, SVP64Record
.CSV
))
2940 db
= {record
.name
:record
for record
in db
}
2942 self
.__db
= dict(sorted(db
.items()))
2943 self
.__ppcdb
= ppcdb
2945 return super().__init
__()
2947 def __getitem__(self
, key
):
2948 (_
, record
) = self
.__ppcdb
[key
]
2952 for name
in record
.names
:
2953 record
= self
.__db
.get(name
, None)
2954 if record
is not None:
2961 def __init__(self
, root
):
2962 root
= _pathlib
.Path(root
)
2963 mdwndb
= MarkdownDatabase()
2964 fieldsdb
= FieldsDatabase()
2965 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
2966 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
2970 opcodes
= _collections
.defaultdict(
2971 lambda: _collections
.defaultdict(set))
2973 for (name
, mdwn
) in mdwndb
:
2974 if name
.startswith("sv."):
2976 (section
, ppc
) = ppcdb
[name
]
2979 svp64
= svp64db
[name
]
2980 fields
= fieldsdb
[ppc
.form
]
2981 record
= Record(name
=name
,
2982 section
=section
, ppc
=ppc
, svp64
=svp64
,
2983 mdwn
=mdwn
, fields
=fields
)
2985 names
[record
.name
] = record
2989 opcodes
[section
][PO
.value
].add(record
)
2991 self
.__db
= sorted(db
)
2992 self
.__names
= dict(sorted(names
.items()))
2993 self
.__opcodes
= dict(sorted(opcodes
.items()))
2995 return super().__init
__()
2998 return repr(self
.__db
)
3001 yield from self
.__db
3003 @_functools.lru_cache(maxsize
=None)
3004 def __contains__(self
, key
):
3005 return self
.__getitem
__(key
) is not None
3007 @_functools.lru_cache(maxsize
=None)
3008 def __getitem__(self
, key
):
3009 if isinstance(key
, Instruction
):
3012 for (section
, group
) in self
.__opcodes
.items():
3013 for record
in group
[PO
]:
3014 if record
.match(key
=key
):
3019 elif isinstance(key
, str):
3020 return self
.__names
.get(key
)
3022 raise ValueError("instruction or name expected")