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 SVMaskSrc
as _SVMaskSrc
,
38 SVP64RMMode
as _SVP64RMMode
,
39 SVExtraRegType
as _SVExtraRegType
,
40 SVExtraReg
as _SVExtraReg
,
41 SVP64Predicate
as _SVP64Predicate
,
42 SVP64PredicateType
as _SVP64PredicateType
,
43 SVP64SubVL
as _SVP64SubVL
,
45 from openpower
.decoder
.selectable_int
import (
46 SelectableInt
as _SelectableInt
,
47 selectconcat
as _selectconcat
,
49 from openpower
.decoder
.power_fields
import (
52 DecodeFields
as _DecodeFields
,
54 from openpower
.decoder
.pseudo
.pagereader
import ISA
as _ISA
57 @_functools.total_ordering
58 class Verbosity(_enum
.Enum
):
61 VERBOSE
= _enum
.auto()
63 def __lt__(self
, other
):
64 if not isinstance(other
, self
.__class
__):
66 return (self
.value
< other
.value
)
69 @_functools.total_ordering
70 class Priority(_enum
.Enum
):
76 def _missing_(cls
, value
):
77 if isinstance(value
, str):
82 return super()._missing
_(value
)
84 def __lt__(self
, other
):
85 if not isinstance(other
, self
.__class
__):
88 # NOTE: the order is inversed, LOW < NORMAL < HIGH
89 return (self
.value
> other
.value
)
92 def dataclass(cls
, record
, keymap
=None, typemap
=None):
96 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
98 def transform(key_value
):
99 (key
, value
) = key_value
100 key
= keymap
.get(key
, key
)
101 hook
= typemap
.get(key
, lambda value
: value
)
102 if hook
is bool and value
in ("", "0"):
108 record
= dict(map(transform
, record
.items()))
109 for key
in frozenset(record
.keys()):
110 if record
[key
] == "":
116 @_functools.total_ordering
117 @_dataclasses.dataclass(eq
=True, frozen
=True)
120 def __new__(cls
, value
):
121 if isinstance(value
, str):
122 value
= int(value
, 0)
123 if not isinstance(value
, int):
124 raise ValueError(value
)
126 if value
.bit_length() > 64:
127 raise ValueError(value
)
129 return super().__new
__(cls
, value
)
132 return self
.__repr
__()
135 return f
"{self:0{self.bit_length()}b}"
137 def bit_length(self
):
138 if super().bit_length() > 32:
142 class Value(Integer
):
151 def __lt__(self
, other
):
152 if not isinstance(other
, Opcode
):
153 return NotImplemented
154 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
157 def pattern(value
, mask
, bit_length
):
158 for bit
in range(bit_length
):
159 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
161 elif (value
& (1 << (bit_length
- bit
- 1))):
166 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
168 def match(self
, key
):
169 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
172 class IntegerOpcode(Opcode
):
173 def __init__(self
, value
):
174 if value
.startswith("0b"):
175 mask
= int(("1" * len(value
[2:])), 2)
179 value
= Opcode
.Value(value
)
180 mask
= Opcode
.Mask(mask
)
182 return super().__init
__(value
=value
, mask
=mask
)
185 class PatternOpcode(Opcode
):
186 def __init__(self
, pattern
):
187 if not isinstance(pattern
, str):
188 raise ValueError(pattern
)
190 (value
, mask
) = (0, 0)
191 for symbol
in pattern
:
192 if symbol
not in {"0", "1", "-"}:
193 raise ValueError(pattern
)
194 value |
= (symbol
== "1")
195 mask |
= (symbol
!= "-")
201 value
= Opcode
.Value(value
)
202 mask
= Opcode
.Mask(mask
)
204 return super().__init
__(value
=value
, mask
=mask
)
207 @_dataclasses.dataclass(eq
=True, frozen
=True)
209 class FlagsMeta(type):
224 class Flags(frozenset, metaclass
=FlagsMeta
):
225 def __new__(cls
, flags
=frozenset()):
226 flags
= frozenset(flags
)
227 diff
= (flags
- frozenset(cls
))
229 raise ValueError(flags
)
230 return super().__new
__(cls
, flags
)
234 flags
: Flags
= Flags()
236 function
: _Function
= _Function
.NONE
237 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
238 in1
: _In1Sel
= _In1Sel
.RA
239 in2
: _In2Sel
= _In2Sel
.NONE
240 in3
: _In3Sel
= _In3Sel
.NONE
241 out
: _OutSel
= _OutSel
.NONE
242 cr_in
: _CRInSel
= _CRInSel
.NONE
243 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
244 cr_out
: _CROutSel
= _CROutSel
.NONE
245 cry_in
: _CryIn
= _CryIn
.ZERO
246 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
247 upd
: _LDSTMode
= _LDSTMode
.NONE
248 Rc
: _RCOE
= _RCOE
.NONE
249 form
: _Form
= _Form
.NONE
251 unofficial
: bool = False
255 "internal op": "intop",
259 "ldst len": "ldst_len",
261 "CONDITIONS": "conditions",
264 def __lt__(self
, other
):
265 if not isinstance(other
, self
.__class
__):
266 return NotImplemented
267 lhs
= (self
.opcode
, self
.comment
)
268 rhs
= (other
.opcode
, other
.comment
)
272 def CSV(cls
, record
, opcode_cls
):
273 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
274 typemap
["opcode"] = opcode_cls
276 if record
["CR in"] == "BA_BB":
277 record
["cr_in"] = "BA"
278 record
["cr_in2"] = "BB"
282 for flag
in frozenset(PPCRecord
.Flags
):
283 if bool(record
.pop(flag
, "")):
285 record
["flags"] = PPCRecord
.Flags(flags
)
287 return dataclass(cls
, record
,
288 keymap
=PPCRecord
.__KEYMAP
,
293 return frozenset(self
.comment
.split("=")[-1].split("/"))
296 class PPCMultiRecord(tuple):
297 def __getattr__(self
, attr
):
299 raise AttributeError(attr
)
300 return getattr(self
[0], attr
)
303 @_dataclasses.dataclass(eq
=True, frozen
=True)
305 class ExtraMap(tuple):
307 @_dataclasses.dataclass(eq
=True, frozen
=True)
309 regtype
: _SVExtraRegType
= _SVExtraRegType
.NONE
310 reg
: _SVExtraReg
= _SVExtraReg
.NONE
313 return f
"{self.regtype.value}:{self.reg.name}"
315 def __new__(cls
, value
="0"):
316 if isinstance(value
, str):
317 def transform(value
):
318 (regtype
, reg
) = value
.split(":")
319 regtype
= _SVExtraRegType(regtype
)
320 reg
= _SVExtraReg(reg
)
321 return cls
.Entry(regtype
=regtype
, reg
=reg
)
326 value
= map(transform
, value
.split(";"))
328 return super().__new
__(cls
, value
)
331 return repr(list(self
))
333 def __new__(cls
, value
=tuple()):
337 return super().__new
__(cls
, map(cls
.Extra
, value
))
340 return repr({index
:self
[index
] for index
in range(0, 4)})
343 ptype
: _SVPType
= _SVPType
.NONE
344 etype
: _SVEType
= _SVEType
.NONE
345 msrc
: _SVMaskSrc
= _SVMaskSrc
.NO
# MASK_SRC is active
346 in1
: _In1Sel
= _In1Sel
.NONE
347 in2
: _In2Sel
= _In2Sel
.NONE
348 in3
: _In3Sel
= _In3Sel
.NONE
349 out
: _OutSel
= _OutSel
.NONE
350 out2
: _OutSel
= _OutSel
.NONE
351 cr_in
: _CRInSel
= _CRInSel
.NONE
352 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
353 cr_out
: _CROutSel
= _CROutSel
.NONE
354 extra
: ExtraMap
= ExtraMap()
356 mode
: _SVMode
= _SVMode
.NORMAL
360 "CONDITIONS": "conditions",
369 def CSV(cls
, record
):
370 for key
in frozenset({
371 "in1", "in2", "in3", "CR in",
372 "out", "out2", "CR out",
378 if record
["CR in"] == "BA_BB":
379 record
["cr_in"] = "BA"
380 record
["cr_in2"] = "BB"
384 for idx
in range(0, 4):
385 extra
.append(record
.pop(f
"{idx}"))
387 record
["extra"] = cls
.ExtraMap(extra
)
389 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
391 @_functools.lru_cache(maxsize
=None)
392 def extra_idx(self
, key
):
400 if key
not in frozenset({
401 "in1", "in2", "in3", "cr_in", "cr_in2",
402 "out", "out2", "cr_out",
406 sel
= getattr(self
, key
)
407 if sel
is _CRInSel
.BA_BB
:
408 return _SVExtra
.Idx_1_2
409 reg
= _SVExtraReg(sel
)
410 if reg
is _SVExtraReg
.NONE
:
414 _SVExtraRegType
.SRC
: {},
415 _SVExtraRegType
.DST
: {},
417 for index
in range(0, 4):
418 for entry
in self
.extra
[index
]:
419 extra_map
[entry
.regtype
][entry
.reg
] = extra_idx
[index
]
421 for regtype
in (_SVExtraRegType
.SRC
, _SVExtraRegType
.DST
):
422 extra
= extra_map
[regtype
].get(reg
, _SVExtra
.NONE
)
423 if extra
is not _SVExtra
.NONE
:
428 extra_idx_in1
= property(_functools
.partial(extra_idx
, key
="in1"))
429 extra_idx_in2
= property(_functools
.partial(extra_idx
, key
="in2"))
430 extra_idx_in3
= property(_functools
.partial(extra_idx
, key
="in3"))
431 extra_idx_out
= property(_functools
.partial(extra_idx
, key
="out"))
432 extra_idx_out2
= property(_functools
.partial(extra_idx
, key
="out2"))
433 extra_idx_cr_in
= property(_functools
.partial(extra_idx
, key
="cr_in"))
434 extra_idx_cr_in2
= property(_functools
.partial(extra_idx
, key
="cr_in2"))
435 extra_idx_cr_out
= property(_functools
.partial(extra_idx
, key
="cr_out"))
437 @_functools.lru_cache(maxsize
=None)
438 def extra_reg(self
, key
):
439 return _SVExtraReg(getattr(self
, key
))
441 extra_reg_in1
= property(_functools
.partial(extra_reg
, key
="in1"))
442 extra_reg_in2
= property(_functools
.partial(extra_reg
, key
="in2"))
443 extra_reg_in3
= property(_functools
.partial(extra_reg
, key
="in3"))
444 extra_reg_out
= property(_functools
.partial(extra_reg
, key
="out"))
445 extra_reg_out2
= property(_functools
.partial(extra_reg
, key
="out2"))
446 extra_reg_cr_in
= property(_functools
.partial(extra_reg
, key
="cr_in"))
447 extra_reg_cr_in2
= property(_functools
.partial(extra_reg
, key
="cr_in2"))
448 extra_reg_cr_out
= property(_functools
.partial(extra_reg
, key
="cr_out"))
453 for idx
in range(0, 4):
454 for entry
in self
.svp64
.extra
[idx
]:
455 if entry
.regtype
is _SVExtraRegType
.DST
:
456 if regtype
is not None:
457 raise ValueError(self
.svp64
)
458 regtype
= _RegType(entry
.reg
)
459 if regtype
not in (_RegType
.CR_5BIT
, _RegType
.CR_3BIT
):
460 raise ValueError(self
.svp64
)
461 return (regtype
is _RegType
.CR_3BIT
)
465 def __init__(self
, value
=(0, 32)):
466 if isinstance(value
, str):
467 (start
, end
) = map(int, value
.split(":"))
470 if start
< 0 or end
< 0 or start
>= end
:
471 raise ValueError(value
)
476 return super().__init
__()
479 return (self
.__end
- self
.__start
+ 1)
482 return f
"[{self.__start}:{self.__end}]"
485 yield from range(self
.start
, (self
.end
+ 1))
487 def __reversed__(self
):
488 return tuple(reversed(tuple(self
)))
499 @_dataclasses.dataclass(eq
=True, frozen
=True)
501 class Mode(_enum
.Enum
):
502 INTEGER
= _enum
.auto()
503 PATTERN
= _enum
.auto()
506 def _missing_(cls
, value
):
507 if isinstance(value
, str):
508 return cls
[value
.upper()]
509 return super()._missing
_(value
)
512 def __new__(cls
, value
=None):
513 if isinstance(value
, str):
514 if value
.upper() == "NONE":
517 value
= int(value
, 0)
521 return super().__new
__(cls
, value
)
527 return (bin(self
) if self
else "None")
533 opcode
: IntegerOpcode
= None
534 priority
: Priority
= Priority
.NORMAL
536 def __lt__(self
, other
):
537 if not isinstance(other
, self
.__class
__):
538 return NotImplemented
539 return (self
.priority
< other
.priority
)
542 def CSV(cls
, record
):
543 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
544 if record
["opcode"] == "NONE":
545 typemap
["opcode"] = lambda _
: None
547 return dataclass(cls
, record
, typemap
=typemap
)
551 def __init__(self
, items
):
552 if isinstance(items
, dict):
553 items
= items
.items()
556 (name
, bitrange
) = item
557 return (name
, tuple(bitrange
.values()))
559 self
.__mapping
= dict(map(transform
, items
))
561 return super().__init
__()
564 return repr(self
.__mapping
)
567 yield from self
.__mapping
.items()
569 def __contains__(self
, key
):
570 return self
.__mapping
.__contains
__(key
)
572 def __getitem__(self
, key
):
573 return self
.__mapping
.get(key
, None)
577 def __init__(self
, insn
, iterable
):
579 "b": {"target_addr": TargetAddrOperandLI
},
580 "ba": {"target_addr": TargetAddrOperandLI
},
581 "bl": {"target_addr": TargetAddrOperandLI
},
582 "bla": {"target_addr": TargetAddrOperandLI
},
583 "bc": {"target_addr": TargetAddrOperandBD
},
584 "bca": {"target_addr": TargetAddrOperandBD
},
585 "bcl": {"target_addr": TargetAddrOperandBD
},
586 "bcla": {"target_addr": TargetAddrOperandBD
},
587 "addpcis": {"D": DOperandDX
},
588 "fishmv": {"D": DOperandDX
},
589 "fmvis": {"D": DOperandDX
},
592 "SVi": NonZeroOperand
,
593 "SVd": NonZeroOperand
,
594 "SVxd": NonZeroOperand
,
595 "SVyd": NonZeroOperand
,
596 "SVzd": NonZeroOperand
,
598 "D": SignedImmediateOperand
,
602 "SIM": SignedOperand
,
603 "SVD": SignedOperand
,
604 "SVDS": SignedOperand
,
606 custom_immediates
= {
612 for operand
in iterable
:
616 (name
, value
) = operand
.split("=")
617 mapping
[name
] = (StaticOperand
, {
623 if name
.endswith(")"):
624 name
= name
.replace("(", " ").replace(")", "")
625 (immediate
, _
, name
) = name
.partition(" ")
629 if immediate
is not None:
630 cls
= custom_immediates
.get(immediate
, ImmediateOperand
)
632 if insn
in custom_insns
and name
in custom_insns
[insn
]:
633 cls
= custom_insns
[insn
][name
]
634 elif name
in custom_fields
:
635 cls
= custom_fields
[name
]
637 if name
in _RegType
.__members
__:
638 regtype
= _RegType
[name
]
639 if regtype
is _RegType
.GPR
:
641 elif regtype
is _RegType
.FPR
:
643 if regtype
is _RegType
.CR_5BIT
:
645 if regtype
is _RegType
.CR_3BIT
:
648 mapping
[name
] = (cls
, {"name": name
})
652 for (name
, (cls
, kwargs
)) in mapping
.items():
653 kwargs
= dict(kwargs
)
654 kwargs
["name"] = name
655 if issubclass(cls
, StaticOperand
):
656 static
.append((cls
, kwargs
))
657 elif issubclass(cls
, DynamicOperand
):
658 dynamic
.append((cls
, kwargs
))
660 raise ValueError(name
)
662 self
.__mapping
= mapping
663 self
.__static
= tuple(static
)
664 self
.__dynamic
= tuple(dynamic
)
666 return super().__init
__()
669 for (_
, items
) in self
.__mapping
.items():
670 (cls
, kwargs
) = items
674 return self
.__mapping
.__repr
__()
676 def __contains__(self
, key
):
677 return self
.__mapping
.__contains
__(key
)
679 def __getitem__(self
, key
):
680 return self
.__mapping
.__getitem
__(key
)
688 return self
.__dynamic
692 def __init__(self
, iterable
):
693 self
.__pcode
= tuple(iterable
)
694 return super().__init
__()
697 yield from self
.__pcode
700 return self
.__pcode
.__repr
__()
703 @_dataclasses.dataclass(eq
=True, frozen
=True)
704 class MarkdownRecord
:
709 @_functools.total_ordering
710 @_dataclasses.dataclass(eq
=True, frozen
=True)
717 svp64
: SVP64Record
= None
719 def __lt__(self
, other
):
720 if not isinstance(other
, Record
):
721 return NotImplemented
722 lhs
= (min(self
.opcodes
), self
.name
)
723 rhs
= (min(other
.opcodes
), other
.name
)
728 PO
= self
.section
.opcode
730 assert len(self
.ppc
) == 1
731 PO
= self
.ppc
[0].opcode
733 return POStaticOperand(record
=self
,
734 name
="PO", value
=int(PO
.value
), mask
=int(PO
.mask
))
740 PO
= self
.section
.opcode
746 return XOStaticOperand(record
=self
,
747 name
="XO", value
=0, mask
=0)
749 return XOStaticOperand(record
=self
,
750 name
="XO", value
=int(XO
.value
), mask
=int(XO
.mask
))
752 return tuple(dict.fromkeys(map(XO
, self
.ppc
)))
755 def static_operands(self
):
758 operands
.append(self
.PO
)
759 operands
.extend(self
.XO
)
761 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
762 operands
.append(cls(record
=self
, **kwargs
))
764 return tuple(operands
)
767 def dynamic_operands(self
):
770 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
771 operands
.append(cls(record
=self
, **kwargs
))
773 return tuple(operands
)
778 if self
.svp64
is not None:
780 origin_value
= ([0] * bits
)
781 origin_mask
= ([0] * bits
)
783 for operand
in ((self
.PO
,) + tuple(self
.static_operands
)):
784 for (src
, dst
) in enumerate(reversed(operand
.span
)):
785 origin_value
[dst
] = int((operand
.value
& (1 << src
)) != 0)
789 value
= list(origin_value
)
790 mask
= list(origin_mask
)
791 for (src
, dst
) in enumerate(reversed(XO
.span
)):
792 value
[dst
] = int((XO
.value
& (1 << src
)) != 0)
795 value
= Opcode
.Value(int(("".join(map(str, value
))), 2))
796 mask
= Opcode
.Mask(int(("".join(map(str, mask
))), 2))
798 return Opcode(value
=value
, mask
=mask
)
800 return tuple(dict.fromkeys(map(opcode
, self
.XO
)))
802 def match(self
, key
):
803 for opcode
in self
.opcodes
:
804 if opcode
.match(key
):
811 return self
.svp64
.mode
831 if self
.svp64
is None:
837 return self
.ppc
.cr_in
841 return self
.ppc
.cr_in2
845 return self
.ppc
.cr_out
847 ptype
= property(lambda self
: self
.svp64
.ptype
)
848 etype
= property(lambda self
: self
.svp64
.etype
)
850 def extra_idx(self
, key
):
851 return self
.svp64
.extra_idx(key
)
853 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
854 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
855 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
856 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
857 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
858 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
859 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
860 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
862 def __contains__(self
, key
):
863 return self
.mdwn
.operands
.__contains
__(key
)
865 def __getitem__(self
, key
):
866 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
867 return cls(record
=self
, **kwargs
)
873 return self
["Rc"].value
876 @_dataclasses.dataclass(eq
=True, frozen
=True)
879 record
: Record
= _dataclasses
.field(repr=False)
881 def __post_init__(self
):
886 span
= self
.record
.fields
[self
.name
]
887 if self
.record
.svp64
is not None:
888 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
891 def assemble(self
, value
, insn
):
893 if isinstance(value
, str):
894 value
= int(value
, 0)
896 raise ValueError("signed operands not allowed")
899 def disassemble(self
, insn
,
900 verbosity
=Verbosity
.NORMAL
, indent
=""):
901 raise NotImplementedError
904 @_dataclasses.dataclass(eq
=True, frozen
=True)
905 class DynamicOperand(Operand
):
906 def disassemble(self
, insn
,
907 verbosity
=Verbosity
.NORMAL
, indent
=""):
911 if verbosity
>= Verbosity
.VERBOSE
:
912 span
= map(str, span
)
913 yield f
"{indent}{self.name}"
914 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
915 yield f
"{indent}{indent}{', '.join(span)}"
917 yield str(int(value
))
920 @_dataclasses.dataclass(eq
=True, frozen
=True)
921 class SignedOperand(DynamicOperand
):
922 def assemble(self
, value
, insn
):
923 if isinstance(value
, str):
924 value
= int(value
, 0)
925 return super().assemble(value
=value
, insn
=insn
)
927 def disassemble(self
, insn
,
928 verbosity
=Verbosity
.NORMAL
, indent
=""):
932 if verbosity
>= Verbosity
.VERBOSE
:
933 span
= map(str, span
)
934 yield f
"{indent}{self.name}"
935 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
936 yield f
"{indent}{indent}{', '.join(span)}"
938 yield str(value
.to_signed_int())
941 @_dataclasses.dataclass(eq
=True, frozen
=True)
942 class StaticOperand(Operand
):
945 def assemble(self
, insn
):
946 return super().assemble(value
=self
.value
, insn
=insn
)
948 def disassemble(self
, insn
,
949 verbosity
=Verbosity
.NORMAL
, indent
=""):
953 if verbosity
>= Verbosity
.VERBOSE
:
954 span
= map(str, span
)
955 yield f
"{indent}{self.name}"
956 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
957 yield f
"{indent}{indent}{', '.join(span)}"
959 yield str(int(value
))
962 @_dataclasses.dataclass(eq
=True, frozen
=True)
963 class POStaticOperand(StaticOperand
):
968 span
= tuple(range(0, 6))
969 if self
.record
.svp64
is not None:
970 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
974 @_dataclasses.dataclass(eq
=True, frozen
=True)
975 class XOStaticOperand(StaticOperand
):
978 def __post_init__(self
):
979 if self
.record
.section
.opcode
is None:
980 assert self
.value
== 0
981 assert self
.mask
== 0
982 object.__setattr
__(self
, "span", ())
985 bits
= self
.record
.section
.bitsel
986 value
= _SelectableInt(value
=self
.value
, bits
=len(bits
))
987 span
= dict(zip(bits
, range(len(bits
))))
988 span_rev
= {value
:key
for (key
, value
) in span
.items()}
990 # This part is tricky: we could have used self.record.static_operands,
991 # but this would cause an infinite recursion, since this code is called
992 # from the self.record.static_operands method already.
994 operands
.extend(self
.record
.mdwn
.operands
.static
)
995 operands
.extend(self
.record
.mdwn
.operands
.dynamic
)
996 for (cls
, kwargs
) in operands
:
997 operand
= cls(record
=self
.record
, **kwargs
)
998 for idx
in operand
.span
:
999 rev
= span
.pop(idx
, None)
1001 span_rev
.pop(rev
, None)
1003 # This part is simpler: we drop bits which are not in the mask.
1004 for bit
in tuple(span
.values()):
1005 rev
= (len(bits
) - bit
- 1)
1006 if ((self
.mask
& (1 << bit
)) == 0):
1007 idx
= span_rev
.pop(rev
, None)
1011 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1012 span
= tuple(span
.keys())
1013 if self
.record
.svp64
is not None:
1014 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
1016 object.__setattr
__(self
, "value", value
)
1017 object.__setattr
__(self
, "span", span
)
1019 return super().__post
_init
__()
1022 @_dataclasses.dataclass(eq
=True, frozen
=True)
1023 class ImmediateOperand(DynamicOperand
):
1027 @_dataclasses.dataclass(eq
=True, frozen
=True)
1028 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1032 @_dataclasses.dataclass(eq
=True, frozen
=True)
1033 class NonZeroOperand(DynamicOperand
):
1034 def assemble(self
, value
, insn
):
1035 if isinstance(value
, str):
1036 value
= int(value
, 0)
1037 if not isinstance(value
, int):
1038 raise ValueError("non-integer operand")
1040 return super().assemble(value
=value
, insn
=insn
)
1042 def disassemble(self
, insn
,
1043 verbosity
=Verbosity
.NORMAL
, indent
=""):
1047 if verbosity
>= Verbosity
.VERBOSE
:
1048 span
= map(str, span
)
1049 yield f
"{indent}{self.name}"
1050 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1051 yield f
"{indent}{indent}{', '.join(span)}"
1053 yield str(int(value
) + 1)
1056 @_dataclasses.dataclass(eq
=True, frozen
=True)
1057 class ExtendableOperand(DynamicOperand
):
1058 def sv_spec_enter(self
, value
, span
):
1059 return (value
, span
)
1061 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1062 return (value
, span
)
1064 def spec(self
, insn
):
1068 span
= tuple(map(str, span
))
1070 if isinstance(insn
, SVP64Instruction
):
1071 (origin_value
, origin_span
) = (value
, span
)
1072 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1074 extra_idx
= self
.extra_idx
1075 if extra_idx
is _SVExtra
.NONE
:
1076 return (vector
, value
, span
)
1078 if self
.record
.etype
is _SVEType
.EXTRA3
:
1079 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1080 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1081 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1083 raise ValueError(self
.record
.etype
)
1086 vector
= bool(spec
[0])
1087 spec_span
= spec
.__class
__
1088 if self
.record
.etype
is _SVEType
.EXTRA3
:
1089 spec_span
= tuple(map(str, spec_span
[1, 2]))
1091 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1092 spec_span
= tuple(map(str, spec_span
[1,]))
1093 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1096 spec_span
= (spec_span
+ ("{0}",))
1098 spec_span
= (("{0}",) + spec_span
)
1100 raise ValueError(self
.record
.etype
)
1102 vector_shift
= (2 + (5 - value
.bits
))
1103 scalar_shift
= value
.bits
1104 spec_shift
= (5 - value
.bits
)
1106 bits
= (len(span
) + len(spec_span
))
1107 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1108 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1110 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1111 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1113 value
= ((spec
<< scalar_shift
) | value
)
1114 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1116 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1117 origin_value
=origin_value
, origin_span
=origin_span
)
1119 return (vector
, value
, span
)
1122 def extra_reg(self
):
1123 return _SVExtraReg(self
.name
)
1126 def extra_idx(self
):
1127 for key
in frozenset({
1128 "in1", "in2", "in3", "cr_in", "cr_in2",
1129 "out", "out2", "cr_out",
1131 extra_reg
= self
.record
.svp64
.extra_reg(key
=key
)
1132 if extra_reg
is self
.extra_reg
:
1133 return self
.record
.extra_idx(key
=key
)
1135 return _SVExtra
.NONE
1137 def remap(self
, value
, vector
):
1138 raise NotImplementedError
1140 def assemble(self
, value
, insn
, prefix
):
1143 if isinstance(value
, str):
1144 value
= value
.lower()
1145 if value
.startswith("%"):
1147 if value
.startswith("*"):
1148 if not isinstance(insn
, SVP64Instruction
):
1149 raise ValueError(value
)
1152 if value
.startswith(prefix
):
1153 value
= value
[len(prefix
):]
1154 value
= int(value
, 0)
1156 if isinstance(insn
, SVP64Instruction
):
1157 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1159 extra_idx
= self
.extra_idx
1160 if extra_idx
is _SVExtra
.NONE
:
1161 raise ValueError(self
.record
)
1163 if self
.record
.etype
is _SVEType
.EXTRA3
:
1164 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1165 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1166 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1168 raise ValueError(self
.record
.etype
)
1170 return super().assemble(value
=value
, insn
=insn
)
1172 return super().assemble(value
=value
, insn
=insn
)
1174 def disassemble(self
, insn
,
1175 verbosity
=Verbosity
.NORMAL
, prefix
="", indent
=""):
1176 (vector
, value
, span
) = self
.spec(insn
=insn
)
1178 if verbosity
>= Verbosity
.VERBOSE
:
1179 mode
= "vector" if vector
else "scalar"
1180 yield f
"{indent}{self.name} ({mode})"
1181 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1182 yield f
"{indent}{indent}{', '.join(span)}"
1183 if isinstance(insn
, SVP64Instruction
):
1184 extra_idx
= self
.extra_idx
1185 if self
.record
.etype
is _SVEType
.NONE
:
1186 yield f
"{indent}{indent}extra[none]"
1188 etype
= repr(self
.record
.etype
).lower()
1189 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1191 vector
= "*" if vector
else ""
1192 yield f
"{vector}{prefix}{int(value)}"
1195 @_dataclasses.dataclass(eq
=True, frozen
=True)
1196 class SimpleRegisterOperand(ExtendableOperand
):
1197 def remap(self
, value
, vector
):
1199 extra
= (value
& 0b11)
1200 value
= (value
>> 2)
1202 extra
= (value
>> 5)
1203 value
= (value
& 0b11111)
1205 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1206 # (and shrink to a single bit if ok)
1207 if self
.record
.etype
is _SVEType
.EXTRA2
:
1209 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1210 assert (extra
& 0b01) == 0, \
1211 ("vector field %s cannot fit into EXTRA2" % value
)
1212 extra
= (0b10 |
(extra
>> 1))
1214 # range is r0-r63 in increments of 1
1215 assert (extra
>> 1) == 0, \
1216 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1218 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1220 # EXTRA3 vector bit needs marking
1223 raise ValueError(self
.record
.etype
)
1225 return (value
, extra
)
1228 @_dataclasses.dataclass(eq
=True, frozen
=True)
1229 class GPROperand(SimpleRegisterOperand
):
1230 def assemble(self
, value
, insn
):
1231 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1233 def disassemble(self
, insn
,
1234 verbosity
=Verbosity
.NORMAL
, indent
=""):
1235 prefix
= "" if (verbosity
<= Verbosity
.SHORT
) else "r"
1236 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1237 verbosity
=verbosity
, indent
=indent
)
1240 @_dataclasses.dataclass(eq
=True, frozen
=True)
1241 class FPROperand(SimpleRegisterOperand
):
1242 def assemble(self
, value
, insn
):
1243 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1245 def disassemble(self
, insn
,
1246 verbosity
=Verbosity
.NORMAL
, indent
=""):
1247 prefix
= "" if (verbosity
<= Verbosity
.SHORT
) else "f"
1248 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1249 verbosity
=verbosity
, indent
=indent
)
1252 @_dataclasses.dataclass(eq
=True, frozen
=True)
1253 class ConditionRegisterFieldOperand(ExtendableOperand
):
1254 def pattern(name_pattern
):
1255 (name
, pattern
) = name_pattern
1256 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1265 CR
= r
"(?:CR|cr)([0-9]+)"
1267 BIT
= rf
"({'|'.join(CONDS.keys())})"
1268 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1269 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1270 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1271 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1272 XCR
= fr
"{CR}\.{BIT}"
1273 PATTERNS
= tuple(map(pattern
, (
1278 ("BIT+CR", (LBIT
+ CR
)),
1279 ("CR+BIT", (CR
+ RBIT
)),
1280 ("BIT+CR*N", (LBIT
+ CRN
)),
1281 ("CR*N+BIT", (CRN
+ RBIT
)),
1282 ("BIT+N*CR", (LBIT
+ NCR
)),
1283 ("N*CR+BIT", (NCR
+ RBIT
)),
1286 def remap(self
, value
, vector
, regtype
):
1287 if regtype
is _RegType
.CR_5BIT
:
1288 subvalue
= (value
& 0x3)
1292 extra
= (value
& 0xf)
1295 extra
= (value
>> 3)
1298 if self
.record
.etype
is _SVEType
.EXTRA2
:
1300 assert (extra
& 0x7) == 0, \
1301 "vector CR cannot fit into EXTRA2"
1302 extra
= (0x2 |
(extra
>> 3))
1304 assert (extra
>> 1) == 0, \
1305 "scalar CR cannot fit into EXTRA2"
1307 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1309 assert (extra
& 0x3) == 0, \
1310 "vector CR cannot fit into EXTRA3"
1311 extra
= (0x4 |
(extra
>> 2))
1313 assert (extra
>> 2) == 0, \
1314 "scalar CR cannot fit into EXTRA3"
1317 if regtype
is _RegType
.CR_5BIT
:
1318 value
= ((value
<< 2) | subvalue
)
1320 return (value
, extra
)
1322 def assemble(self
, value
, insn
):
1323 if isinstance(value
, str):
1326 if value
.startswith("*"):
1327 if not isinstance(insn
, SVP64Instruction
):
1328 raise ValueError(value
)
1332 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1333 match
= pattern
.match(value
)
1334 if match
is not None:
1335 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1336 values
= match
.groups()
1337 match
= dict(zip(keys
, values
))
1338 CR
= int(match
["CR"])
1342 N
= int(match
.get("N", "1"))
1343 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1344 value
= ((CR
* N
) + BIT
)
1347 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1349 def disassemble(self
, insn
,
1350 verbosity
=Verbosity
.NORMAL
, prefix
="", indent
=""):
1351 (vector
, value
, span
) = self
.spec(insn
=insn
)
1353 if verbosity
>= Verbosity
.VERBOSE
:
1354 mode
= "vector" if vector
else "scalar"
1355 yield f
"{indent}{self.name} ({mode})"
1356 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1357 yield f
"{indent}{indent}{', '.join(span)}"
1358 if isinstance(insn
, SVP64Instruction
):
1359 extra_idx
= self
.extra_idx
1360 if self
.record
.etype
is _SVEType
.NONE
:
1361 yield f
"{indent}{indent}extra[none]"
1363 etype
= repr(self
.record
.etype
).lower()
1364 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1366 vector
= "*" if vector
else ""
1367 cr
= int(value
>> 2)
1369 cond
= ("lt", "gt", "eq", "so")[cc
]
1370 if verbosity
>= Verbosity
.NORMAL
:
1372 if isinstance(insn
, SVP64Instruction
):
1373 yield f
"{vector}cr{cr}.{cond}"
1375 yield f
"4*cr{cr}+{cond}"
1379 yield f
"{vector}{prefix}{int(value)}"
1382 @_dataclasses.dataclass(eq
=True, frozen
=True)
1383 class CR3Operand(ConditionRegisterFieldOperand
):
1384 def remap(self
, value
, vector
):
1385 return super().remap(value
=value
, vector
=vector
,
1386 regtype
=_RegType
.CR_3BIT
)
1389 @_dataclasses.dataclass(eq
=True, frozen
=True)
1390 class CR5Operand(ConditionRegisterFieldOperand
):
1391 def remap(self
, value
, vector
):
1392 return super().remap(value
=value
, vector
=vector
,
1393 regtype
=_RegType
.CR_5BIT
)
1395 def sv_spec_enter(self
, value
, span
):
1396 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1397 return (value
, span
)
1399 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1400 value
= _selectconcat(value
, origin_value
[3:5])
1402 return (value
, span
)
1405 @_dataclasses.dataclass(eq
=True, frozen
=True)
1406 class EXTSOperand(DynamicOperand
):
1407 field
: str # real name to report
1408 nz
: int = 0 # number of zeros
1409 fmt
: str = "d" # integer formatter
1411 def __post_init__(self
):
1413 object.__setattr
__(self
, "field", self
.name
)
1417 span
= self
.record
.fields
[self
.field
]
1418 if self
.record
.svp64
is not None:
1419 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
1422 def disassemble(self
, insn
,
1423 verbosity
=Verbosity
.NORMAL
, indent
=""):
1427 if verbosity
>= Verbosity
.VERBOSE
:
1428 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1429 zeros
= ("0" * self
.nz
)
1430 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1431 yield f
"{indent * 1}{hint}"
1432 yield f
"{indent * 2}{self.field}"
1433 yield f
"{indent * 3}{int(value):0{value.bits}b}{zeros}"
1434 yield f
"{indent * 3}{', '.join(span)}"
1436 value
= _selectconcat(value
,
1437 _SelectableInt(value
=0, bits
=self
.nz
)).to_signed_int()
1438 yield f
"{value:{self.fmt}}"
1441 @_dataclasses.dataclass(eq
=True, frozen
=True)
1442 class TargetAddrOperand(EXTSOperand
):
1447 @_dataclasses.dataclass(eq
=True, frozen
=True)
1448 class TargetAddrOperandLI(TargetAddrOperand
):
1452 @_dataclasses.dataclass(eq
=True, frozen
=True)
1453 class TargetAddrOperandBD(TargetAddrOperand
):
1457 @_dataclasses.dataclass(eq
=True, frozen
=True)
1458 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1463 @_dataclasses.dataclass(eq
=True, frozen
=True)
1464 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1469 @_dataclasses.dataclass(eq
=True, frozen
=True)
1470 class DOperandDX(SignedOperand
):
1473 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1474 operands
= map(cls
, ("d0", "d1", "d2"))
1475 spans
= map(lambda operand
: operand
.span
, operands
)
1476 span
= sum(spans
, tuple())
1477 if self
.record
.svp64
is not None:
1478 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
1481 def disassemble(self
, insn
,
1482 verbosity
=Verbosity
.NORMAL
, indent
=""):
1486 if verbosity
>= Verbosity
.VERBOSE
:
1493 for (subname
, subspan
) in mapping
.items():
1494 operand
= DynamicOperand(name
=subname
)
1497 span
= map(str, span
)
1498 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1499 yield f
"{indent}{indent}{indent}{int(value):0{value.bits}b}"
1500 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1502 yield str(value
.to_signed_int())
1505 class Instruction(_Mapping
):
1507 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1508 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1509 raise ValueError(bits
)
1511 if isinstance(value
, bytes
):
1512 if ((len(value
) * 8) != bits
):
1513 raise ValueError(f
"bit length mismatch")
1514 value
= int.from_bytes(value
, byteorder
=byteorder
)
1516 if isinstance(value
, int):
1517 value
= _SelectableInt(value
=value
, bits
=bits
)
1518 elif isinstance(value
, Instruction
):
1519 value
= value
.storage
1521 if not isinstance(value
, _SelectableInt
):
1522 raise ValueError(value
)
1525 if len(value
) != bits
:
1526 raise ValueError(value
)
1528 value
= _SelectableInt(value
=value
, bits
=bits
)
1530 return cls(storage
=value
)
1533 return hash(int(self
))
1535 def __getitem__(self
, key
):
1536 return self
.storage
.__getitem
__(key
)
1538 def __setitem__(self
, key
, value
):
1539 return self
.storage
.__setitem
__(key
, value
)
1541 def bytes(self
, byteorder
="little"):
1542 nr_bytes
= (len(self
.__class
__) // 8)
1543 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1545 def record(self
, db
):
1548 raise KeyError(self
)
1551 def spec(self
, db
, prefix
):
1552 record
= self
.record(db
=db
)
1554 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1555 self
.dynamic_operands(db
=db
)))
1557 static_operands
= []
1558 for (name
, value
) in self
.static_operands(db
=db
):
1559 static_operands
.append(f
"{name}={value}")
1562 if dynamic_operands
:
1564 operands
+= ",".join(dynamic_operands
)
1567 operands
+= " ".join(static_operands
)
1569 return f
"{prefix}{record.name}{operands}"
1571 def dynamic_operands(self
, db
, verbosity
=Verbosity
.NORMAL
):
1572 record
= self
.record(db
=db
)
1577 for operand
in record
.dynamic_operands
:
1579 value
= " ".join(operand
.disassemble(insn
=self
,
1580 verbosity
=min(verbosity
, Verbosity
.NORMAL
)))
1582 name
= f
"{imm_name}({name})"
1583 value
= f
"{imm_value}({value})"
1585 if isinstance(operand
, ImmediateOperand
):
1592 def static_operands(self
, db
):
1593 record
= self
.record(db
=db
)
1594 for operand
in record
.static_operands
:
1595 yield (operand
.name
, operand
.value
)
1598 def assemble(cls
, db
, opcode
, arguments
=None):
1599 raise NotImplementedError(f
"{cls.__name__}.assemble")
1601 def disassemble(self
, db
,
1603 verbosity
=Verbosity
.NORMAL
):
1604 raise NotImplementedError
1607 class WordInstruction(Instruction
):
1608 _
: _Field
= range(0, 32)
1609 PO
: _Field
= range(0, 6)
1612 def integer(cls
, value
, byteorder
="little"):
1613 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1618 for idx
in range(32):
1619 bit
= int(self
[idx
])
1621 return "".join(map(str, bits
))
1624 def assemble(cls
, db
, opcode
, arguments
=None):
1625 if arguments
is None:
1629 insn
= cls
.integer(value
=0)
1630 for operand
in record
.static_operands
:
1631 operand
.assemble(insn
=insn
)
1633 dynamic_operands
= tuple(record
.dynamic_operands
)
1634 if len(dynamic_operands
) != len(arguments
):
1635 raise ValueError("operands count mismatch")
1636 for (value
, operand
) in zip(arguments
, dynamic_operands
):
1637 operand
.assemble(value
=value
, insn
=insn
)
1641 def disassemble(self
, db
,
1643 verbosity
=Verbosity
.NORMAL
):
1644 if verbosity
<= Verbosity
.SHORT
:
1647 blob
= self
.bytes(byteorder
=byteorder
)
1648 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1653 yield f
"{blob}.long 0x{int(self):08x}"
1656 operands
= tuple(map(_operator
.itemgetter(1),
1657 self
.dynamic_operands(db
=db
, verbosity
=verbosity
)))
1659 operands
= ",".join(operands
)
1660 yield f
"{blob}{record.name} {operands}"
1662 yield f
"{blob}{record.name}"
1664 if verbosity
>= Verbosity
.VERBOSE
:
1666 binary
= self
.binary
1667 spec
= self
.spec(db
=db
, prefix
="")
1668 yield f
"{indent}spec"
1669 yield f
"{indent}{indent}{spec}"
1670 yield f
"{indent}pcode"
1671 for stmt
in record
.mdwn
.pcode
:
1672 yield f
"{indent}{indent}{stmt}"
1673 yield f
"{indent}binary"
1674 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1675 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1676 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1677 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1678 yield f
"{indent}opcodes"
1679 for opcode
in record
.opcodes
:
1680 yield f
"{indent}{indent}{opcode!r}"
1681 for (cls
, kwargs
) in record
.mdwn
.operands
:
1682 operand
= cls(record
=record
, **kwargs
)
1683 yield from operand
.disassemble(insn
=self
,
1684 verbosity
=verbosity
, indent
=indent
)
1688 class PrefixedInstruction(Instruction
):
1689 class Prefix(WordInstruction
.remap(range(0, 32))):
1692 class Suffix(WordInstruction
.remap(range(32, 64))):
1695 _
: _Field
= range(64)
1701 def integer(cls
, value
, byteorder
="little"):
1702 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
1705 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
1706 def transform(value
):
1707 return WordInstruction
.integer(value
=value
,
1708 byteorder
=byteorder
)[0:32]
1710 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
1711 value
= _selectconcat(prefix
, suffix
)
1713 return super().integer(bits
=64, value
=value
)
1716 class Mode(_Mapping
):
1717 _
: _Field
= range(0, 5)
1718 sel
: _Field
= (0, 1)
1721 class Extra(_Mapping
):
1722 _
: _Field
= range(0, 9)
1725 class Extra2(Extra
):
1726 idx0
: _Field
= range(0, 2)
1727 idx1
: _Field
= range(2, 4)
1728 idx2
: _Field
= range(4, 6)
1729 idx3
: _Field
= range(6, 8)
1731 def __getitem__(self
, key
):
1737 _SVExtra
.Idx0
: self
.idx0
,
1738 _SVExtra
.Idx1
: self
.idx1
,
1739 _SVExtra
.Idx2
: self
.idx2
,
1740 _SVExtra
.Idx3
: self
.idx3
,
1743 def __setitem__(self
, key
, value
):
1744 self
[key
].assign(value
)
1747 class Extra3(Extra
):
1748 idx0
: _Field
= range(0, 3)
1749 idx1
: _Field
= range(3, 6)
1750 idx2
: _Field
= range(6, 9)
1752 def __getitem__(self
, key
):
1757 _SVExtra
.Idx0
: self
.idx0
,
1758 _SVExtra
.Idx1
: self
.idx1
,
1759 _SVExtra
.Idx2
: self
.idx2
,
1762 def __setitem__(self
, key
, value
):
1763 self
[key
].assign(value
)
1766 class BaseRM(_Mapping
):
1767 _
: _Field
= range(24)
1768 mmode
: _Field
= (0,)
1769 mask
: _Field
= range(1, 4)
1770 elwidth
: _Field
= range(4, 6)
1771 ewsrc
: _Field
= range(6, 8)
1772 subvl
: _Field
= range(8, 10)
1773 mode
: Mode
.remap(range(19, 24))
1774 smask
: _Field
= range(16, 19)
1775 extra
: Extra
.remap(range(10, 19))
1776 extra2
: Extra2
.remap(range(10, 19))
1777 extra3
: Extra3
.remap(range(10, 19))
1779 def specifiers(self
, record
):
1780 subvl
= int(self
.subvl
)
1788 def disassemble(self
, verbosity
=Verbosity
.NORMAL
):
1789 if verbosity
>= Verbosity
.VERBOSE
:
1791 for (name
, span
) in self
.traverse(path
="RM"):
1792 value
= self
.storage
[span
]
1794 yield f
"{indent}{int(value):0{value.bits}b}"
1795 yield f
"{indent}{', '.join(map(str, span))}"
1798 class FFPRRc1BaseRM(BaseRM
):
1799 def specifiers(self
, record
, mode
):
1800 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
1801 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
1802 mask
= int(_selectconcat(CR
, inv
))
1803 predicate
= PredicateBaseRM
.predicate(True, mask
)
1804 yield f
"{mode}={predicate}"
1806 yield from super().specifiers(record
=record
)
1809 class FFPRRc0BaseRM(BaseRM
):
1810 def specifiers(self
, record
, mode
):
1812 inv
= "~" if self
.inv
else ""
1813 yield f
"{mode}={inv}RC1"
1815 yield from super().specifiers(record
=record
)
1818 class SatBaseRM(BaseRM
):
1819 def specifiers(self
, record
):
1825 yield from super().specifiers(record
=record
)
1828 class ZZBaseRM(BaseRM
):
1829 def specifiers(self
, record
):
1833 yield from super().specifiers(record
=record
)
1836 class DZBaseRM(BaseRM
):
1837 def specifiers(self
, record
):
1841 yield from super().specifiers(record
=record
)
1844 class SZBaseRM(BaseRM
):
1845 def specifiers(self
, record
):
1849 yield from super().specifiers(record
=record
)
1852 class MRBaseRM(BaseRM
):
1853 def specifiers(self
, record
):
1859 yield from super().specifiers(record
=record
)
1862 class ElsBaseRM(BaseRM
):
1863 def specifiers(self
, record
):
1867 yield from super().specifiers(record
=record
)
1870 class WidthBaseRM(BaseRM
):
1872 def width(FP
, width
):
1881 width
= ("fp" + width
)
1884 def specifiers(self
, record
):
1885 # elwidths: use "w=" if same otherwise dw/sw
1886 # FIXME this should consider FP instructions
1888 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
1889 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
1898 yield from super().specifiers(record
=record
)
1901 class PredicateBaseRM(BaseRM
):
1903 def predicate(CR
, mask
):
1906 (False, 0b001): "1<<r3",
1907 (False, 0b010): "r3",
1908 (False, 0b011): "~r3",
1909 (False, 0b100): "r10",
1910 (False, 0b101): "~r10",
1911 (False, 0b110): "r30",
1912 (False, 0b111): "~r30",
1914 (True, 0b000): "lt",
1915 (True, 0b001): "ge",
1916 (True, 0b010): "gt",
1917 (True, 0b011): "le",
1918 (True, 0b100): "eq",
1919 (True, 0b101): "ne",
1920 (True, 0b110): "so",
1921 (True, 0b111): "ns",
1924 def specifiers(self
, record
):
1925 # predication - single and twin
1926 # use "m=" if same otherwise sm/dm
1927 CR
= (int(self
.mmode
) == 1)
1928 mask
= int(self
.mask
)
1929 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
1930 if record
.svp64
.ptype
is _SVPType
.P2
:
1931 smask
= int(self
.smask
)
1932 sm
= PredicateBaseRM
.predicate(CR
, smask
)
1941 yield from super().specifiers(record
=record
)
1944 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
1948 class SEABaseRM(BaseRM
):
1949 def specifiers(self
, record
):
1953 yield from super().specifiers(record
=record
)
1956 class VLiBaseRM(BaseRM
):
1957 def specifiers(self
, record
):
1961 yield from super().specifiers(record
=record
)
1964 class NormalBaseRM(PredicateWidthBaseRM
):
1967 https://libre-soc.org/openpower/sv/normal/
1972 class NormalSimpleRM(DZBaseRM
, SZBaseRM
, NormalBaseRM
):
1973 """normal: simple mode"""
1977 def specifiers(self
, record
):
1978 yield from super().specifiers(record
=record
)
1981 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
1982 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
1986 class NormalFFRc1RM(FFPRRc1BaseRM
, NormalBaseRM
):
1987 """normal: Rc=1: ffirst CR sel"""
1989 CR
: BaseRM
.mode
[3, 4]
1991 def specifiers(self
, record
):
1992 yield from super().specifiers(record
=record
, mode
="ff")
1995 class NormalFFRc0RM(FFPRRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
1996 """normal: Rc=0: ffirst z/nonz"""
2001 def specifiers(self
, record
):
2002 yield from super().specifiers(record
=record
, mode
="ff")
2005 class NormalSatRM(SatBaseRM
, DZBaseRM
, SZBaseRM
, NormalBaseRM
):
2006 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2012 class NormalPRRc1RM(FFPRRc1BaseRM
, NormalBaseRM
):
2013 """normal: Rc=1: pred-result CR sel"""
2015 CR
: BaseRM
.mode
[3, 4]
2017 def specifiers(self
, record
):
2018 yield from super().specifiers(record
=record
, mode
="pr")
2021 class NormalPRRc0RM(FFPRRc0BaseRM
, ZZBaseRM
, NormalBaseRM
):
2022 """normal: Rc=0: pred-result z/nonz"""
2029 def specifiers(self
, record
):
2030 yield from super().specifiers(record
=record
, mode
="pr")
2033 class NormalRM(NormalBaseRM
):
2034 simple
: NormalSimpleRM
2036 ffrc1
: NormalFFRc1RM
2037 ffrc0
: NormalFFRc0RM
2039 prrc1
: NormalPRRc1RM
2040 prrc0
: NormalPRRc0RM
2043 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2045 LD/ST Immediate mode
2046 https://libre-soc.org/openpower/sv/ldst/
2051 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2052 """ld/st immediate: simple mode"""
2059 class LDSTImmPostRM(LDSTImmBaseRM
):
2060 """ld/st immediate: postinc mode (and load-fault)"""
2061 pi
: BaseRM
.mode
[3] # Post-Increment Mode
2062 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2064 def specifiers(self
, record
):
2071 class LDSTImmFFRc1RM(FFPRRc1BaseRM
, LDSTImmBaseRM
):
2072 """ld/st immediate: Rc=1: ffirst CR sel"""
2074 CR
: BaseRM
.mode
[3, 4]
2076 def specifiers(self
, record
):
2077 yield from super().specifiers(record
=record
, mode
="ff")
2080 class LDSTImmFFRc0RM(FFPRRc0BaseRM
, ElsBaseRM
, LDSTImmBaseRM
):
2081 """ld/st immediate: Rc=0: ffirst z/nonz"""
2086 def specifiers(self
, record
):
2087 yield from super().specifiers(record
=record
, mode
="ff")
2090 class LDSTImmSatRM(ElsBaseRM
, SatBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2091 """ld/st immediate: sat mode: N=0/1 u/s"""
2099 class LDSTImmPRRc1RM(FFPRRc1BaseRM
, LDSTImmBaseRM
):
2100 """ld/st immediate: Rc=1: pred-result CR sel"""
2102 CR
: BaseRM
.mode
[3, 4]
2104 def specifiers(self
, record
):
2105 yield from super().specifiers(record
=record
, mode
="pr")
2108 class LDSTImmPRRc0RM(FFPRRc0BaseRM
, ElsBaseRM
, LDSTImmBaseRM
):
2109 """ld/st immediate: Rc=0: pred-result z/nonz"""
2114 def specifiers(self
, record
):
2115 yield from super().specifiers(record
=record
, mode
="pr")
2118 class LDSTImmRM(LDSTImmBaseRM
):
2119 simple
: LDSTImmSimpleRM
2121 ffrc1
: LDSTImmFFRc1RM
2122 ffrc0
: LDSTImmFFRc0RM
2124 prrc1
: LDSTImmPRRc1RM
2125 prrc0
: LDSTImmPRRc0RM
2128 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2131 https://libre-soc.org/openpower/sv/ldst/
2136 class LDSTIdxSimpleRM(SEABaseRM
, DZBaseRM
, SZBaseRM
, LDSTIdxBaseRM
):
2137 """ld/st index: simple mode"""
2143 class LDSTIdxStrideRM(SEABaseRM
, DZBaseRM
, SZBaseRM
, LDSTIdxBaseRM
):
2144 """ld/st index: strided (scalar only source)"""
2149 def specifiers(self
, record
):
2152 yield from super().specifiers(record
=record
)
2155 class LDSTIdxSatRM(SatBaseRM
, DZBaseRM
, SZBaseRM
, LDSTIdxBaseRM
):
2156 """ld/st index: sat mode: N=0/1 u/s"""
2162 class LDSTIdxPRRc1RM(LDSTIdxBaseRM
):
2163 """ld/st index: Rc=1: pred-result CR sel"""
2165 CR
: BaseRM
.mode
[3, 4]
2167 def specifiers(self
, record
):
2168 yield from super().specifiers(record
=record
, mode
="pr")
2171 class LDSTIdxPRRc0RM(FFPRRc0BaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2172 """ld/st index: Rc=0: pred-result z/nonz"""
2179 def specifiers(self
, record
):
2180 yield from super().specifiers(record
=record
, mode
="pr")
2183 class LDSTIdxRM(LDSTIdxBaseRM
):
2184 simple
: LDSTIdxSimpleRM
2185 stride
: LDSTIdxStrideRM
2187 prrc1
: LDSTIdxPRRc1RM
2188 prrc0
: LDSTIdxPRRc0RM
2192 class CROpBaseRM(BaseRM
):
2195 https://libre-soc.org/openpower/sv/cr_ops/
2200 class CROpSimpleRM(PredicateBaseRM
, DZBaseRM
, SZBaseRM
, CROpBaseRM
):
2201 """cr_op: simple mode"""
2206 def specifiers(self
, record
):
2208 yield "rg" # simple CR Mode reports /rg
2210 yield from super().specifiers(record
=record
)
2212 class CROpMRRM(MRBaseRM
, DZBaseRM
, SZBaseRM
, CROpBaseRM
):
2213 """cr_op: scalar reduce mode (mapreduce), SUBVL=1"""
2219 class CROpFF3RM(FFPRRc1BaseRM
, VLiBaseRM
, ZZBaseRM
, PredicateBaseRM
, CROpBaseRM
):
2220 """cr_op: ffirst 3-bit mode"""
2228 def specifiers(self
, record
):
2229 yield from super().specifiers(record
=record
, mode
="ff")
2232 class CROpFF5RM(FFPRRc0BaseRM
, PredicateBaseRM
,
2233 VLiBaseRM
, DZBaseRM
, SZBaseRM
, CROpBaseRM
):
2234 """cr_op: ffirst 5-bit mode"""
2237 RC1
: BaseRM
[19] # cheat: set RC=1 based on ffirst mode being set
2241 def specifiers(self
, record
):
2242 yield from super().specifiers(record
=record
, mode
="ff")
2245 class CROpRM(CROpBaseRM
):
2246 simple
: CROpSimpleRM
2252 # ********************
2254 # https://libre-soc.org/openpower/sv/branches/
2255 class BranchBaseRM(BaseRM
):
2265 def specifiers(self
, record
):
2277 raise ValueError(self
.sz
)
2289 # Branch modes lack source mask.
2290 # Therefore a custom code is needed.
2291 CR
= (int(self
.mmode
) == 1)
2292 mask
= int(self
.mask
)
2293 m
= PredicateBaseRM
.predicate(CR
, mask
)
2297 yield from super().specifiers(record
=record
)
2300 class BranchSimpleRM(BranchBaseRM
):
2301 """branch: simple mode"""
2305 class BranchVLSRM(BranchBaseRM
):
2306 """branch: VLSET mode"""
2310 def specifiers(self
, record
):
2316 }[int(self
.VSb
), int(self
.VLi
)]
2318 yield from super().specifiers(record
=record
)
2321 class BranchCTRRM(BranchBaseRM
):
2322 """branch: CTR-test mode"""
2325 def specifiers(self
, record
):
2331 yield from super().specifiers(record
=record
)
2334 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2335 """branch: CTR-test+VLSET mode"""
2339 class BranchRM(BranchBaseRM
):
2340 simple
: BranchSimpleRM
2343 ctrvls
: BranchCTRVLSRM
2353 def select(self
, record
):
2357 # the idea behind these tables is that they are now literally
2358 # in identical format to insndb.csv and minor_xx.csv and can
2359 # be done precisely as that. the only thing to watch out for
2360 # is the insertion of Rc=1 as a "mask/value" bit and likewise
2361 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
2364 if record
.svp64
.mode
is _SVMode
.NORMAL
:
2365 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
2366 # mode Rc mask Rc member
2368 (0b000000, 0b111000, "simple"), # simple (no Rc)
2369 (0b001000, 0b111000, "mr"), # mapreduce (no Rc)
2370 (0b010001, 0b110001, "ffrc1"), # ffirst, Rc=1
2371 (0b010000, 0b110001, "ffrc0"), # ffirst, Rc=0
2372 (0b100000, 0b110000, "sat"), # saturation (no Rc)
2373 (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
2374 (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
2377 search
= ((int(rm
.mode
) << 1) | Rc
)
2379 elif record
.svp64
.mode
is _SVMode
.LDST_IMM
:
2380 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
2381 # mode Rc mask Rc member
2382 # ironically/coincidentally this table is identical to NORMAL
2383 # mode except reserved in place of mr
2385 (0b000000, 0b111000, "simple"), # simple (no Rc)
2386 (0b001000, 0b111000, "post"), # post (no Rc)
2387 (0b010001, 0b110001, "ffrc1"), # ffirst, Rc=1
2388 (0b010000, 0b110001, "ffrc0"), # ffirst, Rc=0
2389 (0b100000, 0b110000, "sat"), # saturation (no Rc)
2390 (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
2391 (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
2394 search
= ((int(rm
.mode
) << 1) | Rc
)
2396 elif record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2397 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
2398 # mode Rc mask Rc member
2400 (0b000000, 0b110000, "simple"), # simple (no Rc)
2401 (0b010000, 0b110000, "stride"), # strided, (no Rc)
2402 (0b100000, 0b110000, "sat"), # saturation (no Rc)
2403 (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
2404 (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
2407 search
= ((int(rm
.mode
) << 1) | Rc
)
2409 elif record
.svp64
.mode
is _SVMode
.CROP
:
2410 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
2411 # mode 3b mask 3b member
2413 (0b000000, 0b111000, "simple"), # simple
2414 (0b001000, 0b111000, "mr"), # mapreduce
2415 (0b100001, 0b100001, "ff3"), # ffirst, 3-bit CR
2416 (0b100000, 0b100000, "ff5"), # ffirst, 5-bit CR
2419 search
= ((int(rm
.mode
) << 1) |
int(record
.svp64
.cr_3bit
))
2421 elif record
.svp64
.mode
is _SVMode
.BRANCH
:
2425 (0b00, 0b11, "simple"), # simple
2426 (0b01, 0b11, "vls"), # VLset
2427 (0b10, 0b11, "ctr"), # CTR mode
2428 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
2430 # slightly weird: doesn't have a 5-bit "mode" field like others
2432 search
= int(rm
.mode
.sel
)
2435 if table
is not None:
2436 for (value
, mask
, member
) in table
:
2437 if ((value
& mask
) == (search
& mask
)):
2438 rm
= getattr(rm
, member
)
2441 if rm
.__class
__ is self
.__class
__:
2442 raise ValueError(self
)
2447 @_dataclasses.dataclass(eq
=True, frozen
=True)
2452 def match(cls
, desc
, record
):
2453 raise NotImplementedError
2455 def validate(self
, others
):
2458 def assemble(self
, insn
):
2459 raise NotImplementedError
2462 @_dataclasses.dataclass(eq
=True, frozen
=True)
2463 class SpecifierWidth(Specifier
):
2468 def match(cls
, desc
, record
):
2469 (mode
, _
, value
) = desc
.partition("=")
2471 value
= value
.strip()
2472 if mode
not in ("w", "sw", "dw"):
2474 if value
not in ("8", "16", "32"):
2475 raise ValueError(value
)
2477 value
= {"8": 3, "16": 2, "32": 1}[value
]
2479 return cls(record
=record
, mode
=mode
, value
=value
)
2481 def assemble(self
, insn
):
2482 if self
.mode
== "sw":
2483 insn
.prefix
.rm
.ewsrc
= self
.value
2484 elif self
.mode
== "dw":
2485 insn
.prefix
.rm
.elwidth
= self
.value
2487 insn
.prefix
.rm
.ewsrc
= self
.value
2488 insn
.prefix
.rm
.elwidth
= self
.value
2491 @_dataclasses.dataclass(eq
=True, frozen
=True)
2492 class SpecifierSubVL(Specifier
):
2496 def match(cls
, desc
, record
):
2498 value
= _SVP64SubVL(desc
)
2502 return cls(record
=record
, value
=value
)
2504 def assemble(self
, insn
):
2505 insn
.prefix
.rm
.subvl
= int(self
.value
.value
)
2508 @_dataclasses.dataclass(eq
=True, frozen
=True)
2509 class SpecifierPredicate(Specifier
):
2511 pred
: _SVP64Predicate
2514 def match(cls
, desc
, record
, mode_match
, pred_match
):
2515 (mode
, _
, pred
) = desc
.partition("=")
2518 if not mode_match(mode
):
2521 pred
= _SVP64Predicate(pred
.strip())
2522 if not pred_match(pred
):
2523 raise ValueError(pred
)
2525 return cls(record
=record
, mode
=mode
, pred
=pred
)
2528 @_dataclasses.dataclass(eq
=True, frozen
=True)
2529 class SpecifierFFPR(SpecifierPredicate
):
2531 def match(cls
, desc
, record
, mode
):
2532 return super().match(desc
=desc
, record
=record
,
2533 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2534 pred_match
=lambda pred_arg
: pred_arg
.type in (
2535 _SVP64PredicateType
.CR
,
2536 _SVP64PredicateType
.RC1
,
2539 def assemble(self
, insn
):
2541 if rm
.mode
.sel
!= 0:
2542 raise ValueError("cannot override mode")
2544 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2545 if self
.mode
== "pr":
2546 raise ValueError("crop: 'pr' mode not supported")
2548 if self
.record
.svp64
.cr_3bit
:
2553 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
2555 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
2557 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2559 if self
.mode
== "ff":
2560 raise ValueError("ld/st idx: 'ff' mode not supported")
2562 raise ValueError(f
"{self.mode!r} not supported")
2564 # These 2-bit values should have bits swapped
2566 return (((value
& 0b10) >> 1) |
((value
& 0b01) << 1))
2569 "ff": bitswap(_SVP64RMMode
.FFIRST
.value
),
2570 "pr": bitswap(_SVP64RMMode
.PREDRES
.value
),
2573 Rc
= int(self
.record
.Rc
)
2574 rm
= getattr(rm
, f
"{self.mode}rc{Rc}")
2575 rm
.inv
= self
.pred
.inv
2577 rm
.CR
= self
.pred
.state
2579 rm
.RC1
= self
.pred
.state
2582 @_dataclasses.dataclass(eq
=True, frozen
=True)
2583 class SpecifierFF(SpecifierFFPR
):
2585 def match(cls
, desc
, record
):
2586 return super().match(desc
=desc
, record
=record
, mode
="ff")
2589 @_dataclasses.dataclass(eq
=True, frozen
=True)
2590 class SpecifierPR(SpecifierFFPR
):
2592 def match(cls
, desc
, record
):
2593 return super().match(desc
=desc
, record
=record
, mode
="pr")
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
.type in (
2603 _SVP64PredicateType
.INTEGER
,
2604 _SVP64PredicateType
.CR
,
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
):
2618 items
= list(others
)
2621 if isinstance(spec
, SpecifierSM
):
2622 raise ValueError("source-mask and predicate mask conflict")
2623 elif isinstance(spec
, SpecifierDM
):
2624 raise ValueError("dest-mask and predicate mask conflict")
2625 spec
.validate(others
=items
)
2627 def assemble(self
, insn
):
2628 insn
.prefix
.rm
.mask
= self
.pred
.mask
2631 @_dataclasses.dataclass(eq
=True, frozen
=True)
2632 class SpecifierSM(SpecifierMask
):
2634 def match(cls
, desc
, record
):
2635 return super().match(desc
=desc
, record
=record
, mode
="sm")
2637 def validate(self
, others
):
2638 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2639 raise ValueError("source-mask on non-twin predicate")
2641 if self
.pred
.type is _SVP64PredicateType
.CR
:
2643 items
= list(others
)
2646 if isinstance(spec
, SpecifierDM
):
2648 spec
.validate(others
=items
)
2651 raise ValueError("missing dest-mask in CR twin predication")
2652 if self
.pred
!= twin
.pred
:
2653 raise ValueError(f
"predicate masks mismatch: {self!r} vs {twin!r}")
2655 def assemble(self
, insn
):
2656 insn
.prefix
.rm
.smask
= self
.pred
.mask
2659 @_dataclasses.dataclass(eq
=True, frozen
=True)
2660 class SpecifierDM(SpecifierMask
):
2662 def match(cls
, desc
, record
):
2663 return super().match(desc
=desc
, record
=record
, mode
="dm")
2665 def validate(self
, others
):
2666 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2667 raise ValueError("dest-mask on non-twin predicate")
2669 if self
.pred
.type is _SVP64PredicateType
.CR
:
2671 items
= list(others
)
2674 if isinstance(spec
, SpecifierSM
):
2676 spec
.validate(others
=items
)
2679 raise ValueError("missing source-mask in CR twin predication")
2680 if self
.pred
!= twin
.pred
:
2681 raise ValueError(f
"predicate masks mismatch: {self!r} vs {twin!r}")
2683 def assemble(self
, insn
):
2684 insn
.prefix
.rm
.mask
= self
.pred
.mask
2687 class Specifiers(tuple):
2698 def __new__(cls
, items
, record
):
2699 def transform(item
):
2700 for spec_cls
in cls
.SPECS
:
2701 spec
= spec_cls
.match(item
, record
=record
)
2702 if spec
is not None:
2704 raise ValueError(item
)
2706 specs
= tuple(map(transform
, items
))
2710 spec
.validate(others
=items
)
2712 return super().__new
__(cls
, specs
)
2715 class SVP64Instruction(PrefixedInstruction
):
2716 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
2717 class Prefix(PrefixedInstruction
.Prefix
):
2719 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
2723 def record(self
, db
):
2724 record
= db
[self
.suffix
]
2726 raise KeyError(self
)
2732 for idx
in range(64):
2733 bit
= int(self
[idx
])
2735 return "".join(map(str, bits
))
2738 def assemble(cls
, db
, opcode
, arguments
=None, specifiers
=None):
2739 if arguments
is None:
2741 if specifiers
is None:
2745 insn
= cls
.integer(value
=0)
2747 specifiers
= Specifiers(items
=specifiers
, record
=record
)
2748 for specifier
in specifiers
:
2749 specifier
.assemble(insn
=insn
)
2751 for operand
in record
.static_operands
:
2752 operand
.assemble(insn
=insn
)
2754 dynamic_operands
= tuple(record
.dynamic_operands
)
2755 if len(dynamic_operands
) != len(arguments
):
2756 raise ValueError("operands count mismatch")
2757 for (value
, operand
) in zip(arguments
, dynamic_operands
):
2758 operand
.assemble(value
=value
, insn
=insn
)
2760 insn
.prefix
.PO
= 0x1
2761 insn
.prefix
.id = 0x3
2765 def disassemble(self
, db
,
2767 verbosity
=Verbosity
.NORMAL
):
2769 if verbosity
<= Verbosity
.SHORT
:
2772 blob
= insn
.bytes(byteorder
=byteorder
)
2773 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
2776 record
= self
.record(db
=db
)
2777 blob_prefix
= blob(self
.prefix
)
2778 blob_suffix
= blob(self
.suffix
)
2779 if record
is None or record
.svp64
is None:
2780 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
2781 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
2784 name
= f
"sv.{record.name}"
2786 rm
= self
.prefix
.rm
.select(record
=record
)
2788 # convert specifiers to /x/y/z (sorted lexicographically)
2789 specifiers
= sorted(rm
.specifiers(record
=record
))
2790 if specifiers
: # if any add one extra to get the extra "/"
2791 specifiers
= ([""] + specifiers
)
2792 specifiers
= "/".join(specifiers
)
2794 # convert operands to " ,x,y,z"
2795 operands
= tuple(map(_operator
.itemgetter(1),
2796 self
.dynamic_operands(db
=db
, verbosity
=verbosity
)))
2797 operands
= ",".join(operands
)
2798 if len(operands
) > 0: # if any separate with a space
2799 operands
= (" " + operands
)
2801 yield f
"{blob_prefix}{name}{specifiers}{operands}"
2803 yield f
"{blob_suffix}"
2805 if verbosity
>= Verbosity
.VERBOSE
:
2807 binary
= self
.binary
2808 spec
= self
.spec(db
=db
, prefix
="sv.")
2810 yield f
"{indent}spec"
2811 yield f
"{indent}{indent}{spec}"
2812 yield f
"{indent}pcode"
2813 for stmt
in record
.mdwn
.pcode
:
2814 yield f
"{indent}{indent}{stmt}"
2815 yield f
"{indent}binary"
2816 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
2817 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
2818 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
2819 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
2820 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
2821 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
2822 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
2823 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
2824 yield f
"{indent}opcodes"
2825 for opcode
in record
.opcodes
:
2826 yield f
"{indent}{indent}{opcode!r}"
2827 for (cls
, kwargs
) in record
.mdwn
.operands
:
2828 operand
= cls(record
=record
, **kwargs
)
2829 yield from operand
.disassemble(insn
=self
,
2830 verbosity
=verbosity
, indent
=indent
)
2832 yield f
"{indent}{indent}{rm.__doc__}"
2833 for line
in rm
.disassemble(verbosity
=verbosity
):
2834 yield f
"{indent}{indent}{line}"
2838 def parse(stream
, factory
):
2840 return ("TODO" not in frozenset(entry
.values()))
2842 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
2843 entries
= _csv
.DictReader(lines
)
2844 entries
= filter(match
, entries
)
2845 return tuple(map(factory
, entries
))
2848 class MarkdownDatabase
:
2851 for (name
, desc
) in _ISA():
2854 (dynamic
, *static
) = desc
.regs
2855 operands
.extend(dynamic
)
2856 operands
.extend(static
)
2857 pcode
= PCode(iterable
=desc
.pcode
)
2858 operands
= Operands(insn
=name
, iterable
=operands
)
2859 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
2861 self
.__db
= dict(sorted(db
.items()))
2863 return super().__init
__()
2866 yield from self
.__db
.items()
2868 def __contains__(self
, key
):
2869 return self
.__db
.__contains
__(key
)
2871 def __getitem__(self
, key
):
2872 return self
.__db
.__getitem
__(key
)
2875 class FieldsDatabase
:
2878 df
= _DecodeFields()
2880 for (form
, fields
) in df
.instrs
.items():
2881 if form
in {"DQE", "TX"}:
2885 db
[_Form
[form
]] = Fields(fields
)
2889 return super().__init
__()
2891 def __getitem__(self
, key
):
2892 return self
.__db
.__getitem
__(key
)
2896 def __init__(self
, root
, mdwndb
):
2897 # The code below groups the instructions by name:section.
2898 # There can be multiple names for the same instruction.
2899 # The point is to capture different opcodes for the same instruction.
2900 dd
= _collections
.defaultdict
2902 records
= _collections
.defaultdict(set)
2903 path
= (root
/ "insndb.csv")
2904 with
open(path
, "r", encoding
="UTF-8") as stream
:
2905 for section
in sorted(parse(stream
, Section
.CSV
)):
2906 path
= (root
/ section
.path
)
2908 section
.Mode
.INTEGER
: IntegerOpcode
,
2909 section
.Mode
.PATTERN
: PatternOpcode
,
2911 factory
= _functools
.partial(
2912 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
2913 with
open(path
, "r", encoding
="UTF-8") as stream
:
2914 for insn
in parse(stream
, factory
):
2915 for name
in insn
.names
:
2916 records
[name
].add(insn
)
2917 sections
[name
] = section
2919 items
= sorted(records
.items())
2921 for (name
, multirecord
) in items
:
2922 records
[name
] = PPCMultiRecord(sorted(multirecord
))
2924 def exact_match(name
):
2925 record
= records
.get(name
)
2931 if not name
.endswith("l"):
2933 alias
= exact_match(name
[:-1])
2936 record
= records
[alias
]
2937 if "lk" not in record
.flags
:
2938 raise ValueError(record
)
2942 if not name
.endswith("a"):
2944 alias
= LK_match(name
[:-1])
2947 record
= records
[alias
]
2948 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
2949 raise ValueError(record
)
2950 if "AA" not in mdwndb
[name
].operands
:
2951 raise ValueError(record
)
2955 if not name
.endswith("."):
2957 alias
= exact_match(name
[:-1])
2960 record
= records
[alias
]
2961 if record
.Rc
is _RCOE
.NONE
:
2962 raise ValueError(record
)
2966 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
2967 for (name
, _
) in mdwndb
:
2968 if name
.startswith("sv."):
2971 for match
in matches
:
2973 if alias
is not None:
2977 section
= sections
[alias
]
2978 record
= records
[alias
]
2979 db
[name
] = (section
, record
)
2981 self
.__db
= dict(sorted(db
.items()))
2983 return super().__init
__()
2985 @_functools.lru_cache(maxsize
=512, typed
=False)
2986 def __getitem__(self
, key
):
2987 return self
.__db
.get(key
, (None, None))
2990 class SVP64Database
:
2991 def __init__(self
, root
, ppcdb
):
2993 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
2994 for (prefix
, _
, names
) in _os
.walk(root
):
2995 prefix
= _pathlib
.Path(prefix
)
2996 for name
in filter(lambda name
: pattern
.match(name
), names
):
2997 path
= (prefix
/ _pathlib
.Path(name
))
2998 with
open(path
, "r", encoding
="UTF-8") as stream
:
2999 db
.update(parse(stream
, SVP64Record
.CSV
))
3000 db
= {record
.name
:record
for record
in db
}
3002 self
.__db
= dict(sorted(db
.items()))
3003 self
.__ppcdb
= ppcdb
3005 return super().__init
__()
3007 def __getitem__(self
, key
):
3008 (_
, record
) = self
.__ppcdb
[key
]
3012 for name
in record
.names
:
3013 record
= self
.__db
.get(name
, None)
3014 if record
is not None:
3021 def __init__(self
, root
):
3022 root
= _pathlib
.Path(root
)
3023 mdwndb
= MarkdownDatabase()
3024 fieldsdb
= FieldsDatabase()
3025 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
3026 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
3030 opcodes
= _collections
.defaultdict(
3031 lambda: _collections
.defaultdict(set))
3033 for (name
, mdwn
) in mdwndb
:
3034 if name
.startswith("sv."):
3036 (section
, ppc
) = ppcdb
[name
]
3039 svp64
= svp64db
[name
]
3040 fields
= fieldsdb
[ppc
.form
]
3041 record
= Record(name
=name
,
3042 section
=section
, ppc
=ppc
, svp64
=svp64
,
3043 mdwn
=mdwn
, fields
=fields
)
3045 names
[record
.name
] = record
3049 opcodes
[section
][PO
.value
].add(record
)
3051 self
.__db
= sorted(db
)
3052 self
.__names
= dict(sorted(names
.items()))
3053 self
.__opcodes
= dict(sorted(opcodes
.items()))
3055 return super().__init
__()
3058 return repr(self
.__db
)
3061 yield from self
.__db
3063 @_functools.lru_cache(maxsize
=None)
3064 def __contains__(self
, key
):
3065 return self
.__getitem
__(key
) is not None
3067 @_functools.lru_cache(maxsize
=None)
3068 def __getitem__(self
, key
):
3069 if isinstance(key
, Instruction
):
3072 for (section
, group
) in self
.__opcodes
.items():
3073 for record
in group
[PO
]:
3074 if record
.match(key
=key
):
3079 elif isinstance(key
, str):
3080 return self
.__names
.get(key
)
3082 raise ValueError("instruction or name expected")