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 CROutSel
as _CROutSel
,
27 LDSTMode
as _LDSTMode
,
36 SVExtraRegType
as _SVExtraRegType
,
37 SVExtraReg
as _SVExtraReg
,
39 from openpower
.decoder
.selectable_int
import (
40 SelectableInt
as _SelectableInt
,
41 selectconcat
as _selectconcat
,
43 from openpower
.decoder
.power_fields
import (
46 DecodeFields
as _DecodeFields
,
48 from openpower
.decoder
.pseudo
.pagereader
import ISA
as _ISA
51 @_functools.total_ordering
52 class Verbosity(_enum
.Enum
):
55 VERBOSE
= _enum
.auto()
57 def __lt__(self
, other
):
58 if not isinstance(other
, self
.__class
__):
60 return (self
.value
< other
.value
)
63 def dataclass(cls
, record
, keymap
=None, typemap
=None):
67 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
69 def transform(key_value
):
70 (key
, value
) = key_value
71 key
= keymap
.get(key
, key
)
72 hook
= typemap
.get(key
, lambda value
: value
)
73 if hook
is bool and value
in ("", "0"):
79 record
= dict(map(transform
, record
.items()))
80 for key
in frozenset(record
.keys()):
87 @_functools.total_ordering
88 @_dataclasses.dataclass(eq
=True, frozen
=True)
91 def __new__(cls
, value
):
92 if isinstance(value
, str):
94 if not isinstance(value
, int):
95 raise ValueError(value
)
97 if value
.bit_length() > 64:
98 raise ValueError(value
)
100 return super().__new
__(cls
, value
)
103 return super().__repr
__()
106 return f
"{self:0{self.bit_length()}b}"
108 def bit_length(self
):
109 if super().bit_length() > 32:
113 class Value(Integer
):
122 def __lt__(self
, other
):
123 if not isinstance(other
, Opcode
):
124 return NotImplemented
125 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
127 def __post_init__(self
):
128 if self
.value
.bit_length() != self
.mask
.bit_length():
129 raise ValueError("bit length mismatch")
132 def pattern(value
, mask
, bit_length
):
133 for bit
in range(bit_length
):
134 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
136 elif (value
& (1 << (bit_length
- bit
- 1))):
141 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
144 class IntegerOpcode(Opcode
):
145 def __init__(self
, value
):
146 if value
.startswith("0b"):
147 mask
= int(("1" * len(value
[2:])), 2)
151 value
= Opcode
.Value(value
)
152 mask
= Opcode
.Mask(mask
)
154 return super().__init
__(value
=value
, mask
=mask
)
157 class PatternOpcode(Opcode
):
158 def __init__(self
, pattern
):
159 if not isinstance(pattern
, str):
160 raise ValueError(pattern
)
162 (value
, mask
) = (0, 0)
163 for symbol
in pattern
:
164 if symbol
not in {"0", "1", "-"}:
165 raise ValueError(pattern
)
166 value |
= (symbol
== "1")
167 mask |
= (symbol
!= "-")
173 value
= Opcode
.Value(value
)
174 mask
= Opcode
.Mask(mask
)
176 return super().__init
__(value
=value
, mask
=mask
)
179 @_dataclasses.dataclass(eq
=True, frozen
=True)
181 class FlagsMeta(type):
196 class Flags(frozenset, metaclass
=FlagsMeta
):
197 def __new__(cls
, flags
=frozenset()):
198 flags
= frozenset(flags
)
199 diff
= (flags
- frozenset(cls
))
201 raise ValueError(flags
)
202 return super().__new
__(cls
, flags
)
206 flags
: Flags
= Flags()
208 function
: _Function
= _Function
.NONE
209 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
210 in1
: _In1Sel
= _In1Sel
.RA
211 in2
: _In2Sel
= _In2Sel
.NONE
212 in3
: _In3Sel
= _In3Sel
.NONE
213 out
: _OutSel
= _OutSel
.NONE
214 cr_in
: _CRInSel
= _CRInSel
.NONE
215 cr_out
: _CROutSel
= _CROutSel
.NONE
216 cry_in
: _CryIn
= _CryIn
.ZERO
217 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
218 upd
: _LDSTMode
= _LDSTMode
.NONE
219 Rc
: _RCOE
= _RCOE
.NONE
220 form
: _Form
= _Form
.NONE
222 unofficial
: bool = False
226 "internal op": "intop",
230 "ldst len": "ldst_len",
232 "CONDITIONS": "conditions",
236 def CSV(cls
, record
, opcode_cls
):
237 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
238 typemap
["opcode"] = opcode_cls
241 for flag
in frozenset(PPCRecord
.Flags
):
242 if bool(record
.pop(flag
, "")):
244 record
["flags"] = PPCRecord
.Flags(flags
)
246 return dataclass(cls
, record
,
247 keymap
=PPCRecord
.__KEYMAP
,
252 return frozenset(self
.comment
.split("=")[-1].split("/"))
255 class PPCMultiRecord(tuple):
256 def __getattr__(self
, attr
):
258 raise AttributeError(attr
)
259 return getattr(self
[0], attr
)
262 @_dataclasses.dataclass(eq
=True, frozen
=True)
264 class ExtraMap(tuple):
266 @_dataclasses.dataclass(eq
=True, frozen
=True)
268 regtype
: _SVExtraRegType
= _SVExtraRegType
.NONE
269 reg
: _SVExtraReg
= _SVExtraReg
.NONE
272 return f
"{self.regtype.value}:{self.reg.name}"
274 def __new__(cls
, value
="0"):
275 if isinstance(value
, str):
276 def transform(value
):
277 (regtype
, reg
) = value
.split(":")
278 regtype
= _SVExtraRegType(regtype
)
279 reg
= _SVExtraReg(reg
)
280 return cls
.Entry(regtype
=regtype
, reg
=reg
)
285 value
= map(transform
, value
.split(";"))
287 return super().__new
__(cls
, value
)
290 return repr(list(self
))
292 def __new__(cls
, value
=tuple()):
296 return super().__new
__(cls
, map(cls
.Extra
, value
))
299 return repr({index
:self
[index
] for index
in range(0, 4)})
302 ptype
: _SVPtype
= _SVPtype
.NONE
303 etype
: _SVEtype
= _SVEtype
.NONE
304 in1
: _In1Sel
= _In1Sel
.NONE
305 in2
: _In2Sel
= _In2Sel
.NONE
306 in3
: _In3Sel
= _In3Sel
.NONE
307 out
: _OutSel
= _OutSel
.NONE
308 out2
: _OutSel
= _OutSel
.NONE
309 cr_in
: _CRInSel
= _CRInSel
.NONE
310 cr_out
: _CROutSel
= _CROutSel
.NONE
311 extra
: ExtraMap
= ExtraMap()
313 mode
: _SVMode
= _SVMode
.NORMAL
317 "CONDITIONS": "conditions",
325 def CSV(cls
, record
):
326 for key
in ("in1", "in2", "in3", "out", "out2", "CR in", "CR out"):
332 for idx
in range(0, 4):
333 extra
.append(record
.pop(f
"{idx}"))
335 record
["extra"] = cls
.ExtraMap(extra
)
337 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
339 @_functools.lru_cache(maxsize
=None)
340 def extra_idx(self
, key
):
348 if key
not in frozenset({
349 "in1", "in2", "in3", "cr_in",
350 "out", "out2", "cr_out",
354 sel
= getattr(self
, key
)
355 if sel
is _CRInSel
.BA_BB
:
356 return _SVExtra
.Idx_1_2
357 reg
= _SVExtraReg(sel
)
358 if reg
is _SVExtraReg
.NONE
:
362 _SVExtraRegType
.SRC
: {},
363 _SVExtraRegType
.DST
: {},
365 for index
in range(0, 4):
366 for entry
in self
.extra
[index
]:
367 extra_map
[entry
.regtype
][entry
.reg
] = extra_idx
[index
]
369 for regtype
in (_SVExtraRegType
.SRC
, _SVExtraRegType
.DST
):
370 extra
= extra_map
[regtype
].get(reg
, _SVExtra
.NONE
)
371 if extra
is not _SVExtra
.NONE
:
376 extra_idx_in1
= property(_functools
.partial(extra_idx
, key
="in1"))
377 extra_idx_in2
= property(_functools
.partial(extra_idx
, key
="in2"))
378 extra_idx_in3
= property(_functools
.partial(extra_idx
, key
="in3"))
379 extra_idx_out
= property(_functools
.partial(extra_idx
, key
="out"))
380 extra_idx_out2
= property(_functools
.partial(extra_idx
, key
="out2"))
381 extra_idx_cr_in
= property(_functools
.partial(extra_idx
, key
="cr_in"))
382 extra_idx_cr_out
= property(_functools
.partial(extra_idx
, key
="cr_out"))
384 @_functools.lru_cache(maxsize
=None)
385 def extra_reg(self
, key
):
386 return _SVExtraReg(getattr(self
, key
))
388 extra_reg_in1
= property(_functools
.partial(extra_reg
, key
="in1"))
389 extra_reg_in2
= property(_functools
.partial(extra_reg
, key
="in2"))
390 extra_reg_in3
= property(_functools
.partial(extra_reg
, key
="in3"))
391 extra_reg_out
= property(_functools
.partial(extra_reg
, key
="out"))
392 extra_reg_out2
= property(_functools
.partial(extra_reg
, key
="out2"))
393 extra_reg_cr_in
= property(_functools
.partial(extra_reg
, key
="cr_in"))
394 extra_reg_cr_out
= property(_functools
.partial(extra_reg
, key
="cr_out"))
398 def __init__(self
, value
=(0, 32)):
399 if isinstance(value
, str):
400 (start
, end
) = map(int, value
.split(":"))
403 if start
< 0 or end
< 0 or start
>= end
:
404 raise ValueError(value
)
409 return super().__init
__()
412 return f
"[{self.__start}:{self.__end}]"
415 yield from range(self
.start
, (self
.end
+ 1))
417 def __reversed__(self
):
418 return tuple(reversed(tuple(self
)))
429 @_dataclasses.dataclass(eq
=True, frozen
=True)
431 class Mode(_enum
.Enum
):
432 INTEGER
= _enum
.auto()
433 PATTERN
= _enum
.auto()
436 def _missing_(cls
, value
):
437 if isinstance(value
, str):
438 return cls
[value
.upper()]
439 return super()._missing
_(value
)
442 def __new__(cls
, value
=None):
443 if isinstance(value
, str):
444 if value
.upper() == "NONE":
447 value
= int(value
, 0)
451 return super().__new
__(cls
, value
)
457 return (bin(self
) if self
else "None")
463 opcode
: IntegerOpcode
= None
466 def CSV(cls
, record
):
467 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
468 if record
["opcode"] == "NONE":
469 typemap
["opcode"] = lambda _
: None
471 return dataclass(cls
, record
, typemap
=typemap
)
475 def __init__(self
, items
):
476 if isinstance(items
, dict):
477 items
= items
.items()
480 (name
, bitrange
) = item
481 return (name
, tuple(bitrange
.values()))
483 self
.__mapping
= dict(map(transform
, items
))
485 return super().__init
__()
488 return repr(self
.__mapping
)
491 yield from self
.__mapping
.items()
493 def __contains__(self
, key
):
494 return self
.__mapping
.__contains
__(key
)
496 def __getitem__(self
, key
):
497 return self
.__mapping
.get(key
, None)
500 @_dataclasses.dataclass(eq
=True, frozen
=True)
504 def span(self
, record
):
505 return record
.fields
[self
.name
]
507 def disassemble(self
, insn
, record
,
508 verbosity
=Verbosity
.NORMAL
, indent
=""):
509 raise NotImplementedError
512 class DynamicOperand(Operand
):
513 def disassemble(self
, insn
, record
,
514 verbosity
=Verbosity
.NORMAL
, indent
=""):
515 span
= self
.span(record
=record
)
516 if isinstance(insn
, SVP64Instruction
):
517 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
520 if verbosity
>= Verbosity
.VERBOSE
:
521 span
= map(str, span
)
522 yield f
"{indent}{self.name}"
523 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
524 yield f
"{indent}{indent}{', '.join(span)}"
526 yield str(int(value
))
529 @_dataclasses.dataclass(eq
=True, frozen
=True)
530 class StaticOperand(Operand
):
533 def disassemble(self
, insn
, record
,
534 verbosity
=Verbosity
.NORMAL
, indent
=""):
535 span
= self
.span(record
=record
)
536 if isinstance(insn
, SVP64Instruction
):
537 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
540 if verbosity
>= Verbosity
.VERBOSE
:
541 span
= map(str, span
)
542 yield f
"{indent}{self.name}"
543 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
544 yield f
"{indent}{indent}{', '.join(span)}"
546 yield str(int(value
))
549 class ImmediateOperand(DynamicOperand
):
553 class NonZeroOperand(DynamicOperand
):
554 def disassemble(self
, insn
, record
,
555 verbosity
=Verbosity
.NORMAL
, indent
=""):
556 span
= self
.span(record
=record
)
557 if isinstance(insn
, SVP64Instruction
):
558 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
561 if verbosity
>= Verbosity
.VERBOSE
:
562 span
= map(str, span
)
563 yield f
"{indent}{self.name}"
564 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
565 yield f
"{indent}{indent}{', '.join(span)}"
567 yield str(int(value
) + 1)
570 class RegisterOperand(DynamicOperand
):
571 def spec(self
, insn
, record
, merge
):
573 span
= self
.span(record
=record
)
574 if isinstance(insn
, SVP64Instruction
):
575 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
577 span
= tuple(map(str, span
))
579 if isinstance(insn
, SVP64Instruction
):
580 extra_idx
= self
.extra_idx(record
=record
)
581 if extra_idx
is _SVExtra
.NONE
:
582 return (vector
, value
, span
)
584 if record
.etype
is _SVEtype
.EXTRA3
:
585 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
586 elif record
.etype
is _SVEtype
.EXTRA2
:
587 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
589 raise ValueError(record
.etype
)
592 vector
= bool(spec
[0])
593 spec_span
= spec
.__class
__
594 if record
.etype
is _SVEtype
.EXTRA3
:
595 spec_span
= tuple(map(str, spec_span
[1, 2]))
597 elif record
.etype
is _SVEtype
.EXTRA2
:
598 spec_span
= tuple(map(str, spec_span
[1,]))
599 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
602 spec_span
= (spec_span
+ ("{0}",))
604 spec_span
= (("{0}",) + spec_span
)
606 raise ValueError(record
.etype
)
608 (value
, span
) = merge(vector
, value
, span
, spec
, spec_span
)
610 return (vector
, value
, span
)
614 return _SVExtraReg(self
.name
)
616 def extra_idx(self
, record
):
617 for key
in frozenset({
618 "in1", "in2", "in3", "cr_in",
619 "out", "out2", "cr_out",
621 extra_reg
= record
.svp64
.extra_reg(key
=key
)
622 if extra_reg
is self
.extra_reg
:
623 return record
.extra_idx(key
=key
)
627 def disassemble(self
, insn
, record
,
628 verbosity
=Verbosity
.NORMAL
, prefix
="", indent
=""):
629 (vector
, value
, span
) = self
.spec(insn
=insn
, record
=record
)
631 if verbosity
>= Verbosity
.VERBOSE
:
632 mode
= "vector" if vector
else "scalar"
633 yield f
"{indent}{self.name} ({mode})"
634 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
635 yield f
"{indent}{indent}{', '.join(span)}"
636 if isinstance(insn
, SVP64Instruction
):
637 extra_idx
= self
.extra_idx(record
)
638 if record
.etype
is _SVEtype
.NONE
:
639 yield f
"{indent}{indent}extra[none]"
641 etype
= repr(record
.etype
).lower()
642 yield f
"{indent}{indent}{etype}{extra_idx!r}"
644 vector
= "*" if vector
else ""
645 yield f
"{vector}{prefix}{int(value)}"
648 class GPRFPROperand(RegisterOperand
):
649 def spec(self
, insn
, record
):
650 def merge(vector
, value
, span
, spec
, spec_span
):
651 bits
= (len(span
) + len(spec_span
))
652 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
653 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
654 # this is silly these should be in a general base class,
655 # settable by constructor
660 value
= ((value
<< vshift
) |
(spec
<<spshft
))
661 span
= (span
+ spec_span
)
663 value
= ((spec
<< sshift
) | value
)
664 span
= (spec_span
+ span
)
668 return super().spec(insn
=insn
, record
=record
, merge
=merge
)
671 class GPROperand(GPRFPROperand
):
672 def disassemble(self
, insn
, record
,
673 verbosity
=Verbosity
.NORMAL
, indent
=""):
674 prefix
= "" if (verbosity
<= Verbosity
.SHORT
) else "r"
675 yield from super().disassemble(prefix
=prefix
,
676 insn
=insn
, record
=record
,
677 verbosity
=verbosity
, indent
=indent
)
680 class FPROperand(GPRFPROperand
):
681 def disassemble(self
, insn
, record
,
682 verbosity
=Verbosity
.NORMAL
, indent
=""):
683 prefix
= "" if (verbosity
<= Verbosity
.SHORT
) else "f"
684 yield from super().disassemble(prefix
=prefix
,
685 insn
=insn
, record
=record
,
686 verbosity
=verbosity
, indent
=indent
)
689 class CR3Operand(RegisterOperand
):
690 def spec(self
, insn
, record
):
691 def merge(vector
, value
, span
, spec
, spec_span
):
692 bits
= (len(span
) + len(spec_span
))
693 #print ("value", bin(value.value), value.bits)
694 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
695 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
696 #print ("spec", bin(spec.value), spec.bits)
697 #print ("value", bin(value.value), value.bits)
698 #print ("lsbs", bin(lsbs.value), lsbs.bits)
699 # this is silly these should be in a general base class,
700 # settable by constructor
706 value
= ((value
<< vshift
) |
(spec
<<spshft
))
707 span
= (span
[0:3] + spec_span
+ ('{0}', '{0}') + span
[3:5])
709 value
= ((spec
<< sshift
) | value
)
710 span
= (('{0}', '{0}') + spec_span
+ span
)
712 # add the 2 LSBs back in
713 #print ("after", bin(value.value), value.bits)
716 return super().spec(insn
=insn
, record
=record
, merge
=merge
)
719 # exactly the same as CR3Operand, should be exactly the same base class
720 # which should also be exactly the same base class as GPR and FPR operand
721 # which sohuld be taking a constructor with prefix "r" and "f" as options
722 # as well as vshift, sshift and spsft as parameters, and whether
723 # to skip 2 LSBs and put them back on afterwards.
724 # it's all the exact same scheme, so why on earth duplicate code?
725 class CR5Operand(RegisterOperand
):
726 def spec(self
, insn
, record
):
727 def merge(vector
, value
, span
, spec
, spec_span
):
728 # this is silly these should be in a general base class,
729 # settable by constructor
730 sshift
= 3 # len(value) aka value.bits
731 vshift
= 4 # 7-sshift
732 spshft
= 2 # 5-sshift
733 lsbshf
= 2 # has to be set as a parameter
734 lsbmsk
= (1<<lsbshf
)-1
735 # record the 2 lsbs first
736 lsbs
= _SelectableInt(value
=value
.value
&(lsbmsk
), bits
=lsbshf
)
737 bits
= (len(span
) + len(spec_span
))
738 #print ("value", bin(value.value), value.bits)
739 value
= _SelectableInt(value
=value
.value
>>lsbshf
, bits
=bits
)
740 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
741 #print ("spec", bin(spec.value), spec.bits)
742 #print ("value", bin(value.value), value.bits)
743 #print ("lsbs", bin(lsbs.value), lsbs.bits)
745 value
= ((value
<< vshift
) |
(spec
<<spshft
))
746 span
= (span
[0:3] + spec_span
+ spshft
*('{0}',) + span
[3:5])
748 value
= ((spec
<< sshift
) | value
)
749 span
= (spshft
*('{0}',) + spec_span
+ span
)
751 # add the 2 LSBs back in
752 v
= (value
.value
<<lsbshf
)+lsbs
.value
753 res
= _SelectableInt(value
=v
, bits
=bits
+lsbshf
)
754 #print ("after", bin(value.value), value.bits)
755 #print ("res", bin(res.value), res.bits)
758 return super().spec(insn
=insn
, record
=record
, merge
=merge
)
761 # this is silly, all of these should be the same base class
762 class DynamicOperandCR(RegisterOperand
):
763 def spec(self
, insn
, record
):
764 def merge(vector
, value
, span
, spec
, spec_span
):
765 bits
= (len(span
) + len(spec_span
))
766 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
767 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
772 (value
, span
, (0, 1, 2)),
773 (spec
, spec_span
, (0, 1)),
774 (value
, span
, (3, 4)),
778 _SelectableInt(value
=0, bits
=1),
779 _SelectableInt(value
=0, bits
=1),
781 dst_span
= ["{0}", "{0}"]
783 (spec
, spec_span
, (0, 1)),
784 (value
, span
, (0, 1, 2, 3, 4)),
787 for (src_value
, src_span
, sel
) in table
:
789 dst_value
.append(src_value
[idx
])
790 dst_span
.append(src_span
[idx
])
792 value
= _selectconcat(dst_value
)
793 span
= tuple(dst_span
)
797 return super().spec(insn
=insn
, record
=record
, merge
=merge
)
799 def disassemble(self
, insn
, record
, verbose
=False, indent
=""):
800 yield from super().disassemble(prefix
="cr",
801 insn
=insn
, record
=record
, verbose
=verbose
, indent
=indent
)
804 class TargetAddrOperand(RegisterOperand
):
805 def disassemble(self
, insn
, record
, field
,
806 verbosity
=Verbosity
.NORMAL
, indent
=""):
807 span
= self
.span(record
=record
)
808 if isinstance(insn
, SVP64Instruction
):
809 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
812 if verbosity
>= Verbosity
.VERBOSE
:
813 span
= tuple(map(str, span
))
814 yield f
"{indent}{self.name} = EXTS({field} || 0b00))"
815 yield f
"{indent}{indent}{field}"
816 yield f
"{indent}{indent}{indent}{int(value):0{value.bits}b}00"
817 yield f
"{indent}{indent}{indent}{', '.join(span + ('{0}', '{0}'))}"
819 yield hex(int(_selectconcat(value
,
820 _SelectableInt(value
=0b00, bits
=2))))
823 class TargetAddrOperandLI(TargetAddrOperand
):
824 def span(self
, record
):
825 return record
.fields
["LI"]
827 def disassemble(self
, insn
, record
,
828 verbosity
=Verbosity
.NORMAL
, indent
=""):
829 return super().disassemble(field
="LI",
830 insn
=insn
, record
=record
,
831 verbosity
=verbosity
, indent
=indent
)
834 class TargetAddrOperandBD(TargetAddrOperand
):
835 def span(self
, record
):
836 return record
.fields
["BD"]
838 def disassemble(self
, insn
, record
,
839 verbosity
=Verbosity
.NORMAL
, indent
=""):
840 return super().disassemble(field
="BD",
841 insn
=insn
, record
=record
,
842 verbosity
=verbosity
, indent
=indent
)
845 class DOperandDX(DynamicOperand
):
846 def span(self
, record
):
847 operands
= map(DynamicOperand
, ("d0", "d1", "d2"))
848 spans
= map(lambda operand
: operand
.span(record
=record
), operands
)
849 return sum(spans
, tuple())
851 def disassemble(self
, insn
, record
,
852 verbosity
=Verbosity
.NORMAL
, indent
=""):
853 span
= self
.span(record
=record
)
854 if isinstance(insn
, SVP64Instruction
):
855 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
858 if verbosity
>= Verbosity
.VERBOSE
:
865 for (subname
, subspan
) in mapping
.items():
866 operand
= DynamicOperand(name
=subname
)
867 span
= operand
.span(record
=record
)
868 if isinstance(insn
, SVP64Instruction
):
869 span
= tuple(map(lambda bit
: (bit
+ 32), span
))
871 span
= map(str, span
)
872 yield f
"{indent}{indent}{operand.name} = D{subspan}"
873 yield f
"{indent}{indent}{indent}{int(value):0{value.bits}b}"
874 yield f
"{indent}{indent}{indent}{', '.join(span)}"
876 yield str(int(value
))
879 class Operands(tuple):
880 def __new__(cls
, insn
, iterable
):
882 "b": {"target_addr": TargetAddrOperandLI
},
883 "ba": {"target_addr": TargetAddrOperandLI
},
884 "bl": {"target_addr": TargetAddrOperandLI
},
885 "bla": {"target_addr": TargetAddrOperandLI
},
886 "bc": {"target_addr": TargetAddrOperandBD
},
887 "bca": {"target_addr": TargetAddrOperandBD
},
888 "bcl": {"target_addr": TargetAddrOperandBD
},
889 "bcla": {"target_addr": TargetAddrOperandBD
},
890 "addpcis": {"D": DOperandDX
},
891 "fishmv": {"D": DOperandDX
},
892 "fmvis": {"D": DOperandDX
},
895 "SVi": NonZeroOperand
,
896 "SVd": NonZeroOperand
,
897 "SVxd": NonZeroOperand
,
898 "SVyd": NonZeroOperand
,
899 "SVzd": NonZeroOperand
,
903 for operand
in iterable
:
904 dynamic_cls
= DynamicOperand
905 static_cls
= StaticOperand
908 (name
, value
) = operand
.split("=")
909 operand
= static_cls(name
=name
, value
=int(value
))
910 operands
.append(operand
)
912 if operand
.endswith(")"):
913 operand
= operand
.replace("(", " ").replace(")", "")
914 (immediate
, _
, operand
) = operand
.partition(" ")
918 if immediate
is not None:
919 operands
.append(ImmediateOperand(name
=immediate
))
921 if insn
in custom_insns
and operand
in custom_insns
[insn
]:
922 dynamic_cls
= custom_insns
[insn
][operand
]
923 if operand
in custom_fields
:
924 dynamic_cls
= custom_fields
[operand
]
926 if operand
in _RegType
.__members
__:
927 regtype
= _RegType
[operand
]
928 if regtype
is _RegType
.GPR
:
929 dynamic_cls
= GPROperand
930 elif regtype
is _RegType
.FPR
:
931 dynamic_cls
= FPROperand
932 if regtype
is _RegType
.CR_BIT
: # 5-bit
933 dynamic_cls
= CR5Operand
934 if regtype
is _RegType
.CR_REG
: # actually CR Field, 3-bit
935 dynamic_cls
= CR3Operand
937 operand
= dynamic_cls(name
=operand
)
938 operands
.append(operand
)
940 return super().__new
__(cls
, operands
)
942 def __contains__(self
, key
):
943 return self
.__getitem
__(key
) is not None
945 def __getitem__(self
, key
):
947 if operand
.name
== key
:
955 if isinstance(operand
, DynamicOperand
):
961 if isinstance(operand
, StaticOperand
):
966 def __init__(self
, iterable
):
967 self
.__pcode
= tuple(iterable
)
968 return super().__init
__()
971 yield from self
.__pcode
974 return self
.__pcode
.__repr
__()
977 @_dataclasses.dataclass(eq
=True, frozen
=True)
978 class MarkdownRecord
:
983 @_functools.total_ordering
984 @_dataclasses.dataclass(eq
=True, frozen
=True)
991 svp64
: SVP64Record
= None
993 def __lt__(self
, other
):
994 if not isinstance(other
, Record
):
995 return NotImplemented
996 return (min(self
.opcodes
) < min(other
.opcodes
))
1004 PO
= self
.section
.opcode
1006 for (src
, dst
) in enumerate(reversed(BitSel((0, 5)))):
1007 value
[dst
] = int((PO
.value
& (1 << src
)) != 0)
1008 mask
[dst
] = int((PO
.mask
& (1 << src
)) != 0)
1011 for (src
, dst
) in enumerate(reversed(self
.section
.bitsel
)):
1012 value
[dst
] = int((XO
.value
& (1 << src
)) != 0)
1013 mask
[dst
] = int((XO
.mask
& (1 << src
)) != 0)
1015 for operand
in self
.mdwn
.operands
.static
:
1016 for (src
, dst
) in enumerate(reversed(operand
.span(record
=self
))):
1017 value
[dst
] = int((operand
.value
& (1 << src
)) != 0)
1020 value
= Opcode
.Value(int(("".join(map(str, value
))), 2))
1021 mask
= Opcode
.Mask(int(("".join(map(str, mask
))), 2))
1023 return Opcode(value
=value
, mask
=mask
)
1025 return tuple(sorted(map(opcode
, self
.ppc
)))
1027 def match(self
, key
):
1028 for opcode
in self
.opcodes
:
1029 if ((opcode
.value
& opcode
.mask
) ==
1030 (key
& opcode
.mask
)):
1036 return self
.ppc
.function
1056 if self
.svp64
is None:
1062 return self
.ppc
.cr_in
1066 return self
.ppc
.cr_out
1068 ptype
= property(lambda self
: self
.svp64
.ptype
)
1069 etype
= property(lambda self
: self
.svp64
.etype
)
1071 def extra_idx(self
, key
):
1072 return self
.svp64
.extra_idx(key
)
1074 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
1075 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
1076 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
1077 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
1078 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
1079 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
1080 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
1083 class Instruction(_Mapping
):
1085 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1086 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1087 raise ValueError(bits
)
1089 if isinstance(value
, bytes
):
1090 if ((len(value
) * 8) != bits
):
1091 raise ValueError(f
"bit length mismatch")
1092 value
= int.from_bytes(value
, byteorder
=byteorder
)
1094 if isinstance(value
, int):
1095 value
= _SelectableInt(value
=value
, bits
=bits
)
1096 elif isinstance(value
, Instruction
):
1097 value
= value
.storage
1099 if not isinstance(value
, _SelectableInt
):
1100 raise ValueError(value
)
1103 if len(value
) != bits
:
1104 raise ValueError(value
)
1106 value
= _SelectableInt(value
=value
, bits
=bits
)
1108 return cls(storage
=value
)
1111 return hash(int(self
))
1113 def record(self
, db
):
1116 raise KeyError(self
)
1119 def spec(self
, db
, prefix
):
1120 record
= self
.record(db
=db
)
1122 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1123 self
.dynamic_operands(db
=db
)))
1125 static_operands
= []
1126 for (name
, value
) in self
.static_operands(db
=db
):
1127 static_operands
.append(f
"{name}={value}")
1130 if dynamic_operands
:
1131 operands
+= f
" {','.join(dynamic_operands)}"
1133 operands
+= f
" ({' '.join(static_operands)})"
1135 return f
"{prefix}{record.name}{operands}"
1137 def dynamic_operands(self
, db
, verbosity
=Verbosity
.NORMAL
):
1138 record
= self
.record(db
=db
)
1143 for operand
in record
.mdwn
.operands
.dynamic
:
1145 dis
= operand
.disassemble(insn
=self
, record
=record
,
1146 verbosity
=min(verbosity
, Verbosity
.NORMAL
))
1147 value
= " ".join(dis
)
1149 name
= f
"{imm_name}({name})"
1150 value
= f
"{imm_value}({value})"
1152 if isinstance(operand
, ImmediateOperand
):
1159 def static_operands(self
, db
):
1160 record
= self
.record(db
=db
)
1161 for operand
in record
.mdwn
.operands
.static
:
1162 yield (operand
.name
, operand
.value
)
1164 def disassemble(self
, db
,
1166 verbosity
=Verbosity
.NORMAL
):
1167 raise NotImplementedError
1170 class WordInstruction(Instruction
):
1171 _
: _Field
= range(0, 32)
1172 po
: _Field
= range(0, 6)
1175 def integer(cls
, value
, byteorder
="little"):
1176 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1181 for idx
in range(32):
1182 bit
= int(self
[idx
])
1184 return "".join(map(str, bits
))
1186 def disassemble(self
, db
,
1188 verbosity
=Verbosity
.NORMAL
):
1190 if verbosity
<= Verbosity
.SHORT
:
1193 blob
= integer
.to_bytes(length
=4, byteorder
=byteorder
)
1194 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1199 yield f
"{blob}.long 0x{integer:08x}"
1202 operands
= tuple(map(_operator
.itemgetter(1),
1203 self
.dynamic_operands(db
=db
, verbosity
=verbosity
)))
1205 yield f
"{blob}{record.name} {','.join(operands)}"
1207 yield f
"{blob}{record.name}"
1209 if verbosity
>= Verbosity
.VERBOSE
:
1211 binary
= self
.binary
1212 spec
= self
.spec(db
=db
, prefix
="")
1213 yield f
"{indent}spec"
1214 yield f
"{indent}{indent}{spec}"
1215 yield f
"{indent}pcode"
1216 for stmt
in record
.mdwn
.pcode
:
1217 yield f
"{indent}{indent}{stmt}"
1218 yield f
"{indent}binary"
1219 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1220 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1221 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1222 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1223 yield f
"{indent}opcodes"
1224 for opcode
in record
.opcodes
:
1225 yield f
"{indent}{indent}{opcode!r}"
1226 for operand
in record
.mdwn
.operands
:
1227 yield from operand
.disassemble(insn
=self
, record
=record
,
1228 verbosity
=verbosity
, indent
=indent
)
1232 class PrefixedInstruction(Instruction
):
1233 class Prefix(WordInstruction
.remap(range(0, 32))):
1236 class Suffix(WordInstruction
.remap(range(32, 64))):
1239 _
: _Field
= range(64)
1245 def integer(cls
, value
, byteorder
="little"):
1246 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
1249 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
1250 def transform(value
):
1251 return WordInstruction
.integer(value
=value
,
1252 byteorder
=byteorder
)[0:32]
1254 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
1255 value
= _selectconcat(prefix
, suffix
)
1257 return super().integer(value
=value
)
1260 class Mode(_Mapping
):
1261 _
: _Field
= range(0, 5)
1262 sel
: _Field
= range(0, 2)
1265 class NormalMode(Mode
):
1272 """scalar reduce mode (mapreduce), SUBVL=1"""
1276 """parallel reduce mode (mapreduce), SUBVL=1"""
1280 """subvector reduce mode, SUBVL>1"""
1284 """Pack/Unpack mode, SUBVL>1"""
1288 """Rc=1: ffirst CR sel"""
1293 """Rc=0: ffirst z/nonz"""
1299 """sat mode: N=0/1 u/s, SUBVL=1"""
1305 """sat mode: N=0/1 u/s, SUBVL>1"""
1312 """Pack/Unpack sat mode: N=0/1 u/s, SUBVL>1"""
1319 """Rc=1: pred-result CR sel"""
1324 """Rc=0: pred-result z/nonz"""
1345 class LDSTImmMode(Mode
):
1354 """Structured Pack/Unpack"""
1361 """Rc=1: ffirst CR sel"""
1366 """Rc=0: ffirst z/nonz"""
1372 """sat mode: N=0/1 u/s"""
1380 """Rc=1: pred-result CR sel"""
1385 """Rc=0: pred-result z/nonz"""
1399 class LDSTIdxMode(Mode
):
1407 """strided (scalar only source)"""
1413 """sat mode: N=0/1 u/s"""
1419 """Rc=1: pred-result CR sel"""
1424 """Rc=0: pred-result z/nonz"""
1438 class Extra(_Mapping
):
1439 _
: _Field
= range(0, 9)
1442 class Extra2(Extra
):
1443 idx0
: _Field
= range(0, 2)
1444 idx1
: _Field
= range(2, 4)
1445 idx2
: _Field
= range(4, 6)
1446 idx3
: _Field
= range(6, 8)
1448 def __getitem__(self
, key
):
1454 _SVExtra
.Idx0
: self
.idx0
,
1455 _SVExtra
.Idx1
: self
.idx1
,
1456 _SVExtra
.Idx2
: self
.idx2
,
1457 _SVExtra
.Idx3
: self
.idx3
,
1460 def __setitem__(self
, key
, value
):
1461 self
[key
].assign(value
)
1464 class Extra3(Extra
):
1465 idx0
: _Field
= range(0, 3)
1466 idx1
: _Field
= range(3, 6)
1467 idx2
: _Field
= range(6, 9)
1469 def __getitem__(self
, key
):
1474 _SVExtra
.Idx0
: self
.idx0
,
1475 _SVExtra
.Idx1
: self
.idx1
,
1476 _SVExtra
.Idx2
: self
.idx2
,
1479 def __setitem__(self
, key
, value
):
1480 self
[key
].assign(value
)
1486 ldst_imm
: LDSTImmMode
1487 ldst_idx
: LDSTIdxMode
1489 _
: _Field
= range(24)
1490 mmode
: _Field
= (0,)
1491 mask
: _Field
= range(1, 4)
1492 elwidth
: _Field
= range(4, 6)
1493 ewsrc
: _Field
= range(6, 8)
1494 subvl
: _Field
= range(8, 10)
1495 mode
: Mode
.remap(range(19, 24))
1496 smask
: _Field
= range(16, 19)
1498 extra
: Extra
.remap(range(10, 19))
1499 extra2
: Extra2
.remap(range(10, 19))
1500 extra3
: Extra3
.remap(range(10, 19))
1503 class SVP64Instruction(PrefixedInstruction
):
1504 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
1505 class Prefix(PrefixedInstruction
.Prefix
):
1507 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
1511 def record(self
, db
):
1512 record
= db
[self
.suffix
]
1514 raise KeyError(self
)
1520 for idx
in range(64):
1521 bit
= int(self
[idx
])
1523 return "".join(map(str, bits
))
1526 record
= self
.record(db
=db
)
1529 if record
.mdwn
.operands
["Rc"] is not None:
1530 Rc
= bool(self
[record
.fields
["Rc"]])
1532 record
= self
.record(db
=db
)
1533 subvl
= self
.prefix
.rm
.subvl
1534 mode
= self
.prefix
.rm
.mode
1537 if record
.svp64
.mode
is _SVMode
.NORMAL
:
1571 elif record
.svp64
.mode
is _SVMode
.LDST_IMM
:
1572 mode
= mode
.ldst_imm
1590 elif record
.svp64
.mode
is _SVMode
.LDST_IMM
:
1591 mode
= mode
.ldst_idx
1592 if mode
.sel
== 0b00:
1594 elif mode
.sel
== 0b01:
1596 elif mode
.sel
== 0b10:
1598 elif mode
.sel
== 0b11:
1605 NormalMode
.simple
: "normal: simple",
1606 NormalMode
.smr
: "normal: smr",
1607 NormalMode
.pmr
: "normal: pmr",
1608 NormalMode
.svmr
: "normal: svmr",
1609 NormalMode
.pu
: "normal: pu",
1610 NormalMode
.ffrc1
: "normal: ffrc1",
1611 NormalMode
.ffrc0
: "normal: ffrc0",
1612 NormalMode
.sat
: "normal: sat",
1613 NormalMode
.satx
: "normal: satx",
1614 NormalMode
.satpu
: "normal: satpu",
1615 NormalMode
.prrc1
: "normal: prrc1",
1616 NormalMode
.prrc0
: "normal: prrc0",
1617 LDSTImmMode
.simple
: "ld/st imm: simple",
1618 LDSTImmMode
.spu
: "ld/st imm: spu",
1619 LDSTImmMode
.ffrc1
: "ld/st imm: ffrc1",
1620 LDSTImmMode
.ffrc0
: "ld/st imm: ffrc0",
1621 LDSTImmMode
.sat
: "ld/st imm: sat",
1622 LDSTImmMode
.prrc1
: "ld/st imm: prrc1",
1623 LDSTImmMode
.prrc0
: "ld/st imm: prrc0",
1624 LDSTIdxMode
.simple
: "ld/st idx simple",
1625 LDSTIdxMode
.stride
: "ld/st idx stride",
1626 LDSTIdxMode
.sat
: "ld/st idx sat",
1627 LDSTIdxMode
.prrc1
: "ld/st idx prrc1",
1628 LDSTIdxMode
.prrc0
: "ld/st idx prrc0",
1630 for (cls
, desc
) in modes
.items():
1631 if isinstance(mode
, cls
):
1634 if record
.svp64
.mode
is _SVMode
.BRANCH
:
1635 return (self
.prefix
.rm
.mode
, "branch")
1637 raise ValueError(self
)
1639 def disassemble(self
, db
,
1641 verbosity
=Verbosity
.NORMAL
):
1643 if verbosity
<= Verbosity
.SHORT
:
1646 blob
= integer
.to_bytes(length
=4, byteorder
=byteorder
)
1647 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1650 blob_prefix
= blob(int(self
.prefix
))
1651 blob_suffix
= blob(int(self
.suffix
))
1653 if record
is None or record
.svp64
is None:
1654 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
1655 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
1658 operands
= tuple(map(_operator
.itemgetter(1),
1659 self
.dynamic_operands(db
=db
, verbosity
=verbosity
)))
1661 yield f
"{blob_prefix}sv.{record.name} {','.join(operands)}"
1663 yield f
"{blob_prefix}{record.name}"
1665 yield f
"{blob_suffix}"
1667 (mode
, mode_desc
) = self
.mode(db
=db
)
1669 if verbosity
>= Verbosity
.VERBOSE
:
1671 binary
= self
.binary
1672 spec
= self
.spec(db
=db
, prefix
="sv.")
1673 yield f
"{indent}spec"
1674 yield f
"{indent}{indent}{spec}"
1675 yield f
"{indent}pcode"
1676 for stmt
in record
.mdwn
.pcode
:
1677 yield f
"{indent}{indent}{stmt}"
1678 yield f
"{indent}binary"
1679 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
1680 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
1681 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
1682 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
1683 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
1684 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
1685 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
1686 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
1687 yield f
"{indent}opcodes"
1688 for opcode
in record
.opcodes
:
1689 yield f
"{indent}{indent}{opcode!r}"
1690 for operand
in record
.mdwn
.operands
:
1691 yield from operand
.disassemble(insn
=self
, record
=record
,
1692 verbosity
=verbosity
, indent
=indent
)
1694 yield f
"{indent}mode"
1695 yield f
"{indent}{indent}{mode_desc}"
1699 def parse(stream
, factory
):
1701 return ("TODO" not in frozenset(entry
.values()))
1703 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
1704 entries
= _csv
.DictReader(lines
)
1705 entries
= filter(match
, entries
)
1706 return tuple(map(factory
, entries
))
1709 class MarkdownDatabase
:
1712 for (name
, desc
) in _ISA():
1715 (dynamic
, *static
) = desc
.regs
1716 operands
.extend(dynamic
)
1717 operands
.extend(static
)
1718 pcode
= PCode(iterable
=desc
.pcode
)
1719 operands
= Operands(insn
=name
, iterable
=operands
)
1720 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
1724 return super().__init
__()
1727 yield from self
.__db
.items()
1729 def __getitem__(self
, key
):
1730 return self
.__db
.__getitem
__(key
)
1733 class FieldsDatabase
:
1736 df
= _DecodeFields()
1738 for (form
, fields
) in df
.instrs
.items():
1739 if form
in {"DQE", "TX"}:
1743 db
[_Form
[form
]] = Fields(fields
)
1747 return super().__init
__()
1749 def __getitem__(self
, key
):
1750 return self
.__db
.__getitem
__(key
)
1754 def __init__(self
, root
, mdwndb
):
1755 # The code below groups the instructions by section:identifier.
1756 # We use the comment as an identifier, there's nothing better.
1757 # The point is to capture different opcodes for the same instruction.
1758 dd
= _collections
.defaultdict
1759 records
= dd(lambda: dd(set))
1760 path
= (root
/ "insndb.csv")
1761 with
open(path
, "r", encoding
="UTF-8") as stream
:
1762 for section
in parse(stream
, Section
.CSV
):
1763 path
= (root
/ section
.path
)
1765 section
.Mode
.INTEGER
: IntegerOpcode
,
1766 section
.Mode
.PATTERN
: PatternOpcode
,
1768 factory
= _functools
.partial(
1769 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
1770 with
open(path
, "r", encoding
="UTF-8") as stream
:
1771 for insn
in parse(stream
, factory
):
1772 records
[section
][insn
.comment
].add(insn
)
1775 for (section
, group
) in records
.items():
1776 for records
in group
.values():
1777 db
[section
].add(PPCMultiRecord(records
))
1780 self
.__mdwndb
= mdwndb
1782 return super().__init
__()
1784 def __getitem__(self
, key
):
1785 def exact_match(key
, record
):
1786 for name
in record
.names
:
1792 def Rc_match(key
, record
):
1793 if not key
.endswith("."):
1796 if not record
.Rc
is _RCOE
.RC
:
1799 return exact_match(key
[:-1], record
)
1801 def LK_match(key
, record
):
1802 if not key
.endswith("l"):
1805 if "lk" not in record
.flags
:
1808 return exact_match(key
[:-1], record
)
1810 def AA_match(key
, record
):
1811 if not key
.endswith("a"):
1814 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
1817 if self
.__mdwndb
[key
].operands
["AA"] is None:
1820 return (exact_match(key
[:-1], record
) or
1821 LK_match(key
[:-1], record
))
1823 for (section
, records
) in self
.__db
.items():
1824 for record
in records
:
1825 if exact_match(key
, record
):
1826 return (section
, record
)
1828 for record
in records
:
1829 if (Rc_match(key
, record
) or
1830 LK_match(key
, record
) or
1831 AA_match(key
, record
)):
1832 return (section
, record
)
1837 class SVP64Database
:
1838 def __init__(self
, root
, ppcdb
):
1840 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
1841 for (prefix
, _
, names
) in _os
.walk(root
):
1842 prefix
= _pathlib
.Path(prefix
)
1843 for name
in filter(lambda name
: pattern
.match(name
), names
):
1844 path
= (prefix
/ _pathlib
.Path(name
))
1845 with
open(path
, "r", encoding
="UTF-8") as stream
:
1846 db
.update(parse(stream
, SVP64Record
.CSV
))
1848 self
.__db
= {record
.name
:record
for record
in db
}
1849 self
.__ppcdb
= ppcdb
1851 return super().__init
__()
1853 def __getitem__(self
, key
):
1854 (_
, record
) = self
.__ppcdb
[key
]
1858 for name
in record
.names
:
1859 record
= self
.__db
.get(name
, None)
1860 if record
is not None:
1867 def __init__(self
, root
):
1868 root
= _pathlib
.Path(root
)
1869 mdwndb
= MarkdownDatabase()
1870 fieldsdb
= FieldsDatabase()
1871 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
1872 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
1876 opcodes
= _collections
.defaultdict(set)
1878 for (name
, mdwn
) in mdwndb
:
1879 (section
, ppc
) = ppcdb
[name
]
1882 svp64
= svp64db
[name
]
1883 fields
= fieldsdb
[ppc
.form
]
1884 record
= Record(name
=name
,
1885 section
=section
, ppc
=ppc
, svp64
=svp64
,
1886 mdwn
=mdwn
, fields
=fields
)
1888 names
[record
.name
] = record
1892 opcodes
[PO
.value
].add(record
)
1895 self
.__names
= names
1896 self
.__opcodes
= opcodes
1898 return super().__init
__()
1901 return repr(self
.__db
)
1904 yield from self
.__db
1906 @_functools.lru_cache(maxsize
=None)
1907 def __contains__(self
, key
):
1908 return self
.__getitem
__(key
) is not None
1910 @_functools.lru_cache(maxsize
=None)
1911 def __getitem__(self
, key
):
1912 if isinstance(key
, (int, Instruction
)):
1914 XO
= int(_SelectableInt(value
=int(key
), bits
=32)[0:6])
1915 for record
in self
.__opcodes
[XO
]:
1916 if record
.match(key
=key
):
1919 elif isinstance(key
, str):
1920 return record
.__names
[key
]