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 SVP64SubVL
as _SVP64SubVL
,
42 SVP64Pred
as _SVP64Pred
,
43 SVP64PredMode
as _SVP64PredMode
,
44 SVP64Width
as _SVP64Width
,
46 from openpower
.decoder
.selectable_int
import (
47 SelectableInt
as _SelectableInt
,
48 selectconcat
as _selectconcat
,
50 from openpower
.decoder
.power_fields
import (
53 DecodeFields
as _DecodeFields
,
55 from openpower
.decoder
.pseudo
.pagereader
import ISA
as _ISA
58 @_functools.total_ordering
59 class Verbosity(_enum
.Enum
):
62 VERBOSE
= _enum
.auto()
64 def __lt__(self
, other
):
65 if not isinstance(other
, self
.__class
__):
67 return (self
.value
< other
.value
)
70 @_functools.total_ordering
71 class Priority(_enum
.Enum
):
77 def _missing_(cls
, value
):
78 if isinstance(value
, str):
83 return super()._missing
_(value
)
85 def __lt__(self
, other
):
86 if not isinstance(other
, self
.__class
__):
89 # NOTE: the order is inversed, LOW < NORMAL < HIGH
90 return (self
.value
> other
.value
)
93 def dataclass(cls
, record
, keymap
=None, typemap
=None):
97 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
99 def transform(key_value
):
100 (key
, value
) = key_value
101 key
= keymap
.get(key
, key
)
102 hook
= typemap
.get(key
, lambda value
: value
)
103 if hook
is bool and value
in ("", "0"):
109 record
= dict(map(transform
, record
.items()))
110 for key
in frozenset(record
.keys()):
111 if record
[key
] == "":
117 @_functools.total_ordering
118 @_dataclasses.dataclass(eq
=True, frozen
=True)
121 def __new__(cls
, value
):
122 if isinstance(value
, str):
123 value
= int(value
, 0)
124 if not isinstance(value
, int):
125 raise ValueError(value
)
127 if value
.bit_length() > 64:
128 raise ValueError(value
)
130 return super().__new
__(cls
, value
)
133 return self
.__repr
__()
136 return f
"{self:0{self.bit_length()}b}"
138 def bit_length(self
):
139 if super().bit_length() > 32:
143 class Value(Integer
):
152 def __lt__(self
, other
):
153 if not isinstance(other
, Opcode
):
154 return NotImplemented
155 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
158 def pattern(value
, mask
, bit_length
):
159 for bit
in range(bit_length
):
160 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
162 elif (value
& (1 << (bit_length
- bit
- 1))):
167 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
169 def match(self
, key
):
170 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
173 class IntegerOpcode(Opcode
):
174 def __init__(self
, value
):
175 if value
.startswith("0b"):
176 mask
= int(("1" * len(value
[2:])), 2)
180 value
= Opcode
.Value(value
)
181 mask
= Opcode
.Mask(mask
)
183 return super().__init
__(value
=value
, mask
=mask
)
186 class PatternOpcode(Opcode
):
187 def __init__(self
, pattern
):
188 if not isinstance(pattern
, str):
189 raise ValueError(pattern
)
191 (value
, mask
) = (0, 0)
192 for symbol
in pattern
:
193 if symbol
not in {"0", "1", "-"}:
194 raise ValueError(pattern
)
195 value |
= (symbol
== "1")
196 mask |
= (symbol
!= "-")
202 value
= Opcode
.Value(value
)
203 mask
= Opcode
.Mask(mask
)
205 return super().__init
__(value
=value
, mask
=mask
)
208 @_dataclasses.dataclass(eq
=True, frozen
=True)
210 class FlagsMeta(type):
225 class Flags(frozenset, metaclass
=FlagsMeta
):
226 def __new__(cls
, flags
=frozenset()):
227 flags
= frozenset(flags
)
228 diff
= (flags
- frozenset(cls
))
230 raise ValueError(flags
)
231 return super().__new
__(cls
, flags
)
235 flags
: Flags
= Flags()
237 function
: _Function
= _Function
.NONE
238 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
239 in1
: _In1Sel
= _In1Sel
.RA
240 in2
: _In2Sel
= _In2Sel
.NONE
241 in3
: _In3Sel
= _In3Sel
.NONE
242 out
: _OutSel
= _OutSel
.NONE
243 cr_in
: _CRInSel
= _CRInSel
.NONE
244 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
245 cr_out
: _CROutSel
= _CROutSel
.NONE
246 cry_in
: _CryIn
= _CryIn
.ZERO
247 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
248 upd
: _LDSTMode
= _LDSTMode
.NONE
249 Rc
: _RCOE
= _RCOE
.NONE
250 form
: _Form
= _Form
.NONE
252 unofficial
: bool = False
256 "internal op": "intop",
260 "ldst len": "ldst_len",
262 "CONDITIONS": "conditions",
265 def __lt__(self
, other
):
266 if not isinstance(other
, self
.__class
__):
267 return NotImplemented
268 lhs
= (self
.opcode
, self
.comment
)
269 rhs
= (other
.opcode
, other
.comment
)
273 def CSV(cls
, record
, opcode_cls
):
274 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
275 typemap
["opcode"] = opcode_cls
277 if record
["CR in"] == "BA_BB":
278 record
["cr_in"] = "BA"
279 record
["cr_in2"] = "BB"
283 for flag
in frozenset(PPCRecord
.Flags
):
284 if bool(record
.pop(flag
, "")):
286 record
["flags"] = PPCRecord
.Flags(flags
)
288 return dataclass(cls
, record
,
289 keymap
=PPCRecord
.__KEYMAP
,
294 return frozenset(self
.comment
.split("=")[-1].split("/"))
297 class PPCMultiRecord(tuple):
298 def __getattr__(self
, attr
):
300 raise AttributeError(attr
)
301 return getattr(self
[0], attr
)
304 @_dataclasses.dataclass(eq
=True, frozen
=True)
306 class ExtraMap(tuple):
308 @_dataclasses.dataclass(eq
=True, frozen
=True)
310 regtype
: _SVExtraRegType
= _SVExtraRegType
.NONE
311 reg
: _SVExtraReg
= _SVExtraReg
.NONE
314 return f
"{self.regtype.value}:{self.reg.name}"
316 def __new__(cls
, value
="0"):
317 if isinstance(value
, str):
318 def transform(value
):
319 (regtype
, reg
) = value
.split(":")
320 regtype
= _SVExtraRegType(regtype
)
321 reg
= _SVExtraReg(reg
)
322 return cls
.Entry(regtype
=regtype
, reg
=reg
)
327 value
= map(transform
, value
.split(";"))
329 return super().__new
__(cls
, value
)
332 return repr(list(self
))
334 def __new__(cls
, value
=tuple()):
338 return super().__new
__(cls
, map(cls
.Extra
, value
))
341 return repr({index
:self
[index
] for index
in range(0, 4)})
344 ptype
: _SVPType
= _SVPType
.NONE
345 etype
: _SVEType
= _SVEType
.NONE
346 msrc
: _SVMaskSrc
= _SVMaskSrc
.NO
# MASK_SRC is active
347 in1
: _In1Sel
= _In1Sel
.NONE
348 in2
: _In2Sel
= _In2Sel
.NONE
349 in3
: _In3Sel
= _In3Sel
.NONE
350 out
: _OutSel
= _OutSel
.NONE
351 out2
: _OutSel
= _OutSel
.NONE
352 cr_in
: _CRInSel
= _CRInSel
.NONE
353 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
354 cr_out
: _CROutSel
= _CROutSel
.NONE
355 extra
: ExtraMap
= ExtraMap()
357 mode
: _SVMode
= _SVMode
.NORMAL
361 "CONDITIONS": "conditions",
370 def CSV(cls
, record
):
371 for key
in frozenset({
372 "in1", "in2", "in3", "CR in",
373 "out", "out2", "CR out",
379 if record
["CR in"] == "BA_BB":
380 record
["cr_in"] = "BA"
381 record
["cr_in2"] = "BB"
385 for idx
in range(0, 4):
386 extra
.append(record
.pop(f
"{idx}"))
388 record
["extra"] = cls
.ExtraMap(extra
)
390 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
392 @_functools.lru_cache(maxsize
=None)
393 def extra_idx(self
, key
):
401 if key
not in frozenset({
402 "in1", "in2", "in3", "cr_in", "cr_in2",
403 "out", "out2", "cr_out",
407 sel
= getattr(self
, key
)
408 if sel
is _CRInSel
.BA_BB
:
409 return _SVExtra
.Idx_1_2
410 reg
= _SVExtraReg(sel
)
411 if reg
is _SVExtraReg
.NONE
:
415 _SVExtraRegType
.SRC
: {},
416 _SVExtraRegType
.DST
: {},
418 for index
in range(0, 4):
419 for entry
in self
.extra
[index
]:
420 extra_map
[entry
.regtype
][entry
.reg
] = extra_idx
[index
]
422 for regtype
in (_SVExtraRegType
.SRC
, _SVExtraRegType
.DST
):
423 extra
= extra_map
[regtype
].get(reg
, _SVExtra
.NONE
)
424 if extra
is not _SVExtra
.NONE
:
429 extra_idx_in1
= property(_functools
.partial(extra_idx
, key
="in1"))
430 extra_idx_in2
= property(_functools
.partial(extra_idx
, key
="in2"))
431 extra_idx_in3
= property(_functools
.partial(extra_idx
, key
="in3"))
432 extra_idx_out
= property(_functools
.partial(extra_idx
, key
="out"))
433 extra_idx_out2
= property(_functools
.partial(extra_idx
, key
="out2"))
434 extra_idx_cr_in
= property(_functools
.partial(extra_idx
, key
="cr_in"))
435 extra_idx_cr_in2
= property(_functools
.partial(extra_idx
, key
="cr_in2"))
436 extra_idx_cr_out
= property(_functools
.partial(extra_idx
, key
="cr_out"))
438 @_functools.lru_cache(maxsize
=None)
439 def extra_reg(self
, key
):
440 return _SVExtraReg(getattr(self
, key
))
442 extra_reg_in1
= property(_functools
.partial(extra_reg
, key
="in1"))
443 extra_reg_in2
= property(_functools
.partial(extra_reg
, key
="in2"))
444 extra_reg_in3
= property(_functools
.partial(extra_reg
, key
="in3"))
445 extra_reg_out
= property(_functools
.partial(extra_reg
, key
="out"))
446 extra_reg_out2
= property(_functools
.partial(extra_reg
, key
="out2"))
447 extra_reg_cr_in
= property(_functools
.partial(extra_reg
, key
="cr_in"))
448 extra_reg_cr_in2
= property(_functools
.partial(extra_reg
, key
="cr_in2"))
449 extra_reg_cr_out
= property(_functools
.partial(extra_reg
, key
="cr_out"))
454 for idx
in range(0, 4):
455 for entry
in self
.svp64
.extra
[idx
]:
456 if entry
.regtype
is _SVExtraRegType
.DST
:
457 if regtype
is not None:
458 raise ValueError(self
.svp64
)
459 regtype
= _RegType(entry
.reg
)
460 if regtype
not in (_RegType
.CR_5BIT
, _RegType
.CR_3BIT
):
461 raise ValueError(self
.svp64
)
462 return (regtype
is _RegType
.CR_3BIT
)
466 def __init__(self
, value
=(0, 32)):
467 if isinstance(value
, str):
468 (start
, end
) = map(int, value
.split(":"))
471 if start
< 0 or end
< 0 or start
>= end
:
472 raise ValueError(value
)
477 return super().__init
__()
480 return (self
.__end
- self
.__start
+ 1)
483 return f
"[{self.__start}:{self.__end}]"
486 yield from range(self
.start
, (self
.end
+ 1))
488 def __reversed__(self
):
489 return tuple(reversed(tuple(self
)))
500 @_dataclasses.dataclass(eq
=True, frozen
=True)
502 class Mode(_enum
.Enum
):
503 INTEGER
= _enum
.auto()
504 PATTERN
= _enum
.auto()
507 def _missing_(cls
, value
):
508 if isinstance(value
, str):
509 return cls
[value
.upper()]
510 return super()._missing
_(value
)
513 def __new__(cls
, value
=None):
514 if isinstance(value
, str):
515 if value
.upper() == "NONE":
518 value
= int(value
, 0)
522 return super().__new
__(cls
, value
)
528 return (bin(self
) if self
else "None")
534 opcode
: IntegerOpcode
= None
535 priority
: Priority
= Priority
.NORMAL
537 def __lt__(self
, other
):
538 if not isinstance(other
, self
.__class
__):
539 return NotImplemented
540 return (self
.priority
< other
.priority
)
543 def CSV(cls
, record
):
544 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
545 if record
["opcode"] == "NONE":
546 typemap
["opcode"] = lambda _
: None
548 return dataclass(cls
, record
, typemap
=typemap
)
552 def __init__(self
, items
):
553 if isinstance(items
, dict):
554 items
= items
.items()
557 (name
, bitrange
) = item
558 return (name
, tuple(bitrange
.values()))
560 self
.__mapping
= dict(map(transform
, items
))
562 return super().__init
__()
565 return repr(self
.__mapping
)
568 yield from self
.__mapping
.items()
570 def __contains__(self
, key
):
571 return self
.__mapping
.__contains
__(key
)
573 def __getitem__(self
, key
):
574 return self
.__mapping
.get(key
, None)
589 def __init__(self
, insn
, iterable
):
591 "b": {"target_addr": TargetAddrOperandLI
},
592 "ba": {"target_addr": TargetAddrOperandLI
},
593 "bl": {"target_addr": TargetAddrOperandLI
},
594 "bla": {"target_addr": TargetAddrOperandLI
},
595 "bc": {"target_addr": TargetAddrOperandBD
},
596 "bca": {"target_addr": TargetAddrOperandBD
},
597 "bcl": {"target_addr": TargetAddrOperandBD
},
598 "bcla": {"target_addr": TargetAddrOperandBD
},
599 "addpcis": {"D": DOperandDX
},
600 "fishmv": {"D": DOperandDX
},
601 "fmvis": {"D": DOperandDX
},
604 "SVi": NonZeroOperand
,
605 "SVd": NonZeroOperand
,
606 "SVxd": NonZeroOperand
,
607 "SVyd": NonZeroOperand
,
608 "SVzd": NonZeroOperand
,
610 "D": SignedImmediateOperand
,
614 "SIM": SignedOperand
,
615 "SVD": SignedOperand
,
616 "SVDS": SignedOperand
,
617 "RSp": GPRPairOperand
,
618 "RTp": GPRPairOperand
,
619 "FRAp": FPRPairOperand
,
620 "FRBp": FPRPairOperand
,
621 "FRSp": FPRPairOperand
,
622 "FRTp": FPRPairOperand
,
624 custom_immediates
= {
630 for operand
in iterable
:
634 (name
, value
) = operand
.split("=")
635 mapping
[name
] = (StaticOperand
, {
641 if name
.endswith(")"):
642 name
= name
.replace("(", " ").replace(")", "")
643 (imm_name
, _
, name
) = name
.partition(" ")
647 if imm_name
is not None:
648 imm_cls
= custom_immediates
.get(imm_name
, ImmediateOperand
)
650 if insn
in custom_insns
and name
in custom_insns
[insn
]:
651 cls
= custom_insns
[insn
][name
]
652 elif name
in custom_fields
:
653 cls
= custom_fields
[name
]
655 if name
in _SVExtraReg
.__members
__:
656 reg
= _SVExtraReg
[name
]
657 if reg
in self
.__class
__.__GPR
_PAIRS
:
659 elif reg
in self
.__class
__.__FPR
_PAIRS
:
662 regtype
= _RegType
[name
]
663 if regtype
is _RegType
.GPR
:
665 elif regtype
is _RegType
.FPR
:
667 elif regtype
is _RegType
.CR_5BIT
:
669 elif regtype
is _RegType
.CR_3BIT
:
672 if imm_name
is not None:
673 mapping
[imm_name
] = (imm_cls
, {"name": imm_name
})
674 mapping
[name
] = (cls
, {"name": name
})
678 for (name
, (cls
, kwargs
)) in mapping
.items():
679 kwargs
= dict(kwargs
)
680 kwargs
["name"] = name
681 if issubclass(cls
, StaticOperand
):
682 static
.append((cls
, kwargs
))
683 elif issubclass(cls
, DynamicOperand
):
684 dynamic
.append((cls
, kwargs
))
686 raise ValueError(name
)
688 self
.__mapping
= mapping
689 self
.__static
= tuple(static
)
690 self
.__dynamic
= tuple(dynamic
)
692 return super().__init
__()
695 for (_
, items
) in self
.__mapping
.items():
696 (cls
, kwargs
) = items
700 return self
.__mapping
.__repr
__()
702 def __contains__(self
, key
):
703 return self
.__mapping
.__contains
__(key
)
705 def __getitem__(self
, key
):
706 return self
.__mapping
.__getitem
__(key
)
714 return self
.__dynamic
717 class Arguments(tuple):
718 def __new__(cls
, arguments
, operands
):
719 iterable
= iter(tuple(arguments
))
720 operands
= iter(tuple(operands
))
725 operand
= next(operands
)
726 except StopIteration:
730 argument
= next(iterable
)
731 except StopIteration:
732 raise ValueError("operands count mismatch")
734 if isinstance(operand
, ImmediateOperand
):
735 argument
= argument
.replace("(", " ").replace(")", "")
736 (imm_argument
, _
, argument
) = argument
.partition(" ")
738 (imm_operand
, operand
) = (operand
, next(operands
))
739 except StopIteration:
740 raise ValueError("operands count mismatch")
741 arguments
.append((imm_argument
, imm_operand
))
742 arguments
.append((argument
, operand
))
746 except StopIteration:
749 raise ValueError("operands count mismatch")
751 return super().__new
__(cls
, arguments
)
755 def __init__(self
, iterable
):
756 self
.__pcode
= tuple(iterable
)
757 return super().__init
__()
760 yield from self
.__pcode
763 return self
.__pcode
.__repr
__()
766 @_dataclasses.dataclass(eq
=True, frozen
=True)
767 class MarkdownRecord
:
772 @_functools.total_ordering
773 @_dataclasses.dataclass(eq
=True, frozen
=True)
780 svp64
: SVP64Record
= None
782 def __lt__(self
, other
):
783 if not isinstance(other
, Record
):
784 return NotImplemented
785 lhs
= (min(self
.opcodes
), self
.name
)
786 rhs
= (min(other
.opcodes
), other
.name
)
791 PO
= self
.section
.opcode
793 assert len(self
.ppc
) == 1
794 PO
= self
.ppc
[0].opcode
796 return POStaticOperand(record
=self
,
797 name
="PO", value
=int(PO
.value
), mask
=int(PO
.mask
))
803 PO
= self
.section
.opcode
809 return XOStaticOperand(record
=self
,
810 name
="XO", value
=0, mask
=0)
812 return XOStaticOperand(record
=self
,
813 name
="XO", value
=int(XO
.value
), mask
=int(XO
.mask
))
815 return tuple(dict.fromkeys(map(XO
, self
.ppc
)))
818 def static_operands(self
):
821 operands
.append(self
.PO
)
822 operands
.extend(self
.XO
)
824 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
825 operands
.append(cls(record
=self
, **kwargs
))
827 return tuple(operands
)
830 def dynamic_operands(self
):
833 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
834 operands
.append(cls(record
=self
, **kwargs
))
836 return tuple(operands
)
841 if self
.svp64
is not None:
843 origin_value
= ([0] * bits
)
844 origin_mask
= ([0] * bits
)
846 for operand
in ((self
.PO
,) + tuple(self
.static_operands
)):
847 for (src
, dst
) in enumerate(reversed(operand
.span
)):
848 origin_value
[dst
] = int((operand
.value
& (1 << src
)) != 0)
852 value
= list(origin_value
)
853 mask
= list(origin_mask
)
854 for (src
, dst
) in enumerate(reversed(XO
.span
)):
855 value
[dst
] = int((XO
.value
& (1 << src
)) != 0)
858 value
= Opcode
.Value(int(("".join(map(str, value
))), 2))
859 mask
= Opcode
.Mask(int(("".join(map(str, mask
))), 2))
861 return Opcode(value
=value
, mask
=mask
)
863 return tuple(dict.fromkeys(map(opcode
, self
.XO
)))
865 def match(self
, key
):
866 for opcode
in self
.opcodes
:
867 if opcode
.match(key
):
874 return self
.svp64
.mode
894 if self
.svp64
is None:
900 return self
.ppc
.cr_in
904 return self
.ppc
.cr_in2
908 return self
.ppc
.cr_out
910 ptype
= property(lambda self
: self
.svp64
.ptype
)
911 etype
= property(lambda self
: self
.svp64
.etype
)
913 def extra_idx(self
, key
):
914 return self
.svp64
.extra_idx(key
)
916 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
917 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
918 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
919 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
920 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
921 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
922 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
923 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
925 def __contains__(self
, key
):
926 return self
.mdwn
.operands
.__contains
__(key
)
928 def __getitem__(self
, key
):
929 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
930 return cls(record
=self
, **kwargs
)
936 return self
["Rc"].value
939 @_dataclasses.dataclass(eq
=True, frozen
=True)
942 record
: Record
= _dataclasses
.field(repr=False)
944 def __post_init__(self
):
949 span
= self
.record
.fields
[self
.name
]
950 if self
.record
.svp64
is not None:
951 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
954 def assemble(self
, value
, insn
):
956 if isinstance(value
, str):
957 value
= int(value
, 0)
959 raise ValueError("signed operands not allowed")
962 def disassemble(self
, insn
,
963 verbosity
=Verbosity
.NORMAL
, indent
=""):
964 raise NotImplementedError
967 @_dataclasses.dataclass(eq
=True, frozen
=True)
968 class DynamicOperand(Operand
):
969 def disassemble(self
, insn
,
970 verbosity
=Verbosity
.NORMAL
, indent
=""):
974 if verbosity
>= Verbosity
.VERBOSE
:
975 span
= map(str, span
)
976 yield f
"{indent}{self.name}"
977 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
978 yield f
"{indent}{indent}{', '.join(span)}"
980 yield str(int(value
))
983 @_dataclasses.dataclass(eq
=True, frozen
=True)
984 class SignedOperand(DynamicOperand
):
985 def assemble(self
, value
, insn
):
986 if isinstance(value
, str):
987 value
= int(value
, 0)
988 return super().assemble(value
=value
, insn
=insn
)
990 def assemble(self
, value
, insn
):
992 if isinstance(value
, str):
993 value
= int(value
, 0)
996 def disassemble(self
, insn
,
997 verbosity
=Verbosity
.NORMAL
, indent
=""):
999 value
= insn
[span
].to_signed_int()
1000 sign
= "-" if (value
< 0) else ""
1003 if verbosity
>= Verbosity
.VERBOSE
:
1004 span
= map(str, span
)
1005 yield f
"{indent}{self.name}"
1006 yield f
"{indent}{indent}{sign}{value}"
1007 yield f
"{indent}{indent}{', '.join(span)}"
1009 yield f
"{sign}{value}"
1012 @_dataclasses.dataclass(eq
=True, frozen
=True)
1013 class StaticOperand(Operand
):
1016 def assemble(self
, insn
):
1017 return super().assemble(value
=self
.value
, insn
=insn
)
1019 def disassemble(self
, insn
,
1020 verbosity
=Verbosity
.NORMAL
, indent
=""):
1024 if verbosity
>= Verbosity
.VERBOSE
:
1025 span
= map(str, span
)
1026 yield f
"{indent}{self.name}"
1027 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1028 yield f
"{indent}{indent}{', '.join(span)}"
1030 yield str(int(value
))
1033 @_dataclasses.dataclass(eq
=True, frozen
=True)
1034 class POStaticOperand(StaticOperand
):
1039 span
= tuple(range(0, 6))
1040 if self
.record
.svp64
is not None:
1041 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
1045 @_dataclasses.dataclass(eq
=True, frozen
=True)
1046 class XOStaticOperand(StaticOperand
):
1049 def __post_init__(self
):
1050 if self
.record
.section
.opcode
is None:
1051 assert self
.value
== 0
1052 assert self
.mask
== 0
1053 object.__setattr
__(self
, "span", ())
1056 bits
= self
.record
.section
.bitsel
1057 value
= _SelectableInt(value
=self
.value
, bits
=len(bits
))
1058 span
= dict(zip(bits
, range(len(bits
))))
1059 span_rev
= {value
:key
for (key
, value
) in span
.items()}
1061 # This part is tricky: we could have used self.record.static_operands,
1062 # but this would cause an infinite recursion, since this code is called
1063 # from the self.record.static_operands method already.
1065 operands
.extend(self
.record
.mdwn
.operands
.static
)
1066 operands
.extend(self
.record
.mdwn
.operands
.dynamic
)
1067 for (cls
, kwargs
) in operands
:
1068 operand
= cls(record
=self
.record
, **kwargs
)
1069 for idx
in operand
.span
:
1070 rev
= span
.pop(idx
, None)
1072 span_rev
.pop(rev
, None)
1074 # This part is simpler: we drop bits which are not in the mask.
1075 for bit
in tuple(span
.values()):
1076 rev
= (len(bits
) - bit
- 1)
1077 if ((self
.mask
& (1 << bit
)) == 0):
1078 idx
= span_rev
.pop(rev
, None)
1082 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1083 span
= tuple(span
.keys())
1084 if self
.record
.svp64
is not None:
1085 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
1087 object.__setattr
__(self
, "value", value
)
1088 object.__setattr
__(self
, "span", span
)
1090 return super().__post
_init
__()
1093 @_dataclasses.dataclass(eq
=True, frozen
=True)
1094 class ImmediateOperand(DynamicOperand
):
1098 @_dataclasses.dataclass(eq
=True, frozen
=True)
1099 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1103 @_dataclasses.dataclass(eq
=True, frozen
=True)
1104 class NonZeroOperand(DynamicOperand
):
1105 def assemble(self
, value
, insn
):
1106 if isinstance(value
, str):
1107 value
= int(value
, 0)
1108 if not isinstance(value
, int):
1109 raise ValueError("non-integer operand")
1111 return super().assemble(value
=value
, insn
=insn
)
1113 def disassemble(self
, insn
,
1114 verbosity
=Verbosity
.NORMAL
, indent
=""):
1118 if verbosity
>= Verbosity
.VERBOSE
:
1119 span
= map(str, span
)
1120 yield f
"{indent}{self.name}"
1121 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1122 yield f
"{indent}{indent}{', '.join(span)}"
1124 yield str(int(value
) + 1)
1127 @_dataclasses.dataclass(eq
=True, frozen
=True)
1128 class ExtendableOperand(DynamicOperand
):
1129 def sv_spec_enter(self
, value
, span
):
1130 return (value
, span
)
1132 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1133 return (value
, span
)
1135 def spec(self
, insn
):
1139 span
= tuple(map(str, span
))
1141 if isinstance(insn
, SVP64Instruction
):
1142 (origin_value
, origin_span
) = (value
, span
)
1143 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1145 extra_idx
= self
.extra_idx
1146 if extra_idx
is _SVExtra
.NONE
:
1147 return (vector
, value
, span
)
1149 if self
.record
.etype
is _SVEType
.EXTRA3
:
1150 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1151 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1152 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1154 raise ValueError(self
.record
.etype
)
1157 vector
= bool(spec
[0])
1158 spec_span
= spec
.__class
__
1159 if self
.record
.etype
is _SVEType
.EXTRA3
:
1160 spec_span
= tuple(map(str, spec_span
[1, 2]))
1162 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1163 spec_span
= tuple(map(str, spec_span
[1,]))
1164 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1167 spec_span
= (spec_span
+ ("{0}",))
1169 spec_span
= (("{0}",) + spec_span
)
1171 raise ValueError(self
.record
.etype
)
1173 vector_shift
= (2 + (5 - value
.bits
))
1174 scalar_shift
= value
.bits
1175 spec_shift
= (5 - value
.bits
)
1177 bits
= (len(span
) + len(spec_span
))
1178 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1179 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1181 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1182 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1184 value
= ((spec
<< scalar_shift
) | value
)
1185 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1187 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1188 origin_value
=origin_value
, origin_span
=origin_span
)
1190 return (vector
, value
, span
)
1193 def extra_reg(self
):
1194 return _SVExtraReg(self
.name
)
1197 def extra_idx(self
):
1199 _SVExtraReg
.RSp
: _SVExtraReg
.RS
,
1200 _SVExtraReg
.RTp
: _SVExtraReg
.RT
,
1201 _SVExtraReg
.FRAp
: _SVExtraReg
.FRA
,
1202 _SVExtraReg
.FRBp
: _SVExtraReg
.FRB
,
1203 _SVExtraReg
.FRSp
: _SVExtraReg
.FRS
,
1204 _SVExtraReg
.FRTp
: _SVExtraReg
.FRT
,
1207 for key
in frozenset({
1208 "in1", "in2", "in3", "cr_in", "cr_in2",
1209 "out", "out2", "cr_out",
1211 extra_reg
= self
.record
.svp64
.extra_reg(key
=key
)
1212 if pairs
.get(extra_reg
, extra_reg
) is pairs
.get(self
.extra_reg
, self
.extra_reg
):
1213 return self
.record
.extra_idx(key
=key
)
1215 return _SVExtra
.NONE
1217 def remap(self
, value
, vector
):
1218 raise NotImplementedError
1220 def assemble(self
, value
, insn
, prefix
):
1223 if isinstance(value
, str):
1224 value
= value
.lower()
1225 if value
.startswith("%"):
1227 if value
.startswith("*"):
1228 if not isinstance(insn
, SVP64Instruction
):
1229 raise ValueError(value
)
1232 if value
.startswith(prefix
):
1233 value
= value
[len(prefix
):]
1234 value
= int(value
, 0)
1236 if isinstance(insn
, SVP64Instruction
):
1237 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1239 extra_idx
= self
.extra_idx
1240 if extra_idx
is _SVExtra
.NONE
:
1241 raise ValueError(self
.record
)
1243 if self
.record
.etype
is _SVEType
.EXTRA3
:
1244 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1245 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1246 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1248 raise ValueError(self
.record
.etype
)
1250 return super().assemble(value
=value
, insn
=insn
)
1252 return super().assemble(value
=value
, insn
=insn
)
1254 def disassemble(self
, insn
,
1255 verbosity
=Verbosity
.NORMAL
, prefix
="", indent
=""):
1256 (vector
, value
, span
) = self
.spec(insn
=insn
)
1258 if verbosity
>= Verbosity
.VERBOSE
:
1259 mode
= "vector" if vector
else "scalar"
1260 yield f
"{indent}{self.name} ({mode})"
1261 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1262 yield f
"{indent}{indent}{', '.join(span)}"
1263 if isinstance(insn
, SVP64Instruction
):
1264 extra_idx
= self
.extra_idx
1265 if self
.record
.etype
is _SVEType
.NONE
:
1266 yield f
"{indent}{indent}extra[none]"
1268 etype
= repr(self
.record
.etype
).lower()
1269 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1271 vector
= "*" if vector
else ""
1272 yield f
"{vector}{prefix}{int(value)}"
1275 @_dataclasses.dataclass(eq
=True, frozen
=True)
1276 class SimpleRegisterOperand(ExtendableOperand
):
1277 def remap(self
, value
, vector
):
1279 extra
= (value
& 0b11)
1280 value
= (value
>> 2)
1282 extra
= (value
>> 5)
1283 value
= (value
& 0b11111)
1285 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1286 # (and shrink to a single bit if ok)
1287 if self
.record
.etype
is _SVEType
.EXTRA2
:
1289 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1290 assert (extra
& 0b01) == 0, \
1291 ("vector field %s cannot fit into EXTRA2" % value
)
1292 extra
= (0b10 |
(extra
>> 1))
1294 # range is r0-r63 in increments of 1
1295 assert (extra
>> 1) == 0, \
1296 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1298 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1300 # EXTRA3 vector bit needs marking
1303 raise ValueError(self
.record
.etype
)
1305 return (value
, extra
)
1308 @_dataclasses.dataclass(eq
=True, frozen
=True)
1309 class GPROperand(SimpleRegisterOperand
):
1310 def assemble(self
, value
, insn
):
1311 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1313 def disassemble(self
, insn
,
1314 verbosity
=Verbosity
.NORMAL
, indent
=""):
1315 prefix
= "" if (verbosity
<= Verbosity
.SHORT
) else "r"
1316 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1317 verbosity
=verbosity
, indent
=indent
)
1320 @_dataclasses.dataclass(eq
=True, frozen
=True)
1321 class GPRPairOperand(GPROperand
):
1325 @_dataclasses.dataclass(eq
=True, frozen
=True)
1326 class FPROperand(SimpleRegisterOperand
):
1327 def assemble(self
, value
, insn
):
1328 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1330 def disassemble(self
, insn
,
1331 verbosity
=Verbosity
.NORMAL
, indent
=""):
1332 prefix
= "" if (verbosity
<= Verbosity
.SHORT
) else "f"
1333 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1334 verbosity
=verbosity
, indent
=indent
)
1337 @_dataclasses.dataclass(eq
=True, frozen
=True)
1338 class FPRPairOperand(FPROperand
):
1342 @_dataclasses.dataclass(eq
=True, frozen
=True)
1343 class ConditionRegisterFieldOperand(ExtendableOperand
):
1344 def pattern(name_pattern
):
1345 (name
, pattern
) = name_pattern
1346 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1355 CR
= r
"(?:CR|cr)([0-9]+)"
1357 BIT
= rf
"({'|'.join(CONDS.keys())})"
1358 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1359 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1360 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1361 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1362 XCR
= fr
"{CR}\.{BIT}"
1363 PATTERNS
= tuple(map(pattern
, (
1368 ("BIT+CR", (LBIT
+ CR
)),
1369 ("CR+BIT", (CR
+ RBIT
)),
1370 ("BIT+CR*N", (LBIT
+ CRN
)),
1371 ("CR*N+BIT", (CRN
+ RBIT
)),
1372 ("BIT+N*CR", (LBIT
+ NCR
)),
1373 ("N*CR+BIT", (NCR
+ RBIT
)),
1376 def remap(self
, value
, vector
, regtype
):
1377 if regtype
is _RegType
.CR_5BIT
:
1378 subvalue
= (value
& 0x3)
1382 extra
= (value
& 0xf)
1385 extra
= (value
>> 3)
1388 if self
.record
.etype
is _SVEType
.EXTRA2
:
1390 assert (extra
& 0x7) == 0, \
1391 "vector CR cannot fit into EXTRA2"
1392 extra
= (0x2 |
(extra
>> 3))
1394 assert (extra
>> 1) == 0, \
1395 "scalar CR cannot fit into EXTRA2"
1397 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1399 assert (extra
& 0x3) == 0, \
1400 "vector CR cannot fit into EXTRA3"
1401 extra
= (0x4 |
(extra
>> 2))
1403 assert (extra
>> 2) == 0, \
1404 "scalar CR cannot fit into EXTRA3"
1407 if regtype
is _RegType
.CR_5BIT
:
1408 value
= ((value
<< 2) | subvalue
)
1410 return (value
, extra
)
1412 def assemble(self
, value
, insn
):
1413 if isinstance(value
, str):
1416 if value
.startswith("*"):
1417 if not isinstance(insn
, SVP64Instruction
):
1418 raise ValueError(value
)
1422 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1423 match
= pattern
.match(value
)
1424 if match
is not None:
1425 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1426 values
= match
.groups()
1427 match
= dict(zip(keys
, values
))
1428 CR
= int(match
["CR"])
1432 N
= int(match
.get("N", "1"))
1433 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1434 value
= ((CR
* N
) + BIT
)
1437 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1439 def disassemble(self
, insn
,
1440 verbosity
=Verbosity
.NORMAL
, prefix
="", indent
=""):
1441 (vector
, value
, span
) = self
.spec(insn
=insn
)
1443 if verbosity
>= Verbosity
.VERBOSE
:
1444 mode
= "vector" if vector
else "scalar"
1445 yield f
"{indent}{self.name} ({mode})"
1446 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1447 yield f
"{indent}{indent}{', '.join(span)}"
1448 if isinstance(insn
, SVP64Instruction
):
1449 extra_idx
= self
.extra_idx
1450 if self
.record
.etype
is _SVEType
.NONE
:
1451 yield f
"{indent}{indent}extra[none]"
1453 etype
= repr(self
.record
.etype
).lower()
1454 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1456 vector
= "*" if vector
else ""
1457 cr
= int(value
>> 2)
1459 cond
= ("lt", "gt", "eq", "so")[cc
]
1460 if verbosity
>= Verbosity
.NORMAL
:
1462 if isinstance(insn
, SVP64Instruction
):
1463 yield f
"{vector}cr{cr}.{cond}"
1465 yield f
"4*cr{cr}+{cond}"
1469 yield f
"{vector}{prefix}{int(value)}"
1472 @_dataclasses.dataclass(eq
=True, frozen
=True)
1473 class CR3Operand(ConditionRegisterFieldOperand
):
1474 def remap(self
, value
, vector
):
1475 return super().remap(value
=value
, vector
=vector
,
1476 regtype
=_RegType
.CR_3BIT
)
1479 @_dataclasses.dataclass(eq
=True, frozen
=True)
1480 class CR5Operand(ConditionRegisterFieldOperand
):
1481 def remap(self
, value
, vector
):
1482 return super().remap(value
=value
, vector
=vector
,
1483 regtype
=_RegType
.CR_5BIT
)
1485 def sv_spec_enter(self
, value
, span
):
1486 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1487 return (value
, span
)
1489 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1490 value
= _selectconcat(value
, origin_value
[3:5])
1492 return (value
, span
)
1495 @_dataclasses.dataclass(eq
=True, frozen
=True)
1496 class EXTSOperand(SignedOperand
):
1497 field
: str # real name to report
1498 nz
: int = 0 # number of zeros
1499 fmt
: str = "d" # integer formatter
1501 def __post_init__(self
):
1503 object.__setattr
__(self
, "field", self
.name
)
1507 span
= self
.record
.fields
[self
.field
]
1508 if self
.record
.svp64
is not None:
1509 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
1512 def assemble(self
, value
, insn
):
1514 if isinstance(value
, str):
1515 value
= int(value
, 0)
1516 insn
[span
] = (value
>> self
.nz
)
1518 def disassemble(self
, insn
,
1519 verbosity
=Verbosity
.NORMAL
, indent
=""):
1521 value
= insn
[span
].to_signed_int()
1522 sign
= "-" if (value
< 0) else ""
1523 value
= (abs(value
) << self
.nz
)
1525 if verbosity
>= Verbosity
.VERBOSE
:
1526 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1527 zeros
= ("0" * self
.nz
)
1528 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1529 yield f
"{indent * 1}{hint}"
1530 yield f
"{indent * 2}{self.field}"
1531 yield f
"{indent * 3}{sign}{value:{self.fmt}}"
1532 yield f
"{indent * 3}{', '.join(span)}"
1534 yield f
"{sign}{value:{self.fmt}}"
1537 @_dataclasses.dataclass(eq
=True, frozen
=True)
1538 class TargetAddrOperand(EXTSOperand
):
1543 @_dataclasses.dataclass(eq
=True, frozen
=True)
1544 class TargetAddrOperandLI(TargetAddrOperand
):
1548 @_dataclasses.dataclass(eq
=True, frozen
=True)
1549 class TargetAddrOperandBD(TargetAddrOperand
):
1553 @_dataclasses.dataclass(eq
=True, frozen
=True)
1554 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1559 @_dataclasses.dataclass(eq
=True, frozen
=True)
1560 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1565 @_dataclasses.dataclass(eq
=True, frozen
=True)
1566 class DOperandDX(SignedOperand
):
1569 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1570 operands
= map(cls
, ("d0", "d1", "d2"))
1571 spans
= map(lambda operand
: operand
.span
, operands
)
1572 span
= sum(spans
, tuple())
1573 if self
.record
.svp64
is not None:
1574 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
1577 def disassemble(self
, insn
,
1578 verbosity
=Verbosity
.NORMAL
, indent
=""):
1580 value
= insn
[span
].to_signed_int()
1581 sign
= "-" if (value
< 0) else ""
1584 if verbosity
>= Verbosity
.VERBOSE
:
1591 for (subname
, subspan
) in mapping
.items():
1592 operand
= DynamicOperand(name
=subname
)
1594 span
= map(str, span
)
1595 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1596 yield f
"{indent}{indent}{indent}{sign}{value}"
1597 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1599 yield f
"{sign}{value}"
1602 class Instruction(_Mapping
):
1604 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1605 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1606 raise ValueError(bits
)
1608 if isinstance(value
, bytes
):
1609 if ((len(value
) * 8) != bits
):
1610 raise ValueError(f
"bit length mismatch")
1611 value
= int.from_bytes(value
, byteorder
=byteorder
)
1613 if isinstance(value
, int):
1614 value
= _SelectableInt(value
=value
, bits
=bits
)
1615 elif isinstance(value
, Instruction
):
1616 value
= value
.storage
1618 if not isinstance(value
, _SelectableInt
):
1619 raise ValueError(value
)
1622 if len(value
) != bits
:
1623 raise ValueError(value
)
1625 value
= _SelectableInt(value
=value
, bits
=bits
)
1627 return cls(storage
=value
)
1630 return hash(int(self
))
1632 def __getitem__(self
, key
):
1633 return self
.storage
.__getitem
__(key
)
1635 def __setitem__(self
, key
, value
):
1636 return self
.storage
.__setitem
__(key
, value
)
1638 def bytes(self
, byteorder
="little"):
1639 nr_bytes
= (len(self
.__class
__) // 8)
1640 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1643 def record(cls
, db
, entry
):
1646 raise KeyError(entry
)
1649 def spec(self
, db
, prefix
):
1650 record
= self
.record(db
=db
, entry
=self
)
1652 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1653 self
.dynamic_operands(db
=db
)))
1655 static_operands
= []
1656 for (name
, value
) in self
.static_operands(db
=db
):
1657 static_operands
.append(f
"{name}={value}")
1660 if dynamic_operands
:
1662 operands
+= ",".join(dynamic_operands
)
1665 operands
+= " ".join(static_operands
)
1667 return f
"{prefix}{record.name}{operands}"
1669 def dynamic_operands(self
, db
, verbosity
=Verbosity
.NORMAL
):
1670 record
= self
.record(db
=db
, entry
=self
)
1675 for operand
in record
.dynamic_operands
:
1677 value
= " ".join(operand
.disassemble(insn
=self
,
1678 verbosity
=min(verbosity
, Verbosity
.NORMAL
)))
1680 name
= f
"{imm_name}({name})"
1681 value
= f
"{imm_value}({value})"
1683 if isinstance(operand
, ImmediateOperand
):
1690 def static_operands(self
, db
):
1691 record
= self
.record(db
=db
, entry
=self
)
1692 for operand
in record
.static_operands
:
1693 yield (operand
.name
, operand
.value
)
1696 def assemble(cls
, db
, opcode
, arguments
=None):
1697 raise NotImplementedError(f
"{cls.__name__}.assemble")
1699 def disassemble(self
, db
,
1701 verbosity
=Verbosity
.NORMAL
):
1702 raise NotImplementedError
1705 class WordInstruction(Instruction
):
1706 _
: _Field
= range(0, 32)
1707 PO
: _Field
= range(0, 6)
1710 def record(cls
, db
, entry
):
1711 record
= super().record(db
=db
, entry
=entry
)
1712 return _dataclasses
.replace(record
, svp64
=None)
1715 def integer(cls
, value
, byteorder
="little"):
1716 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1721 for idx
in range(32):
1722 bit
= int(self
[idx
])
1724 return "".join(map(str, bits
))
1727 def assemble(cls
, db
, opcode
, arguments
=None):
1728 if arguments
is None:
1731 record
= cls
.record(db
=db
, entry
=opcode
)
1732 insn
= cls
.integer(value
=0)
1733 for operand
in record
.static_operands
:
1734 operand
.assemble(insn
=insn
)
1736 dynamic_operands
= tuple(record
.dynamic_operands
)
1737 for (value
, operand
) in Arguments(arguments
, dynamic_operands
):
1738 operand
.assemble(value
=value
, insn
=insn
)
1742 def disassemble(self
, db
,
1744 verbosity
=Verbosity
.NORMAL
):
1745 if verbosity
<= Verbosity
.SHORT
:
1748 blob
= self
.bytes(byteorder
=byteorder
)
1749 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1752 record
= self
.record(db
=db
, entry
=self
)
1754 yield f
"{blob}.long 0x{int(self):08x}"
1757 operands
= tuple(map(_operator
.itemgetter(1),
1758 self
.dynamic_operands(db
=db
, verbosity
=verbosity
)))
1760 operands
= ",".join(operands
)
1761 yield f
"{blob}{record.name} {operands}"
1763 yield f
"{blob}{record.name}"
1765 if verbosity
>= Verbosity
.VERBOSE
:
1767 binary
= self
.binary
1768 spec
= self
.spec(db
=db
, prefix
="")
1769 yield f
"{indent}spec"
1770 yield f
"{indent}{indent}{spec}"
1771 yield f
"{indent}pcode"
1772 for stmt
in record
.mdwn
.pcode
:
1773 yield f
"{indent}{indent}{stmt}"
1774 yield f
"{indent}binary"
1775 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1776 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1777 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1778 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1779 yield f
"{indent}opcodes"
1780 for opcode
in record
.opcodes
:
1781 yield f
"{indent}{indent}{opcode!r}"
1782 for (cls
, kwargs
) in record
.mdwn
.operands
:
1783 operand
= cls(record
=record
, **kwargs
)
1784 yield from operand
.disassemble(insn
=self
,
1785 verbosity
=verbosity
, indent
=indent
)
1789 class PrefixedInstruction(Instruction
):
1790 class Prefix(WordInstruction
.remap(range(0, 32))):
1793 class Suffix(WordInstruction
.remap(range(32, 64))):
1796 _
: _Field
= range(64)
1802 def integer(cls
, value
, byteorder
="little"):
1803 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
1806 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
1807 def transform(value
):
1808 return WordInstruction
.integer(value
=value
,
1809 byteorder
=byteorder
)[0:32]
1811 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
1812 value
= _selectconcat(prefix
, suffix
)
1814 return super().integer(bits
=64, value
=value
)
1817 class Mode(_Mapping
):
1818 _
: _Field
= range(0, 5)
1819 sel
: _Field
= (0, 1)
1822 class Extra(_Mapping
):
1823 _
: _Field
= range(0, 9)
1826 class Extra2(Extra
):
1827 idx0
: _Field
= range(0, 2)
1828 idx1
: _Field
= range(2, 4)
1829 idx2
: _Field
= range(4, 6)
1830 idx3
: _Field
= range(6, 8)
1832 def __getitem__(self
, key
):
1838 _SVExtra
.Idx0
: self
.idx0
,
1839 _SVExtra
.Idx1
: self
.idx1
,
1840 _SVExtra
.Idx2
: self
.idx2
,
1841 _SVExtra
.Idx3
: self
.idx3
,
1844 def __setitem__(self
, key
, value
):
1845 self
[key
].assign(value
)
1848 class Extra3(Extra
):
1849 idx0
: _Field
= range(0, 3)
1850 idx1
: _Field
= range(3, 6)
1851 idx2
: _Field
= range(6, 9)
1853 def __getitem__(self
, key
):
1858 _SVExtra
.Idx0
: self
.idx0
,
1859 _SVExtra
.Idx1
: self
.idx1
,
1860 _SVExtra
.Idx2
: self
.idx2
,
1863 def __setitem__(self
, key
, value
):
1864 self
[key
].assign(value
)
1867 class BaseRM(_Mapping
):
1868 _
: _Field
= range(24)
1869 mmode
: _Field
= (0,)
1870 mask
: _Field
= range(1, 4)
1871 elwidth
: _Field
= range(4, 6)
1872 ewsrc
: _Field
= range(6, 8)
1873 subvl
: _Field
= range(8, 10)
1874 mode
: Mode
.remap(range(19, 24))
1875 smask
: _Field
= range(16, 19)
1876 extra
: Extra
.remap(range(10, 19))
1877 extra2
: Extra2
.remap(range(10, 19))
1878 extra3
: Extra3
.remap(range(10, 19))
1880 def specifiers(self
, record
):
1881 subvl
= int(self
.subvl
)
1889 def disassemble(self
, verbosity
=Verbosity
.NORMAL
):
1890 if verbosity
>= Verbosity
.VERBOSE
:
1892 for (name
, span
) in self
.traverse(path
="RM"):
1893 value
= self
.storage
[span
]
1895 yield f
"{indent}{int(value):0{value.bits}b}"
1896 yield f
"{indent}{', '.join(map(str, span))}"
1899 class FFPRRc1BaseRM(BaseRM
):
1900 def specifiers(self
, record
, mode
):
1901 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
1902 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
1903 mask
= int(_selectconcat(CR
, inv
))
1904 predicate
= PredicateBaseRM
.predicate(True, mask
)
1905 yield f
"{mode}={predicate}"
1907 yield from super().specifiers(record
=record
)
1910 class FFPRRc0BaseRM(BaseRM
):
1911 def specifiers(self
, record
, mode
):
1913 inv
= "~" if self
.inv
else ""
1914 yield f
"{mode}={inv}RC1"
1916 yield from super().specifiers(record
=record
)
1919 class SatBaseRM(BaseRM
):
1920 def specifiers(self
, record
):
1926 yield from super().specifiers(record
=record
)
1929 class ZZBaseRM(BaseRM
):
1930 def specifiers(self
, record
):
1934 yield from super().specifiers(record
=record
)
1937 class ZZCombinedBaseRM(BaseRM
):
1938 def specifiers(self
, record
):
1939 if self
.sz
and self
.dz
:
1946 yield from super().specifiers(record
=record
)
1949 class DZBaseRM(BaseRM
):
1950 def specifiers(self
, record
):
1954 yield from super().specifiers(record
=record
)
1957 class SZBaseRM(BaseRM
):
1958 def specifiers(self
, record
):
1962 yield from super().specifiers(record
=record
)
1965 class MRBaseRM(BaseRM
):
1966 def specifiers(self
, record
):
1972 yield from super().specifiers(record
=record
)
1975 class ElsBaseRM(BaseRM
):
1976 def specifiers(self
, record
):
1980 yield from super().specifiers(record
=record
)
1983 class WidthBaseRM(BaseRM
):
1985 def width(FP
, width
):
1994 width
= ("fp" + width
)
1997 def specifiers(self
, record
):
1998 # elwidths: use "w=" if same otherwise dw/sw
1999 # FIXME this should consider FP instructions
2001 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
2002 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2011 yield from super().specifiers(record
=record
)
2014 class PredicateBaseRM(BaseRM
):
2016 def predicate(CR
, mask
):
2019 (False, 0b001): "1<<r3",
2020 (False, 0b010): "r3",
2021 (False, 0b011): "~r3",
2022 (False, 0b100): "r10",
2023 (False, 0b101): "~r10",
2024 (False, 0b110): "r30",
2025 (False, 0b111): "~r30",
2027 (True, 0b000): "lt",
2028 (True, 0b001): "ge",
2029 (True, 0b010): "gt",
2030 (True, 0b011): "le",
2031 (True, 0b100): "eq",
2032 (True, 0b101): "ne",
2033 (True, 0b110): "so",
2034 (True, 0b111): "ns",
2037 def specifiers(self
, record
):
2038 # predication - single and twin
2039 # use "m=" if same otherwise sm/dm
2040 CR
= (int(self
.mmode
) == 1)
2041 mask
= int(self
.mask
)
2042 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
2043 if record
.svp64
.ptype
is _SVPType
.P2
:
2044 smask
= int(self
.smask
)
2045 sm
= PredicateBaseRM
.predicate(CR
, smask
)
2054 yield from super().specifiers(record
=record
)
2057 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
2061 class SEABaseRM(BaseRM
):
2062 def specifiers(self
, record
):
2066 yield from super().specifiers(record
=record
)
2069 class VLiBaseRM(BaseRM
):
2070 def specifiers(self
, record
):
2074 yield from super().specifiers(record
=record
)
2077 class NormalBaseRM(PredicateWidthBaseRM
):
2080 https://libre-soc.org/openpower/sv/normal/
2085 class NormalSimpleRM(ZZCombinedBaseRM
, NormalBaseRM
):
2086 """normal: simple mode"""
2090 def specifiers(self
, record
):
2091 yield from super().specifiers(record
=record
)
2094 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
2095 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
2099 class NormalFFRc1RM(FFPRRc1BaseRM
, NormalBaseRM
):
2100 """normal: Rc=1: ffirst CR sel"""
2102 CR
: BaseRM
.mode
[3, 4]
2104 def specifiers(self
, record
):
2105 yield from super().specifiers(record
=record
, mode
="ff")
2108 class NormalFFRc0RM(FFPRRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
2109 """normal: Rc=0: ffirst z/nonz"""
2114 def specifiers(self
, record
):
2115 yield from super().specifiers(record
=record
, mode
="ff")
2118 class NormalSatRM(SatBaseRM
, ZZCombinedBaseRM
, NormalBaseRM
):
2119 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2125 class NormalPRRc1RM(FFPRRc1BaseRM
, NormalBaseRM
):
2126 """normal: Rc=1: pred-result CR sel"""
2128 CR
: BaseRM
.mode
[3, 4]
2130 def specifiers(self
, record
):
2131 yield from super().specifiers(record
=record
, mode
="pr")
2134 class NormalPRRc0RM(FFPRRc0BaseRM
, ZZBaseRM
, NormalBaseRM
):
2135 """normal: Rc=0: pred-result z/nonz"""
2142 def specifiers(self
, record
):
2143 yield from super().specifiers(record
=record
, mode
="pr")
2146 class NormalRM(NormalBaseRM
):
2147 simple
: NormalSimpleRM
2149 ffrc1
: NormalFFRc1RM
2150 ffrc0
: NormalFFRc0RM
2152 prrc1
: NormalPRRc1RM
2153 prrc0
: NormalPRRc0RM
2156 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2158 LD/ST Immediate mode
2159 https://libre-soc.org/openpower/sv/ldst/
2164 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2165 """ld/st immediate: simple mode"""
2172 class LDSTImmPostRM(LDSTImmBaseRM
):
2173 """ld/st immediate: postinc mode (and load-fault)"""
2174 pi
: BaseRM
.mode
[3] # Post-Increment Mode
2175 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2177 def specifiers(self
, record
):
2184 class LDSTImmFFRc1RM(FFPRRc1BaseRM
, LDSTImmBaseRM
):
2185 """ld/st immediate: Rc=1: ffirst CR sel"""
2187 CR
: BaseRM
.mode
[3, 4]
2189 def specifiers(self
, record
):
2190 yield from super().specifiers(record
=record
, mode
="ff")
2193 class LDSTImmFFRc0RM(FFPRRc0BaseRM
, ElsBaseRM
, LDSTImmBaseRM
):
2194 """ld/st immediate: Rc=0: ffirst z/nonz"""
2199 def specifiers(self
, record
):
2200 yield from super().specifiers(record
=record
, mode
="ff")
2203 class LDSTImmSatRM(ElsBaseRM
, SatBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2204 """ld/st immediate: sat mode: N=0/1 u/s"""
2212 class LDSTImmPRRc1RM(FFPRRc1BaseRM
, LDSTImmBaseRM
):
2213 """ld/st immediate: Rc=1: pred-result CR sel"""
2215 CR
: BaseRM
.mode
[3, 4]
2217 def specifiers(self
, record
):
2218 yield from super().specifiers(record
=record
, mode
="pr")
2221 class LDSTImmPRRc0RM(FFPRRc0BaseRM
, ElsBaseRM
, LDSTImmBaseRM
):
2222 """ld/st immediate: Rc=0: pred-result z/nonz"""
2227 def specifiers(self
, record
):
2228 yield from super().specifiers(record
=record
, mode
="pr")
2231 class LDSTImmRM(LDSTImmBaseRM
):
2232 simple
: LDSTImmSimpleRM
2234 ffrc1
: LDSTImmFFRc1RM
2235 ffrc0
: LDSTImmFFRc0RM
2237 prrc1
: LDSTImmPRRc1RM
2238 prrc0
: LDSTImmPRRc0RM
2241 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2244 https://libre-soc.org/openpower/sv/ldst/
2249 class LDSTIdxSimpleRM(SEABaseRM
, ZZCombinedBaseRM
, LDSTIdxBaseRM
):
2250 """ld/st index: simple mode"""
2256 class LDSTIdxStrideRM(SEABaseRM
, ZZCombinedBaseRM
, LDSTIdxBaseRM
):
2257 """ld/st index: strided (scalar only source)"""
2262 def specifiers(self
, record
):
2265 yield from super().specifiers(record
=record
)
2268 class LDSTIdxSatRM(SatBaseRM
, ZZCombinedBaseRM
, LDSTIdxBaseRM
):
2269 """ld/st index: sat mode: N=0/1 u/s"""
2275 class LDSTIdxPRRc1RM(LDSTIdxBaseRM
):
2276 """ld/st index: Rc=1: pred-result CR sel"""
2278 CR
: BaseRM
.mode
[3, 4]
2280 def specifiers(self
, record
):
2281 yield from super().specifiers(record
=record
, mode
="pr")
2284 class LDSTIdxPRRc0RM(FFPRRc0BaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2285 """ld/st index: Rc=0: pred-result z/nonz"""
2292 def specifiers(self
, record
):
2293 yield from super().specifiers(record
=record
, mode
="pr")
2296 class LDSTIdxRM(LDSTIdxBaseRM
):
2297 simple
: LDSTIdxSimpleRM
2298 stride
: LDSTIdxStrideRM
2300 prrc1
: LDSTIdxPRRc1RM
2301 prrc0
: LDSTIdxPRRc0RM
2305 class CROpBaseRM(BaseRM
):
2308 https://libre-soc.org/openpower/sv/cr_ops/
2313 class CROpSimpleRM(PredicateBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2314 """cr_op: simple mode"""
2319 def specifiers(self
, record
):
2321 yield "rg" # simple CR Mode reports /rg
2323 yield from super().specifiers(record
=record
)
2325 class CROpMRRM(MRBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2326 """cr_op: scalar reduce mode (mapreduce), SUBVL=1"""
2332 class CROpFF3RM(FFPRRc1BaseRM
, VLiBaseRM
, ZZBaseRM
, PredicateBaseRM
, CROpBaseRM
):
2333 """cr_op: ffirst 3-bit mode"""
2341 def specifiers(self
, record
):
2342 yield from super().specifiers(record
=record
, mode
="ff")
2345 class CROpFF5RM(FFPRRc0BaseRM
, PredicateBaseRM
,
2346 VLiBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2347 """cr_op: ffirst 5-bit mode"""
2350 RC1
: BaseRM
[19] # cheat: set RC=1 based on ffirst mode being set
2354 def specifiers(self
, record
):
2355 yield from super().specifiers(record
=record
, mode
="ff")
2358 class CROpRM(CROpBaseRM
):
2359 simple
: CROpSimpleRM
2365 # ********************
2367 # https://libre-soc.org/openpower/sv/branches/
2368 class BranchBaseRM(BaseRM
):
2378 def specifiers(self
, record
):
2390 raise ValueError(self
.sz
)
2402 # Branch modes lack source mask.
2403 # Therefore a custom code is needed.
2404 CR
= (int(self
.mmode
) == 1)
2405 mask
= int(self
.mask
)
2406 m
= PredicateBaseRM
.predicate(CR
, mask
)
2410 yield from super().specifiers(record
=record
)
2413 class BranchSimpleRM(BranchBaseRM
):
2414 """branch: simple mode"""
2418 class BranchVLSRM(BranchBaseRM
):
2419 """branch: VLSET mode"""
2423 def specifiers(self
, record
):
2429 }[int(self
.VSb
), int(self
.VLi
)]
2431 yield from super().specifiers(record
=record
)
2434 class BranchCTRRM(BranchBaseRM
):
2435 """branch: CTR-test mode"""
2438 def specifiers(self
, record
):
2444 yield from super().specifiers(record
=record
)
2447 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2448 """branch: CTR-test+VLSET mode"""
2452 class BranchRM(BranchBaseRM
):
2453 simple
: BranchSimpleRM
2456 ctrvls
: BranchCTRVLSRM
2466 def select(self
, record
):
2470 # the idea behind these tables is that they are now literally
2471 # in identical format to insndb.csv and minor_xx.csv and can
2472 # be done precisely as that. the only thing to watch out for
2473 # is the insertion of Rc=1 as a "mask/value" bit and likewise
2474 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
2477 if record
.svp64
.mode
is _SVMode
.NORMAL
:
2478 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
2479 # mode Rc mask Rc member
2481 (0b000000, 0b111000, "simple"), # simple (no Rc)
2482 (0b001000, 0b111000, "mr"), # mapreduce (no Rc)
2483 (0b010001, 0b110001, "ffrc1"), # ffirst, Rc=1
2484 (0b010000, 0b110001, "ffrc0"), # ffirst, Rc=0
2485 (0b100000, 0b110000, "sat"), # saturation (no Rc)
2486 (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
2487 (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
2490 search
= ((int(rm
.mode
) << 1) | Rc
)
2492 elif record
.svp64
.mode
is _SVMode
.LDST_IMM
:
2493 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
2494 # mode Rc mask Rc member
2495 # ironically/coincidentally this table is identical to NORMAL
2496 # mode except reserved in place of mr
2498 (0b000000, 0b111000, "simple"), # simple (no Rc)
2499 (0b001000, 0b111000, "post"), # post (no Rc)
2500 (0b010001, 0b110001, "ffrc1"), # ffirst, Rc=1
2501 (0b010000, 0b110001, "ffrc0"), # ffirst, Rc=0
2502 (0b100000, 0b110000, "sat"), # saturation (no Rc)
2503 (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
2504 (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
2507 search
= ((int(rm
.mode
) << 1) | Rc
)
2509 elif record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2510 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
2511 # mode Rc mask Rc member
2513 (0b000000, 0b110000, "simple"), # simple (no Rc)
2514 (0b010000, 0b110000, "stride"), # strided, (no Rc)
2515 (0b100000, 0b110000, "sat"), # saturation (no Rc)
2516 (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
2517 (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
2520 search
= ((int(rm
.mode
) << 1) | Rc
)
2522 elif record
.svp64
.mode
is _SVMode
.CROP
:
2523 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
2524 # mode 3b mask 3b member
2526 (0b000000, 0b111000, "simple"), # simple
2527 (0b001000, 0b111000, "mr"), # mapreduce
2528 (0b100001, 0b100001, "ff3"), # ffirst, 3-bit CR
2529 (0b100000, 0b100000, "ff5"), # ffirst, 5-bit CR
2532 search
= ((int(rm
.mode
) << 1) |
int(record
.svp64
.cr_3bit
))
2534 elif record
.svp64
.mode
is _SVMode
.BRANCH
:
2538 (0b00, 0b11, "simple"), # simple
2539 (0b01, 0b11, "vls"), # VLset
2540 (0b10, 0b11, "ctr"), # CTR mode
2541 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
2543 # slightly weird: doesn't have a 5-bit "mode" field like others
2545 search
= int(rm
.mode
.sel
)
2548 if table
is not None:
2549 for (value
, mask
, member
) in table
:
2550 if ((value
& mask
) == (search
& mask
)):
2551 rm
= getattr(rm
, member
)
2554 if rm
.__class
__ is self
.__class
__:
2555 raise ValueError(self
)
2560 @_dataclasses.dataclass(eq
=True, frozen
=True)
2565 def match(cls
, desc
, record
):
2566 raise NotImplementedError
2568 def validate(self
, others
):
2571 def assemble(self
, insn
):
2572 raise NotImplementedError
2575 @_dataclasses.dataclass(eq
=True, frozen
=True)
2576 class SpecifierWidth(Specifier
):
2580 def match(cls
, desc
, record
, etalon
):
2581 (mode
, _
, value
) = desc
.partition("=")
2583 value
= value
.strip()
2586 value
= _SVP64Width(value
)
2588 return cls(record
=record
, mode
=mode
, value
=value
)
2591 @_dataclasses.dataclass(eq
=True, frozen
=True)
2592 class SpecifierW(SpecifierWidth
):
2594 def match(cls
, desc
, record
):
2595 return super().match(desc
=desc
, record
=record
, etalon
="w")
2597 def assemble(self
, insn
):
2598 insn
.prefix
.rm
.ewsrc
= int(self
.value
)
2599 insn
.prefix
.rm
.elwidth
= int(self
.value
)
2602 @_dataclasses.dataclass(eq
=True, frozen
=True)
2603 class SpecifierSW(SpecifierWidth
):
2605 def match(cls
, desc
, record
):
2606 return super().match(desc
=desc
, record
=record
, etalon
="sw")
2608 def assemble(self
, insn
):
2609 insn
.prefix
.rm
.ewsrc
= int(self
.value
)
2612 @_dataclasses.dataclass(eq
=True, frozen
=True)
2613 class SpecifierDW(SpecifierWidth
):
2615 def match(cls
, desc
, record
):
2616 return super().match(desc
=desc
, record
=record
, etalon
="dw")
2618 def assemble(self
, insn
):
2619 insn
.prefix
.rm
.elwidth
= int(self
.value
)
2622 @_dataclasses.dataclass(eq
=True, frozen
=True)
2623 class SpecifierSubVL(Specifier
):
2627 def match(cls
, desc
, record
):
2629 value
= _SVP64SubVL(desc
)
2633 return cls(record
=record
, value
=value
)
2635 def assemble(self
, insn
):
2636 insn
.prefix
.rm
.subvl
= int(self
.value
.value
)
2639 @_dataclasses.dataclass(eq
=True, frozen
=True)
2640 class SpecifierPredicate(Specifier
):
2645 def match(cls
, desc
, record
, mode_match
, pred_match
):
2646 (mode
, _
, pred
) = desc
.partition("=")
2649 if not mode_match(mode
):
2652 pred
= _SVP64Pred(pred
.strip())
2653 if not pred_match(pred
):
2654 raise ValueError(pred
)
2656 return cls(record
=record
, mode
=mode
, pred
=pred
)
2659 @_dataclasses.dataclass(eq
=True, frozen
=True)
2660 class SpecifierFFPR(SpecifierPredicate
):
2662 def match(cls
, desc
, record
, mode
):
2663 return super().match(desc
=desc
, record
=record
,
2664 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2665 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2670 def assemble(self
, insn
):
2672 if rm
.mode
.sel
!= 0:
2673 raise ValueError("cannot override mode")
2675 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2676 if self
.mode
== "pr":
2677 raise ValueError("crop: 'pr' mode not supported")
2679 if self
.record
.svp64
.cr_3bit
:
2684 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
2686 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
2688 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2690 if self
.mode
== "ff":
2691 raise ValueError("ld/st idx: 'ff' mode not supported")
2693 raise ValueError(f
"{self.mode!r} not supported")
2695 # These 2-bit values should have bits swapped
2697 return (((value
& 0b10) >> 1) |
((value
& 0b01) << 1))
2700 "ff": bitswap(_SVP64RMMode
.FFIRST
.value
),
2701 "pr": bitswap(_SVP64RMMode
.PREDRES
.value
),
2704 Rc
= int(self
.record
.Rc
)
2705 rm
= getattr(rm
, f
"{self.mode}rc{Rc}")
2706 rm
.inv
= self
.pred
.inv
2708 rm
.CR
= self
.pred
.state
2710 rm
.RC1
= self
.pred
.state
2713 @_dataclasses.dataclass(eq
=True, frozen
=True)
2714 class SpecifierFF(SpecifierFFPR
):
2716 def match(cls
, desc
, record
):
2717 return super().match(desc
=desc
, record
=record
, mode
="ff")
2720 @_dataclasses.dataclass(eq
=True, frozen
=True)
2721 class SpecifierPR(SpecifierFFPR
):
2723 def match(cls
, desc
, record
):
2724 return super().match(desc
=desc
, record
=record
, mode
="pr")
2727 @_dataclasses.dataclass(eq
=True, frozen
=True)
2728 class SpecifierMask(SpecifierPredicate
):
2730 def match(cls
, desc
, record
, mode
):
2731 return super().match(desc
=desc
, record
=record
,
2732 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2733 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2738 def assemble(self
, insn
):
2739 raise NotImplementedError
2742 @_dataclasses.dataclass(eq
=True, frozen
=True)
2743 class SpecifierM(SpecifierMask
):
2745 def match(cls
, desc
, record
):
2746 return super().match(desc
=desc
, record
=record
, mode
="m")
2748 def validate(self
, others
):
2750 if isinstance(spec
, SpecifierSM
):
2751 raise ValueError("source-mask and predicate mask conflict")
2752 elif isinstance(spec
, SpecifierDM
):
2753 raise ValueError("dest-mask and predicate mask conflict")
2755 def assemble(self
, insn
):
2756 insn
.prefix
.rm
.mask
= int(self
.pred
)
2759 @_dataclasses.dataclass(eq
=True, frozen
=True)
2760 class SpecifierSM(SpecifierMask
):
2762 def match(cls
, desc
, record
):
2763 return super().match(desc
=desc
, record
=record
, mode
="sm")
2765 def validate(self
, others
):
2766 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2767 raise ValueError("source-mask on non-twin predicate")
2769 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2772 if isinstance(spec
, SpecifierDM
):
2776 raise ValueError("missing dest-mask in CR twin predication")
2777 if self
.pred
!= twin
.pred
:
2778 raise ValueError(f
"predicate masks mismatch: {self!r} vs {twin!r}")
2780 def assemble(self
, insn
):
2781 insn
.prefix
.rm
.smask
= int(self
.pred
)
2784 @_dataclasses.dataclass(eq
=True, frozen
=True)
2785 class SpecifierDM(SpecifierMask
):
2787 def match(cls
, desc
, record
):
2788 return super().match(desc
=desc
, record
=record
, mode
="dm")
2790 def validate(self
, others
):
2791 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2792 raise ValueError("dest-mask on non-twin predicate")
2794 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2797 if isinstance(spec
, SpecifierSM
):
2801 raise ValueError("missing source-mask in CR twin predication")
2802 if self
.pred
!= twin
.pred
:
2803 raise ValueError(f
"predicate masks mismatch: {self!r} vs {twin!r}")
2805 def assemble(self
, insn
):
2806 insn
.prefix
.rm
.mask
= int(self
.pred
)
2810 @_dataclasses.dataclass(eq
=True, frozen
=True)
2811 class SpecifierZZ(Specifier
):
2813 def match(cls
, desc
, record
):
2817 return cls(record
=record
)
2819 def validate(self
, others
):
2821 # Since m=xx takes precedence (overrides) sm=xx and dm=xx,
2822 # treat them as mutually exclusive.
2823 if isinstance(spec
, (SpecifierSZ
, SpecifierDZ
)):
2824 raise ValueError("mutually exclusive predicate masks")
2826 def assemble(self
, insn
):
2827 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
2828 if hasattr(rm
, "zz"):
2835 @_dataclasses.dataclass(eq
=True, frozen
=True)
2836 class SpecifierXZ(Specifier
):
2838 hint
: str = _dataclasses
.field(repr=False)
2841 def match(cls
, desc
, record
, etalon
, hint
):
2845 return cls(desc
=desc
, record
=record
, hint
=hint
)
2847 def validate(self
, others
):
2848 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2849 raise ValueError(f
"{self.hint} on non-twin predicate")
2851 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2854 if isinstance(spec
, SpecifierSM
):
2858 raise ValueError(f
"missing {self.hint} in CR twin predication")
2859 if self
.pred
!= twin
.pred
:
2860 raise ValueError(f
"predicate masks mismatch: {self!r} vs {twin!r}")
2862 def assemble(self
, insn
):
2863 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
2864 setattr(rm
, self
.desc
, 1)
2867 @_dataclasses.dataclass(eq
=True, frozen
=True)
2868 class SpecifierSZ(SpecifierXZ
):
2870 def match(cls
, desc
, record
):
2871 return super().match(desc
=desc
, record
=record
,
2872 etalon
="sz", hint
="source-mask")
2874 def validate(self
, others
):
2876 if isinstance(spec
, SpecifierFF
):
2877 raise ValueError("source-zero not allowed in ff mode")
2878 elif isinstance(spec
, SpecifierPR
):
2879 raise ValueError("source-zero not allowed in pr mode")
2882 @_dataclasses.dataclass(eq
=True, frozen
=True)
2883 class SpecifierDZ(SpecifierXZ
):
2885 def match(cls
, desc
, record
):
2886 return super().match(desc
=desc
, record
=record
,
2887 etalon
="dz", hint
="dest-mask")
2889 def validate(self
, others
):
2891 if (isinstance(spec
, (SpecifierFF
, SpecifierPR
)) and
2892 (spec
.pred
.mode
is _SVP64PredMode
.RC1
)):
2893 mode
= "ff" if isinstance(spec
, SpecifierFF
) else "pr"
2894 raise ValueError(f
"dest-zero not allowed in {mode} mode BO")
2897 @_dataclasses.dataclass(eq
=True, frozen
=True)
2898 class SpecifierEls(Specifier
):
2900 def match(cls
, desc
, record
):
2904 return cls(record
=record
)
2906 def assemble(self
, insn
):
2907 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
2909 if self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2913 @_dataclasses.dataclass(eq
=True, frozen
=True)
2914 class SpecifierSEA(Specifier
):
2916 def match(cls
, desc
, record
):
2920 return cls(record
=record
)
2922 def validate(self
, others
):
2923 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
:
2924 raise ValueError("sea is only valid in ld/st modes")
2927 if isinstance(spec
, SpecifierFF
):
2928 raise ValueError(f
"sea cannot be used in ff mode")
2930 def assemble(self
, insn
):
2931 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
2932 if rm
.mode
.sel
not in (0b00, 0b01):
2933 raise ValueError("sea is only valid for normal and els modes")
2937 @_dataclasses.dataclass(eq
=True, frozen
=True)
2938 class SpecifierSat(Specifier
):
2943 def match(cls
, desc
, record
, etalon
, sign
):
2947 return cls(record
=record
, desc
=desc
, sign
=sign
)
2949 def assemble(self
, insn
):
2950 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
2952 rm
.sat
= 1 if self
.sign
else 0
2955 @_dataclasses.dataclass(eq
=True, frozen
=True)
2956 class SpecifierSatS(SpecifierSat
):
2958 def match(cls
, desc
, record
):
2959 return super().match(desc
=desc
, record
=record
,
2960 etalon
="sats", sign
=True)
2963 @_dataclasses.dataclass(eq
=True, frozen
=True)
2964 class SpecifierSatU(SpecifierSat
):
2966 def match(cls
, desc
, record
):
2967 return super().match(desc
=desc
, record
=record
,
2968 etalon
="satu", sign
=False)
2971 @_dataclasses.dataclass(eq
=True, frozen
=True)
2972 class SpecifierMR(Specifier
):
2974 def match(cls
, desc
, record
):
2978 return cls(record
=record
)
2980 def assemble(self
, insn
):
2981 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
2987 @_dataclasses.dataclass(eq
=True, frozen
=True)
2988 class SpecifierMRR(Specifier
):
2990 def match(cls
, desc
, record
):
2994 return cls(record
=record
)
2996 def assemble(self
, insn
):
2997 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
3003 @_dataclasses.dataclass(eq
=True, frozen
=True)
3004 class SpecifierCRM(Specifier
):
3006 def match(cls
, desc
, record
):
3010 return cls(record
=record
)
3012 def assemble(self
, insn
):
3013 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
3018 @_dataclasses.dataclass(eq
=True, frozen
=True)
3019 class SpecifierBranch(Specifier
):
3021 def match(cls
, desc
, record
, etalon
):
3025 return cls(record
=record
)
3027 def validate(self
, others
):
3028 if self
.record
.svp64
.mode
!= _SVMode
.BRANCH
:
3029 raise ValueError("only branch modes supported")
3032 @_dataclasses.dataclass(eq
=True, frozen
=True)
3033 class SpecifierAll(SpecifierBranch
):
3035 def match(cls
, desc
, record
):
3036 return super().match(desc
=desc
, record
=record
, etalon
="all")
3038 def assemble(self
, insn
):
3039 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
3043 @_dataclasses.dataclass(eq
=True, frozen
=True)
3044 class SpecifierSNZ(SpecifierBranch
):
3046 def match(cls
, desc
, record
):
3047 return super().match(desc
=desc
, record
=record
, etalon
="snz")
3049 def assemble(self
, insn
):
3050 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
3055 @_dataclasses.dataclass(eq
=True, frozen
=True)
3056 class SpecifierSL(SpecifierBranch
):
3058 def match(cls
, desc
, record
):
3059 return super().match(desc
=desc
, record
=record
, etalon
="sl")
3061 def assemble(self
, insn
):
3062 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
3066 @_dataclasses.dataclass(eq
=True, frozen
=True)
3067 class SpecifierSLu(SpecifierBranch
):
3069 def match(cls
, desc
, record
):
3070 return super().match(desc
=desc
, record
=record
, etalon
="slu")
3072 def assemble(self
, insn
):
3073 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
3077 @_dataclasses.dataclass(eq
=True, frozen
=True)
3078 class SpecifierLRu(SpecifierBranch
):
3080 def match(cls
, desc
, record
):
3081 return super().match(desc
=desc
, record
=record
, etalon
="lru")
3083 def assemble(self
, insn
):
3084 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
3088 @_dataclasses.dataclass(eq
=True, frozen
=True)
3089 class SpecifierVS(SpecifierBranch
):
3091 def match(cls
, desc
, record
):
3092 return super().match(desc
=desc
, record
=record
, etalon
="vs")
3094 def assemble(self
, insn
):
3095 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
3101 @_dataclasses.dataclass(eq
=True, frozen
=True)
3102 class SpecifierVSi(SpecifierBranch
):
3104 def match(cls
, desc
, record
):
3105 return super().match(desc
=desc
, record
=record
, etalon
="vsi")
3107 def assemble(self
, insn
):
3108 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
3114 @_dataclasses.dataclass(eq
=True, frozen
=True)
3115 class SpecifierVSb(SpecifierBranch
):
3117 def match(cls
, desc
, record
):
3118 return super().match(desc
=desc
, record
=record
, etalon
="vsb")
3120 def assemble(self
, insn
):
3121 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
3127 @_dataclasses.dataclass(eq
=True, frozen
=True)
3128 class SpecifierVSbi(SpecifierBranch
):
3130 def match(cls
, desc
, record
):
3131 return super().match(desc
=desc
, record
=record
, etalon
="vsbi")
3133 def assemble(self
, insn
):
3134 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
3140 @_dataclasses.dataclass(eq
=True, frozen
=True)
3141 class SpecifierCTR(SpecifierBranch
):
3143 def match(cls
, desc
, record
):
3147 return cls(record
=record
)
3149 def assemble(self
, insn
):
3150 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
3154 @_dataclasses.dataclass(eq
=True, frozen
=True)
3155 class SpecifierCTi(SpecifierBranch
):
3157 def match(cls
, desc
, record
):
3161 return cls(record
=record
)
3163 def assemble(self
, insn
):
3164 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
3169 @_dataclasses.dataclass(eq
=True, frozen
=True)
3170 class SpecifierPI(Specifier
):
3172 def match(cls
, desc
, record
):
3176 return cls(record
=record
)
3178 def assemble(self
, insn
):
3179 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
3183 @_dataclasses.dataclass(eq
=True, frozen
=True)
3184 class SpecifierLF(Specifier
):
3186 def match(cls
, desc
, record
):
3190 return cls(record
=record
)
3192 def assemble(self
, insn
):
3193 rm
= insn
.prefix
.rm
.select(record
=self
.record
)
3197 class Specifiers(tuple):
3233 def __new__(cls
, items
, record
):
3234 def transform(item
):
3235 for spec_cls
in cls
.SPECS
:
3236 spec
= spec_cls
.match(item
, record
=record
)
3237 if spec
is not None:
3239 raise ValueError(item
)
3241 specs
= tuple(map(transform
, items
))
3242 for (index
, spec
) in enumerate(specs
):
3243 head
= specs
[:index
]
3244 tail
= specs
[index
+ 1:]
3245 spec
.validate(others
=(head
+ tail
))
3247 return super().__new
__(cls
, specs
)
3250 class SVP64Instruction(PrefixedInstruction
):
3251 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
3252 class Prefix(PrefixedInstruction
.Prefix
):
3254 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
3259 def record(cls
, db
, entry
):
3260 if isinstance(entry
, SVP64Instruction
):
3261 entry
= entry
.suffix
3262 return super().record(db
=db
, entry
=entry
)
3267 for idx
in range(64):
3268 bit
= int(self
[idx
])
3270 return "".join(map(str, bits
))
3273 def assemble(cls
, db
, opcode
, arguments
=None, specifiers
=None):
3274 if arguments
is None:
3276 if specifiers
is None:
3279 record
= cls
.record(db
=db
, entry
=opcode
)
3280 insn
= cls
.integer(value
=0)
3282 specifiers
= Specifiers(items
=specifiers
, record
=record
)
3283 for specifier
in specifiers
:
3284 specifier
.assemble(insn
=insn
)
3286 for operand
in record
.static_operands
:
3287 operand
.assemble(insn
=insn
)
3289 dynamic_operands
= tuple(record
.dynamic_operands
)
3290 for (value
, operand
) in Arguments(arguments
, dynamic_operands
):
3291 operand
.assemble(value
=value
, insn
=insn
)
3293 insn
.prefix
.PO
= 0x1
3294 insn
.prefix
.id = 0x3
3298 def disassemble(self
, db
,
3300 verbosity
=Verbosity
.NORMAL
):
3302 if verbosity
<= Verbosity
.SHORT
:
3305 blob
= insn
.bytes(byteorder
=byteorder
)
3306 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
3309 record
= self
.record(db
=db
, entry
=self
)
3310 blob_prefix
= blob(self
.prefix
)
3311 blob_suffix
= blob(self
.suffix
)
3312 if record
is None or record
.svp64
is None:
3313 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3314 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
3317 name
= f
"sv.{record.name}"
3319 rm
= self
.prefix
.rm
.select(record
=record
)
3321 # convert specifiers to /x/y/z (sorted lexicographically)
3322 specifiers
= sorted(rm
.specifiers(record
=record
))
3323 if specifiers
: # if any add one extra to get the extra "/"
3324 specifiers
= ([""] + specifiers
)
3325 specifiers
= "/".join(specifiers
)
3327 # convert operands to " ,x,y,z"
3328 operands
= tuple(map(_operator
.itemgetter(1),
3329 self
.dynamic_operands(db
=db
, verbosity
=verbosity
)))
3330 operands
= ",".join(operands
)
3331 if len(operands
) > 0: # if any separate with a space
3332 operands
= (" " + operands
)
3334 yield f
"{blob_prefix}{name}{specifiers}{operands}"
3336 yield f
"{blob_suffix}"
3338 if verbosity
>= Verbosity
.VERBOSE
:
3340 binary
= self
.binary
3341 spec
= self
.spec(db
=db
, prefix
="sv.")
3343 yield f
"{indent}spec"
3344 yield f
"{indent}{indent}{spec}"
3345 yield f
"{indent}pcode"
3346 for stmt
in record
.mdwn
.pcode
:
3347 yield f
"{indent}{indent}{stmt}"
3348 yield f
"{indent}binary"
3349 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
3350 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
3351 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
3352 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
3353 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
3354 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
3355 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
3356 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
3357 yield f
"{indent}opcodes"
3358 for opcode
in record
.opcodes
:
3359 yield f
"{indent}{indent}{opcode!r}"
3360 for (cls
, kwargs
) in record
.mdwn
.operands
:
3361 operand
= cls(record
=record
, **kwargs
)
3362 yield from operand
.disassemble(insn
=self
,
3363 verbosity
=verbosity
, indent
=indent
)
3365 yield f
"{indent}{indent}{rm.__doc__}"
3366 for line
in rm
.disassemble(verbosity
=verbosity
):
3367 yield f
"{indent}{indent}{line}"
3371 def parse(stream
, factory
):
3373 return ("TODO" not in frozenset(entry
.values()))
3375 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
3376 entries
= _csv
.DictReader(lines
)
3377 entries
= filter(match
, entries
)
3378 return tuple(map(factory
, entries
))
3381 class MarkdownDatabase
:
3384 for (name
, desc
) in _ISA():
3387 (dynamic
, *static
) = desc
.regs
3388 operands
.extend(dynamic
)
3389 operands
.extend(static
)
3390 pcode
= PCode(iterable
=desc
.pcode
)
3391 operands
= Operands(insn
=name
, iterable
=operands
)
3392 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
3394 self
.__db
= dict(sorted(db
.items()))
3396 return super().__init
__()
3399 yield from self
.__db
.items()
3401 def __contains__(self
, key
):
3402 return self
.__db
.__contains
__(key
)
3404 def __getitem__(self
, key
):
3405 return self
.__db
.__getitem
__(key
)
3408 class FieldsDatabase
:
3411 df
= _DecodeFields()
3413 for (form
, fields
) in df
.instrs
.items():
3414 if form
in {"DQE", "TX"}:
3418 db
[_Form
[form
]] = Fields(fields
)
3422 return super().__init
__()
3424 def __getitem__(self
, key
):
3425 return self
.__db
.__getitem
__(key
)
3429 def __init__(self
, root
, mdwndb
):
3430 # The code below groups the instructions by name:section.
3431 # There can be multiple names for the same instruction.
3432 # The point is to capture different opcodes for the same instruction.
3433 dd
= _collections
.defaultdict
3435 records
= _collections
.defaultdict(set)
3436 path
= (root
/ "insndb.csv")
3437 with
open(path
, "r", encoding
="UTF-8") as stream
:
3438 for section
in sorted(parse(stream
, Section
.CSV
)):
3439 path
= (root
/ section
.path
)
3441 section
.Mode
.INTEGER
: IntegerOpcode
,
3442 section
.Mode
.PATTERN
: PatternOpcode
,
3444 factory
= _functools
.partial(
3445 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
3446 with
open(path
, "r", encoding
="UTF-8") as stream
:
3447 for insn
in parse(stream
, factory
):
3448 for name
in insn
.names
:
3449 records
[name
].add(insn
)
3450 sections
[name
] = section
3452 items
= sorted(records
.items())
3454 for (name
, multirecord
) in items
:
3455 records
[name
] = PPCMultiRecord(sorted(multirecord
))
3457 def exact_match(name
):
3458 record
= records
.get(name
)
3464 if not name
.endswith("l"):
3466 alias
= exact_match(name
[:-1])
3469 record
= records
[alias
]
3470 if "lk" not in record
.flags
:
3471 raise ValueError(record
)
3475 if not name
.endswith("a"):
3477 alias
= LK_match(name
[:-1])
3480 record
= records
[alias
]
3481 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
3482 raise ValueError(record
)
3483 if "AA" not in mdwndb
[name
].operands
:
3484 raise ValueError(record
)
3488 if not name
.endswith("."):
3490 alias
= exact_match(name
[:-1])
3493 record
= records
[alias
]
3494 if record
.Rc
is _RCOE
.NONE
:
3495 raise ValueError(record
)
3499 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
3500 for (name
, _
) in mdwndb
:
3501 if name
.startswith("sv."):
3504 for match
in matches
:
3506 if alias
is not None:
3510 section
= sections
[alias
]
3511 record
= records
[alias
]
3512 db
[name
] = (section
, record
)
3514 self
.__db
= dict(sorted(db
.items()))
3516 return super().__init
__()
3518 @_functools.lru_cache(maxsize
=512, typed
=False)
3519 def __getitem__(self
, key
):
3520 return self
.__db
.get(key
, (None, None))
3523 class SVP64Database
:
3524 def __init__(self
, root
, ppcdb
):
3526 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
3527 for (prefix
, _
, names
) in _os
.walk(root
):
3528 prefix
= _pathlib
.Path(prefix
)
3529 for name
in filter(lambda name
: pattern
.match(name
), names
):
3530 path
= (prefix
/ _pathlib
.Path(name
))
3531 with
open(path
, "r", encoding
="UTF-8") as stream
:
3532 db
.update(parse(stream
, SVP64Record
.CSV
))
3533 db
= {record
.name
:record
for record
in db
}
3535 self
.__db
= dict(sorted(db
.items()))
3536 self
.__ppcdb
= ppcdb
3538 return super().__init
__()
3540 def __getitem__(self
, key
):
3541 (_
, record
) = self
.__ppcdb
[key
]
3545 for name
in record
.names
:
3546 record
= self
.__db
.get(name
, None)
3547 if record
is not None:
3554 def __init__(self
, root
):
3555 root
= _pathlib
.Path(root
)
3556 mdwndb
= MarkdownDatabase()
3557 fieldsdb
= FieldsDatabase()
3558 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
3559 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
3563 opcodes
= _collections
.defaultdict(
3564 lambda: _collections
.defaultdict(set))
3566 for (name
, mdwn
) in mdwndb
:
3567 if name
.startswith("sv."):
3569 (section
, ppc
) = ppcdb
[name
]
3572 svp64
= svp64db
[name
]
3573 fields
= fieldsdb
[ppc
.form
]
3574 record
= Record(name
=name
,
3575 section
=section
, ppc
=ppc
, svp64
=svp64
,
3576 mdwn
=mdwn
, fields
=fields
)
3578 names
[record
.name
] = record
3582 opcodes
[section
][PO
.value
].add(record
)
3584 self
.__db
= sorted(db
)
3585 self
.__names
= dict(sorted(names
.items()))
3586 self
.__opcodes
= dict(sorted(opcodes
.items()))
3588 return super().__init
__()
3591 return repr(self
.__db
)
3594 yield from self
.__db
3596 @_functools.lru_cache(maxsize
=None)
3597 def __contains__(self
, key
):
3598 return self
.__getitem
__(key
) is not None
3600 @_functools.lru_cache(maxsize
=None)
3601 def __getitem__(self
, key
):
3602 if isinstance(key
, Instruction
):
3605 for (section
, group
) in self
.__opcodes
.items():
3606 for record
in group
[PO
]:
3607 if record
.match(key
=key
):
3612 elif isinstance(key
, str):
3613 return self
.__names
.get(key
)
3615 raise ValueError("instruction or name expected")