power_fields: restore class-oriented traversal
[openpower-isa.git] / src / openpower / decoder / power_insn.py
index 732a06cd2da8efe72a7fec1ca7f887799e3be4c4..c1fb4a2fcf6047f92b555ae08bdb15424e01bbbf 100644 (file)
@@ -30,6 +30,7 @@ from openpower.decoder.power_enums import (
     CryIn as _CryIn,
     Form as _Form,
     SVEtype as _SVEtype,
+    SVmask_src as _SVmask_src,
     SVMode as _SVMode,
     SVPtype as _SVPtype,
     SVExtra as _SVExtra,
@@ -308,6 +309,7 @@ class SVP64Record:
     name: str
     ptype: _SVPtype = _SVPtype.NONE
     etype: _SVEtype = _SVEtype.NONE
+    msrc: _SVmask_src = _SVmask_src.NO # MASK_SRC is active
     in1: _In1Sel = _In1Sel.NONE
     in2: _In2Sel = _In2Sel.NONE
     in3: _In3Sel = _In3Sel.NONE
@@ -325,6 +327,7 @@ class SVP64Record:
         "CONDITIONS": "conditions",
         "Ptype": "ptype",
         "Etype": "etype",
+        "SM": "msrc",
         "CR in": "cr_in",
         "CR out": "cr_out",
     }
@@ -418,7 +421,7 @@ class BitSel:
             (start, end) = value
         if start < 0 or end < 0 or start >= end:
             raise ValueError(value)
-        
+
         self.__start = start
         self.__end = end
 
@@ -542,6 +545,23 @@ class DynamicOperand(Operand):
             yield str(int(value))
 
 
+class SignedOperand(DynamicOperand):
+    def disassemble(self, insn, record,
+            verbosity=Verbosity.NORMAL, indent=""):
+        span = self.span(record=record)
+        if isinstance(insn, SVP64Instruction):
+            span = tuple(map(lambda bit: (bit + 32), span))
+        value = insn[span]
+
+        if verbosity >= Verbosity.VERBOSE:
+            span = map(str, span)
+            yield f"{indent}{self.name}"
+            yield f"{indent}{indent}{int(value):0{value.bits}b}"
+            yield f"{indent}{indent}{', '.join(span)}"
+        else:
+            yield str(value.to_signed_int())
+
+
 @_dataclasses.dataclass(eq=True, frozen=True)
 class StaticOperand(Operand):
     value: int
@@ -639,10 +659,10 @@ class RegisterOperand(DynamicOperand):
                 spec = _SelectableInt(value=spec.value, bits=bits)
                 if vector:
                     value = ((value << vector_shift) | (spec << spec_shift))
-                    span = (span + spec_span + ((spec_shift * ('{0}',))))
+                    span = (span + spec_span + ((spec_shift * ("{0}",))))
                 else:
                     value = ((spec << scalar_shift) | value)
-                    span = ((spec_shift * ('{0}',)) + spec_span + span)
+                    span = ((spec_shift * ("{0}",)) + spec_span + span)
 
             (value, span) = self.sv_spec_leave(value=value, span=span,
                 origin_value=origin_value, origin_span=origin_span)
@@ -727,14 +747,14 @@ class TargetAddrOperand(RegisterOperand):
         value = insn[span]
 
         if verbosity >= Verbosity.VERBOSE:
-            span = tuple(map(str, span))
+            span = (tuple(map(str, span)) + ("{0}", "{0}"))
             yield f"{indent}{self.name} = EXTS({field} || 0b00))"
             yield f"{indent}{indent}{field}"
             yield f"{indent}{indent}{indent}{int(value):0{value.bits}b}00"
-            yield f"{indent}{indent}{indent}{', '.join(span + ('{0}', '{0}'))}"
+            yield f"{indent}{indent}{indent}{', '.join(span)}"
         else:
-            yield hex(int(_selectconcat(value,
-                _SelectableInt(value=0b00, bits=2))))
+            yield hex(_selectconcat(value,
+                _SelectableInt(value=0b00, bits=2)).to_signed_int())
 
 
 class TargetAddrOperandLI(TargetAddrOperand):
@@ -759,7 +779,7 @@ class TargetAddrOperandBD(TargetAddrOperand):
             verbosity=verbosity, indent=indent)
 
 
-class DOperandDX(DynamicOperand):
+class DOperandDX(SignedOperand):
     def span(self, record):
         operands = map(DynamicOperand, ("d0", "d1", "d2"))
         spans = map(lambda operand: operand.span(record=record), operands)
@@ -790,7 +810,7 @@ class DOperandDX(DynamicOperand):
                 yield f"{indent}{indent}{indent}{int(value):0{value.bits}b}"
                 yield f"{indent}{indent}{indent}{', '.join(span)}"
         else:
-            yield str(int(value))
+            yield str(value.to_signed_int())
 
 
 class Operands(tuple):
@@ -814,6 +834,16 @@ class Operands(tuple):
             "SVxd": NonZeroOperand,
             "SVyd": NonZeroOperand,
             "SVzd": NonZeroOperand,
+            "BD": SignedOperand,
+            "D": SignedOperand,
+            "DQ": SignedOperand,
+            "DS": SignedOperand,
+            "SI": SignedOperand,
+            "IB": SignedOperand,
+            "LI": SignedOperand,
+            "SIM": SignedOperand,
+            "SVD": SignedOperand,
+            "SVDS": SignedOperand,
         }
 
         operands = []
@@ -835,10 +865,10 @@ class Operands(tuple):
                 if immediate is not None:
                     operands.append(ImmediateOperand(name=immediate))
 
-                if insn in custom_insns and operand in custom_insns[insn]:
-                    dynamic_cls = custom_insns[insn][operand]
                 if operand in custom_fields:
                     dynamic_cls = custom_fields[operand]
+                if insn in custom_insns and operand in custom_insns[insn]:
+                    dynamic_cls = custom_insns[insn][operand]
 
                 if operand in _RegType.__members__:
                     regtype = _RegType[operand]
@@ -1031,6 +1061,16 @@ class Instruction(_Mapping):
     def __hash__(self):
         return hash(int(self))
 
+    def __getitem__(self, key):
+        return self.storage.__getitem__(key)
+
+    def __setitem__(self, key, value):
+        return self.storage.__setitem__(key, value)
+
+    def bytes(self, byteorder="little"):
+        nr_bytes = (self.storage.bits // 8)
+        return int(self).to_bytes(nr_bytes, byteorder=byteorder)
+
     def record(self, db):
         record = db[self]
         if record is None:
@@ -1049,9 +1089,11 @@ class Instruction(_Mapping):
 
         operands = ""
         if dynamic_operands:
-            operands += f" {','.join(dynamic_operands)}"
+            operands += " "
+            operands += ",".join(dynamic_operands)
         if static_operands:
-            operands += f" ({' '.join(static_operands)})"
+            operands += " "
+            operands += " ".join(static_operands)
 
         return f"{prefix}{record.name}{operands}"
 
@@ -1123,7 +1165,8 @@ class WordInstruction(Instruction):
         operands = tuple(map(_operator.itemgetter(1),
             self.dynamic_operands(db=db, verbosity=verbosity)))
         if operands:
-            yield f"{blob}{record.name} {','.join(operands)}"
+            operands = ",".join(operands)
+            yield f"{blob}{record.name} {operands}"
         else:
             yield f"{blob}{record.name}"
 
@@ -1175,7 +1218,7 @@ class PrefixedInstruction(Instruction):
         (prefix, suffix) = map(transform, (prefix, suffix))
         value = _selectconcat(prefix, suffix)
 
-        return super().integer(value=value)
+        return super().integer(bits=64, value=value)
 
 
 class Mode(_Mapping):
@@ -1236,244 +1279,465 @@ class BaseRM(_Mapping):
     subvl: _Field = range(8, 10)
     mode: Mode.remap(range(19, 24))
     smask: _Field = range(16, 19)
-
     extra: Extra.remap(range(10, 19))
     extra2: Extra2.remap(range(10, 19))
     extra3: Extra3.remap(range(10, 19))
 
+    def specifiers(self, record):
+        subvl = int(self.subvl)
+        if subvl > 0:
+            yield {
+                1: "vec2",
+                2: "vec3",
+                3: "vec4",
+            }[subvl]
+
+    def disassemble(self, verbosity=Verbosity.NORMAL):
+        if verbosity >= Verbosity.VERBOSE:
+            indent = (" " * 4)
+            for (name, span) in self.traverse(path="RM"):
+                value = self.storage[span]
+                yield f"{name}"
+                yield f"{indent}{int(value):0{value.bits}b}"
+                yield f"{indent}{', '.join(map(str, span))}"
+
 
-class NormalRM(BaseRM):
-    class simple(BaseRM):
-        """simple mode"""
-        dz: BaseRM.mode[3]
-        sz: BaseRM.mode[4]
+class FFPRRc1BaseRM(BaseRM):
+    def specifiers(self, record, mode):
+        inv = _SelectableInt(value=int(self.inv), bits=1)
+        CR = _SelectableInt(value=int(self.CR), bits=2)
+        mask = int(_selectconcat(CR, inv))
+        predicate = PredicateBaseRM.predicate(True, mask)
+        yield f"{mode}={predicate}"
 
-    class smr(Mode):
-        """scalar reduce mode (mapreduce), SUBVL=1"""
-        RG: BaseRM.mode[4]
+        yield from super().specifiers(record=record)
+
+
+class FFPRRc0BaseRM(BaseRM):
+    def specifiers(self, record, mode):
+        if self.RC1:
+            inv = "~" if self.inv else ""
+            yield f"{mode}={inv}RC1"
+
+        yield from super().specifiers(record=record)
+
+
+class SatBaseRM(BaseRM):
+    def specifiers(self, record):
+        if self.N:
+            yield "sats"
+        else:
+            yield "satu"
+
+        yield from super().specifiers(record=record)
+
+
+class ZZBaseRM(BaseRM):
+    def specifiers(self, record):
+        if self.zz:
+            yield "zz"
+
+        yield from super().specifiers(record=record)
+
+
+class DZBaseRM(BaseRM):
+    def specifiers(self, record):
+        if self.dz:
+            yield "dz"
+
+        yield from super().specifiers(record=record)
+
+
+class SZBaseRM(BaseRM):
+    def specifiers(self, record):
+        if self.sz:
+            yield "sz"
+
+        yield from super().specifiers(record=record)
+
+
+class MRBaseRM(BaseRM):
+    def specifiers(self, record):
+        if self.RG:
+            yield "mrr"
+        else:
+            yield "mr"
+
+        yield from super().specifiers(record=record)
+
+
+class ElsBaseRM(BaseRM):
+    def specifiers(self, record):
+        if self.els:
+            yield "els"
+
+        yield from super().specifiers(record=record)
+
+
+class WidthBaseRM(BaseRM):
+    @staticmethod
+    def width(FP, width):
+        width = {
+            0b11: "8",
+            0b10: "16",
+            0b01: "32",
+        }.get(width)
+        if width is None:
+            return None
+        if FP:
+            width = ("fp" + width)
+        return width
+
+    def specifiers(self, record):
+        # elwidths: use "w=" if same otherwise dw/sw
+        # FIXME this should consider FP instructions
+        FP = False
+        dw = WidthBaseRM.width(FP, int(self.elwidth))
+        sw = WidthBaseRM.width(FP, int(self.ewsrc))
+        if dw == sw and dw:
+            yield ("w=" + dw)
+        else:
+            if dw:
+                yield ("dw=" + dw)
+            if sw:
+                yield ("sw=" + sw)
+
+        yield from super().specifiers(record=record)
+
+
+class PredicateBaseRM(BaseRM):
+    @staticmethod
+    def predicate(CR, mask):
+        return {
+            # integer
+            (False, 0b001): "1<<r3",
+            (False, 0b010): "r3",
+            (False, 0b011): "~r3",
+            (False, 0b100): "r10",
+            (False, 0b101): "~r10",
+            (False, 0b110): "r30",
+            (False, 0b111): "~r30",
+            # CRs
+            (True, 0b000): "lt",
+            (True, 0b001): "ge",
+            (True, 0b010): "gt",
+            (True, 0b011): "le",
+            (True, 0b100): "eq",
+            (True, 0b101): "ne",
+            (True, 0b110): "so",
+            (True, 0b111): "ns",
+        }.get((CR, mask))
+
+    def specifiers(self, record):
+        # predication - single and twin
+        # use "m=" if same otherwise sm/dm
+        CR = (int(self.mmode) == 1)
+        mask = int(self.mask)
+        sm = dm = PredicateBaseRM.predicate(CR, mask)
+        if record.svp64.ptype is _SVPtype.P2:
+            smask = int(self.smask)
+            sm = PredicateBaseRM.predicate(CR, smask)
+        if sm == dm and dm:
+            yield ("m=" + dm)
+        else:
+            if sm:
+                yield ("sm=" + sm)
+            if dm:
+                yield ("dm=" + dm)
+
+        yield from super().specifiers(record=record)
+
+
+class PredicateWidthBaseRM(WidthBaseRM, PredicateBaseRM):
+    pass
+
+
+class NormalBaseRM(PredicateWidthBaseRM):
+    """
+    Normal mode
+    https://libre-soc.org/openpower/sv/normal/
+    """
+    pass
+
+
+class NormalSimpleRM(DZBaseRM, SZBaseRM, NormalBaseRM):
+    """normal: simple mode"""
+    dz: BaseRM.mode[3]
+    sz: BaseRM.mode[4]
+
+    def specifiers(self, record):
+        yield from super().specifiers(record=record)
+
+
+class NormalSMRRM(MRBaseRM, NormalBaseRM):
+    """normal: scalar reduce mode (mapreduce), SUBVL=1"""
+    RG: BaseRM.mode[4]
+
+
+class NormalReservedRM(NormalBaseRM):
+    """normal: reserved"""
+    pass
+
+
+class NormalFFRc1RM(FFPRRc1BaseRM, NormalBaseRM):
+    """normal: Rc=1: ffirst CR sel"""
+    inv: BaseRM.mode[2]
+    CR: BaseRM.mode[3, 4]
+
+    def specifiers(self, record):
+        yield from super().specifiers(record=record, mode="ff")
+
+
+class NormalFFRc0RM(FFPRRc0BaseRM, NormalBaseRM):
+    """normal: Rc=0: ffirst z/nonz"""
+    inv: BaseRM.mode[2]
+    VLi: BaseRM.mode[3]
+    RC1: BaseRM.mode[4]
+
+    def specifiers(self, record):
+        if self.VLi:
+            yield "vli"
+
+        yield from super().specifiers(record=record, mode="ff")
+
+
+class NormalSatRM(SatBaseRM, DZBaseRM, SZBaseRM, NormalBaseRM):
+    """normal: sat mode: N=0/1 u/s, SUBVL=1"""
+    N: BaseRM.mode[2]
+    dz: BaseRM.mode[3]
+    sz: BaseRM.mode[4]
+
+
+class NormalPRRc1RM(FFPRRc1BaseRM, NormalBaseRM):
+    """normal: Rc=1: pred-result CR sel"""
+    inv: BaseRM.mode[2]
+    CR: BaseRM.mode[3, 4]
+
+    def specifiers(self, record):
+        yield from super().specifiers(record=record, mode="pr")
+
+
+class NormalPRRc0RM(FFPRRc0BaseRM, ZZBaseRM, NormalBaseRM):
+    """normal: Rc=0: pred-result z/nonz"""
+    inv: BaseRM.mode[2]
+    zz: BaseRM.mode[3]
+    RC1: BaseRM.mode[4]
+    dz: BaseRM.mode[3]
+    sz: BaseRM.mode[3]
+
+    def specifiers(self, record):
+        yield from super().specifiers(record=record, mode="pr")
+
+
+class NormalRM(NormalBaseRM):
+    simple: NormalSimpleRM
+    smr: NormalSMRRM
+    reserved: NormalReservedRM
+    ffrc1: NormalFFRc1RM
+    ffrc0: NormalFFRc0RM
+    sat: NormalSatRM
+    prrc1: NormalPRRc1RM
+    prrc0: NormalPRRc0RM
+
+
+class LDSTImmBaseRM(PredicateWidthBaseRM):
+    """
+    LD/ST Immediate mode
+    https://libre-soc.org/openpower/sv/ldst/
+    """
+    pass
+
+
+class LDSTImmSimpleRM(ElsBaseRM, ZZBaseRM, LDSTImmBaseRM):
+    """ld/st immediate: simple mode"""
+    zz: BaseRM.mode[3]
+    els: BaseRM.mode[4]
+    dz: BaseRM.mode[3]
+    sz: BaseRM.mode[3]
+
+
+class LDSTImmReservedRM(LDSTImmBaseRM):
+    """ld/st immediate: reserved"""
+    pass
+
+
+class LDSTImmFFRc1RM(FFPRRc1BaseRM, LDSTImmBaseRM):
+    """ld/st immediate: Rc=1: ffirst CR sel"""
+    inv: BaseRM.mode[2]
+    CR: BaseRM.mode[3, 4]
+
+    def specifiers(self, record):
+        yield from super().specifiers(record=record, mode="ff")
+
+
+class LDSTImmFFRc0RM(FFPRRc0BaseRM, ElsBaseRM, LDSTImmBaseRM):
+    """ld/st immediate: Rc=0: ffirst z/nonz"""
+    inv: BaseRM.mode[2]
+    els: BaseRM.mode[3]
+    RC1: BaseRM.mode[4]
+
+    def specifiers(self, record):
+        yield from super().specifiers(record=record, mode="ff")
+
+
+class LDSTImmSatRM(ElsBaseRM, SatBaseRM, ZZBaseRM, LDSTImmBaseRM):
+    """ld/st immediate: sat mode: N=0/1 u/s"""
+    N: BaseRM.mode[2]
+    zz: BaseRM.mode[3]
+    els: BaseRM.mode[4]
+    dz: BaseRM.mode[3]
+    sz: BaseRM.mode[3]
+
+
+class LDSTImmPRRc1RM(FFPRRc1BaseRM, LDSTImmBaseRM):
+    """ld/st immediate: Rc=1: pred-result CR sel"""
+    inv: BaseRM.mode[2]
+    CR: BaseRM.mode[3, 4]
+
+    def specifiers(self, record):
+        yield from super().specifiers(record=record, mode="pr")
+
+
+class LDSTImmPRRc0RM(FFPRRc0BaseRM, ElsBaseRM, LDSTImmBaseRM):
+    """ld/st immediate: Rc=0: pred-result z/nonz"""
+    inv: BaseRM.mode[2]
+    els: BaseRM.mode[3]
+    RC1: BaseRM.mode[4]
+
+    def specifiers(self, record):
+        yield from super().specifiers(record=record, mode="pr")
+
+
+class LDSTImmRM(LDSTImmBaseRM):
+    simple: LDSTImmSimpleRM
+    reserved: LDSTImmReservedRM
+    ffrc1: LDSTImmFFRc1RM
+    ffrc0: LDSTImmFFRc0RM
+    sat: LDSTImmSatRM
+    prrc1: LDSTImmPRRc1RM
+    prrc0: LDSTImmPRRc0RM
+
+
+class LDSTIdxBaseRM(PredicateWidthBaseRM):
+    """
+    LD/ST Indexed mode
+    https://libre-soc.org/openpower/sv/ldst/
+    """
+    pass
+
+
+class LDSTIdxSimpleRM(DZBaseRM, SZBaseRM, LDSTIdxBaseRM):
+    """ld/st index: simple mode"""
+    SEA: BaseRM.mode[2]
+    dz: BaseRM.mode[3]
+    sz: BaseRM.mode[4]
+
+
+class LDSTIdxStrideRM(DZBaseRM, SZBaseRM, LDSTIdxBaseRM):
+    """ld/st index: strided (scalar only source)"""
+    SEA: BaseRM.mode[2]
+    dz: BaseRM.mode[3]
+    sz: BaseRM.mode[4]
+
+
+class LDSTIdxSatRM(SatBaseRM, DZBaseRM, SZBaseRM, LDSTIdxBaseRM):
+    """ld/st index: sat mode: N=0/1 u/s"""
+    N: BaseRM.mode[2]
+    dz: BaseRM.mode[3]
+    sz: BaseRM.mode[4]
+
+
+class LDSTIdxPRRc1RM(LDSTIdxBaseRM):
+    """ld/st index: Rc=1: pred-result CR sel"""
+    inv: BaseRM.mode[2]
+    CR: BaseRM.mode[3, 4]
+
+    def specifiers(self, record):
+        yield from super().specifiers(record=record, mode="pr")
 
-    class pmr(Mode):
-        """parallel reduce mode (mapreduce), SUBVL=1"""
-        pass
 
-    class svmr(Mode):
-        """subvector reduce mode, SUBVL>1"""
-        SVM: BaseRM.mode[3]
-
-    class pu(Mode):
-        """Pack/Unpack mode, SUBVL>1"""
-        SVM: BaseRM.mode[3]
-
-    class ffrc1(Mode):
-        """Rc=1: ffirst CR sel"""
-        inv: BaseRM.mode[2]
-        CR: BaseRM.mode[3, 4]
-
-    class ffrc0(Mode):
-        """Rc=0: ffirst z/nonz"""
-        inv: BaseRM.mode[2]
-        VLi: BaseRM.mode[3]
-        RC1: BaseRM.mode[4]
-
-    class sat(Mode):
-        """sat mode: N=0/1 u/s, SUBVL=1"""
-        N: BaseRM.mode[2]
-        dz: BaseRM.mode[3]
-        sz: BaseRM.mode[4]
-
-    class satx(Mode):
-        """sat mode: N=0/1 u/s, SUBVL>1"""
-        N: BaseRM.mode[2]
-        zz: BaseRM.mode[3]
-        dz: BaseRM.mode[3]
-        sz: BaseRM.mode[3]
-
-    class satpu(Mode):
-        """Pack/Unpack sat mode: N=0/1 u/s, SUBVL>1"""
-        N: BaseRM.mode[2]
-        zz: BaseRM.mode[3]
-        dz: BaseRM.mode[3]
-        sz: BaseRM.mode[3]
-
-    class prrc1(Mode):
-        """Rc=1: pred-result CR sel"""
-        inv: BaseRM.mode[2]
-        CR: BaseRM.mode[3, 4]
-
-    class prrc0(Mode):
-        """Rc=0: pred-result z/nonz"""
-        inv: BaseRM.mode[2]
-        zz: BaseRM.mode[3]
-        RC1: BaseRM.mode[4]
-        dz: BaseRM.mode[3]
-        sz: BaseRM.mode[3]
-
-    simple: simple
-    smr: smr
-    pmr: pmr
-    svmr: svmr
-    pu: pu
-    ffrc1: ffrc1
-    ffrc0: ffrc0
-    sat: sat
-    satx: satx
-    satpu: satpu
-    prrc1: prrc1
-    prrc0: prrc0
-
-
-class LDSTImmRM(BaseRM):
-    class simple(Mode):
-        """simple mode"""
-        zz: BaseRM.mode[3]
-        els: BaseRM.mode[4]
-        dz: BaseRM.mode[3]
-        sz: BaseRM.mode[3]
-
-    class spu(Mode):
-        """Structured Pack/Unpack"""
-        zz: BaseRM.mode[3]
-        els: BaseRM.mode[4]
-        dz: BaseRM.mode[3]
-        sz: BaseRM.mode[3]
-
-    class ffrc1(Mode):
-        """Rc=1: ffirst CR sel"""
-        inv: BaseRM.mode[2]
-        CR: BaseRM.mode[3, 4]
-
-    class ffrc0(Mode):
-        """Rc=0: ffirst z/nonz"""
-        inv: BaseRM.mode[2]
-        els: BaseRM.mode[3]
-        RC1: BaseRM.mode[4]
-
-    class sat(Mode):
-        """sat mode: N=0/1 u/s"""
-        N: BaseRM.mode[2]
-        zz: BaseRM.mode[3]
-        els: BaseRM.mode[4]
-        dz: BaseRM.mode[3]
-        sz: BaseRM.mode[3]
-
-    class prrc1(Mode):
-        """Rc=1: pred-result CR sel"""
-        inv: BaseRM.mode[2]
-        CR: BaseRM.mode[3, 4]
-
-    class prrc0(Mode):
-        """Rc=0: pred-result z/nonz"""
-        inv: BaseRM.mode[2]
-        els: BaseRM.mode[3]
-        RC1: BaseRM.mode[4]
-
-    simple: simple
-    spu: spu
-    ffrc1: ffrc1
-    ffrc0: ffrc0
-    sat: sat
-    prrc1: prrc1
-    prrc0: prrc0
-
-
-class LDSTIdxRM(BaseRM):
-    class simple(Mode):
-        """simple mode"""
-        SEA: BaseRM.mode[2]
-        sz: BaseRM.mode[3]
-        dz: BaseRM.mode[3]
-
-    class stride(Mode):
-        """strided (scalar only source)"""
-        SEA: BaseRM.mode[2]
-        dz: BaseRM.mode[3]
-        sz: BaseRM.mode[4]
-
-    class sat(Mode):
-        """sat mode: N=0/1 u/s"""
-        N: BaseRM.mode[2]
-        dz: BaseRM.mode[3]
-        sz: BaseRM.mode[4]
-
-    class prrc1(Mode):
-        """Rc=1: pred-result CR sel"""
-        inv: BaseRM.mode[2]
-        CR: BaseRM.mode[3, 4]
-
-    class prrc0(Mode):
-        """Rc=0: pred-result z/nonz"""
-        inv: BaseRM.mode[2]
-        zz: BaseRM.mode[3]
-        RC1: BaseRM.mode[4]
-        dz: BaseRM.mode[3]
-        sz: BaseRM.mode[3]
-
-    simple: simple
-    stride: stride
-    sat: sat
-    prrc1: prrc1
-    prrc0: prrc0
-
-
-class CROpRM(BaseRM):
-    class simple(BaseRM):
-        """simple mode"""
-        sz: BaseRM[6]
-        SNZ: BaseRM[7]
-        RG: BaseRM[20]
-        dz: BaseRM[22]
-
-    class smr(BaseRM):
-        """scalar reduce mode (mapreduce), SUBVL=1"""
-        sz: BaseRM[6]
-        SNZ: BaseRM[7]
-        RG: BaseRM[20]
-
-    class svmr(BaseRM):
-        """subvector reduce mode, SUBVL>1"""
-        zz: BaseRM[6]
-        SNZ: BaseRM[7]
-        RG: BaseRM[20]
-        SVM: BaseRM[22]
-        dz: BaseRM[6]
-        sz: BaseRM[6]
-
-    class reserved(BaseRM):
-        """reserved"""
-        zz: BaseRM[6]
-        SNZ: BaseRM[7]
-        RG: BaseRM[20]
-        dz: BaseRM[6]
-        sz: BaseRM[6]
-
-    class ff3(BaseRM):
-        """ffirst 3-bit mode"""
-        zz: BaseRM[6]
-        SNZ: BaseRM[7]
-        VLI: BaseRM[20]
-        inv: BaseRM[21]
-        CR: BaseRM[22, 23]
-        dz: BaseRM[6]
-        sz: BaseRM[6]
-
-    class ff5(BaseRM):
-        """ffirst 5-bit mode"""
-        zz: BaseRM[6]
-        SNZ: BaseRM[7]
-        VLI: BaseRM[20]
-        inv: BaseRM[21]
-        dz: BaseRM[22]
-        dz: BaseRM[6]
-        sz: BaseRM[6]
-
-    simple: simple
-    smr: smr
-    svmr: svmr
-    reserved: reserved
-    ff3: ff3
-    ff5: ff5
+class LDSTIdxPRRc0RM(FFPRRc0BaseRM, ZZBaseRM, LDSTIdxBaseRM):
+    """ld/st index: Rc=0: pred-result z/nonz"""
+    inv: BaseRM.mode[2]
+    zz: BaseRM.mode[3]
+    RC1: BaseRM.mode[4]
+    dz: BaseRM.mode[3]
+    sz: BaseRM.mode[3]
 
+    def specifiers(self, record):
+        yield from super().specifiers(record=record, mode="pr")
 
+
+class LDSTIdxRM(LDSTIdxBaseRM):
+    simple: LDSTIdxSimpleRM
+    stride: LDSTIdxStrideRM
+    sat: LDSTIdxSatRM
+    prrc1: LDSTIdxPRRc1RM
+    prrc0: LDSTIdxPRRc0RM
+
+
+
+class CROpBaseRM(BaseRM):
+    """
+    CR ops mode
+    https://libre-soc.org/openpower/sv/cr_ops/
+    """
+    SNZ: BaseRM[7]
+
+
+class CROpSimpleRM(DZBaseRM, SZBaseRM, CROpBaseRM):
+    """cr_op: simple mode"""
+    RG: BaseRM[20]
+    dz: BaseRM[22]
+    sz: BaseRM[23]
+
+    def specifiers(self, record):
+        if self.RG:
+            yield "rg" # simple CR Mode reports /rg
+
+        yield from super().specifiers(record=record)
+
+class CROpSMRRM(MRBaseRM, DZBaseRM, SZBaseRM, CROpBaseRM):
+    """cr_op: scalar reduce mode (mapreduce), SUBVL=1"""
+    RG: BaseRM[20]
+    dz: BaseRM[22]
+    sz: BaseRM[23]
+
+
+class CROpFF3RM(ZZBaseRM, CROpBaseRM):
+    """cr_op: ffirst 3-bit mode"""
+    VLI: BaseRM[20]
+    inv: BaseRM[21]
+    CR: BaseRM[22, 23]
+    zz: BaseRM[6]
+    sz: BaseRM[6]
+    dz: BaseRM[6]
+
+    def specifiers(self, record):
+        yield from super().specifiers(record=record, mode="ff")
+
+
+class CROpFF5RM(DZBaseRM, SZBaseRM, CROpBaseRM):
+    """cr_op: ffirst 5-bit mode"""
+    VLI: BaseRM[20]
+    inv: BaseRM[21]
+    dz: BaseRM[22]
+    sz: BaseRM[23]
+
+    def specifiers(self, record):
+        yield from super().specifiers(record=record)
+
+
+class CROpRM(CROpBaseRM):
+    simple: CROpSimpleRM
+    smr: CROpSMRRM
+    ff3: CROpFF3RM
+    ff5: CROpFF5RM
+
+
+# ********************
+# Branches mode
+# https://libre-soc.org/openpower/sv/branches/
 class BranchBaseRM(BaseRM):
     ALL: BaseRM[4]
     SNZ: BaseRM[5]
@@ -1481,25 +1745,88 @@ class BranchBaseRM(BaseRM):
     SLu: BaseRM[18]
     LRu: BaseRM[22]
     sz: BaseRM[23]
+    CTR: BaseRM[19]
+    VLS: BaseRM[20]
+
+    def specifiers(self, record):
+        if self.ALL:
+            yield "all"
+
+        # /sz
+        #   branch.sz=1
+        #   branch.snz=0
+        # /snz
+        #   branch.sz=1
+        #   branch.snz=1
+        if self.SNZ:
+            if not self.sz:
+                raise ValueError(self.sz)
+            yield "snz"
+        elif self.sz:
+            yield "sz"
+
+        if self.SL:
+            yield "sl"
+        if self.SLu:
+            yield "slu"
+        if self.LRu:
+            yield "lru"
+
+        # Branch modes lack source mask.
+        # Therefore a custom code is needed.
+        CR = (int(self.mmode) == 1)
+        mask = int(self.mask)
+        m = PredicateBaseRM.predicate(CR, mask)
+        if m is not None:
+            yield ("m=" + m)
+
+        yield from super().specifiers(record=record)
+
+
+class BranchSimpleRM(BranchBaseRM):
+    """branch: simple mode"""
+    pass
 
 
-class BranchRM(BranchBaseRM):
-    class simple(BranchBaseRM):
-        """simple mode"""
-        pass
+class BranchVLSRM(BranchBaseRM):
+    """branch: VLSET mode"""
+    VSb: BaseRM[7]
+    VLI: BaseRM[21]
 
-    class vls(BranchBaseRM):
-        """VLSET mode"""
-        VSb: BaseRM[7]
-        VLI: BaseRM[21]
+    def specifiers(self, record):
+        yield {
+            (0b0, 0b0): "vs",
+            (0b0, 0b1): "vsi",
+            (0b1, 0b0): "vsb",
+            (0b1, 0b1): "vsbi",
+        }[int(self.VSb), int(self.VLI)]
 
-    class ctr(BranchBaseRM):
-        """CTR-test mode"""
-        CTi: BaseRM[6]
+        yield from super().specifiers(record=record)
 
-    class ctrvls(vls, ctr):
-        """CTR-test+VLSET mode"""
-        pass
+
+class BranchCTRRM(BranchBaseRM):
+    """branch: CTR-test mode"""
+    CTi: BaseRM[6]
+
+    def specifiers(self, record):
+        if self.CTi:
+            yield "cti"
+        else:
+            yield "ctr"
+
+        yield from super().specifiers(record=record)
+
+
+class BranchCTRVLSRM(BranchVLSRM, BranchCTRRM):
+    """branch: CTR-test+VLSET mode"""
+    pass
+
+
+class BranchRM(BranchBaseRM):
+    simple: BranchSimpleRM
+    vls: BranchVLSRM
+    ctr: BranchCTRRM
+    ctrvls: BranchCTRVLSRM
 
 
 class RM(BaseRM):
@@ -1507,6 +1834,114 @@ class RM(BaseRM):
     ldst_imm: LDSTImmRM
     ldst_idx: LDSTIdxRM
     cr_op: CROpRM
+    branch: BranchRM
+
+    def select(self, record, Rc):
+        rm = self
+
+        # the idea behind these tables is that they are now literally
+        # in identical format to insndb.csv and minor_xx.csv and can
+        # be done precisely as that.  the only thing to watch out for
+        # is the insertion of Rc=1 as a "mask/value" bit and likewise
+        # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
+        # as the LSB.
+        table = None
+        if record.svp64.mode is _SVMode.NORMAL:
+            # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
+            #    mode  Rc  mask  Rc  member
+            table = (
+                (0b000000, 0b111000, "simple"), # simple     (no Rc)
+                (0b001000, 0b111000, "smr"),    # mapreduce  (no Rc)
+                (0b010000, 0b110001, "ffrc0"),  # ffirst,     Rc=0
+                (0b010001, 0b110001, "ffrc1"),  # ffirst,     Rc=1
+                (0b100000, 0b110000, "sat"),    # saturation (no Rc)
+                (0b110000, 0b110001, "prrc0"),  # predicate,  Rc=0
+                (0b110001, 0b110001, "prrc1"),  # predicate,  Rc=1
+            )
+            rm = rm.normal
+            search = ((int(rm.mode) << 1) | Rc)
+
+        elif record.svp64.mode is _SVMode.LDST_IMM:
+            # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
+            #    mode  Rc  mask  Rc  member
+            # ironically/coincidentally this table is identical to NORMAL
+            # mode except reserved in place of smr
+            table = (
+                (0b000000, 0b111000, "simple"),   # simple     (no Rc)
+                (0b001000, 0b111000, "reserved"), # rsvd       (no Rc)
+                (0b010000, 0b110001, "ffrc0"),    # ffirst,     Rc=0
+                (0b010001, 0b110001, "ffrc1"),    # ffirst,     Rc=1
+                (0b100000, 0b110000, "sat"),      # saturation (no Rc)
+                (0b110000, 0b110001, "prrc0"),    # predicate,  Rc=0
+                (0b110001, 0b110001, "prrc1"),    # predicate,  Rc=1
+            )
+            rm = rm.ldst_imm
+            search = ((int(rm.mode) << 1) | Rc)
+
+        elif record.svp64.mode is _SVMode.LDST_IDX:
+            # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
+            #    mode  Rc  mask  Rc  member
+            table = (
+                (0b000000, 0b111000, "simple"), # simple     (no Rc)
+                (0b010000, 0b110000, "stride"), # strided,   (no Rc)
+                (0b100000, 0b110000, "sat"),    # saturation (no Rc)
+                (0b110000, 0b110001, "prrc0"),  # predicate,  Rc=0
+                (0b110001, 0b110001, "prrc1"),  # predicate,  Rc=1
+            )
+            rm = rm.ldst_idx
+            search = ((int(rm.mode) << 1) | Rc)
+
+        elif record.svp64.mode is _SVMode.CROP:
+            # concatenate mode 5-bit with regtype (LSB) then do mask/map search
+            #    mode  3b  mask  3b  member
+            table = (
+                (0b000000, 0b111000, "simple"), # simple
+                (0b001000, 0b111000, "smr"),    # mapreduce
+                (0b100000, 0b100000, "ff5"),    # failfirst, 5-bit CR
+                (0b100001, 0b100001, "ff3"),    # failfirst, 3-bit CR
+            )
+            # determine CR type, 5-bit (BA/BB/BT) or 3-bit Field (BF/BFA)
+            regtype = None
+            for idx in range(0, 4):
+                for entry in record.svp64.extra[idx]:
+                    if entry.regtype is _SVExtraRegType.DST:
+                        if regtype is not None:
+                            raise ValueError(record.svp64)
+                        regtype = _RegType(entry.reg)
+            if regtype is _RegType.CR_REG:
+                regtype = 0 # 5-bit
+            elif regtype is _RegType.CR_BIT:
+                regtype = 1 # 3-bit
+            else:
+                raise ValueError(record.svp64)
+            # finally provide info for search
+            rm = rm.cr_op
+            search = ((int(rm.mode) << 1) | (regtype or 0))
+
+        elif record.svp64.mode is _SVMode.BRANCH:
+            # just mode 2-bit
+            #    mode  mask  member
+            table = (
+                (0b00, 0b11, "simple"), # simple
+                (0b01, 0b11, "vls"),    # VLset
+                (0b10, 0b11, "ctr"),    # CTR mode
+                (0b11, 0b11, "ctrvls"), # CTR+VLset mode
+            )
+            # slightly weird: doesn't have a 5-bit "mode" field like others
+            rm = rm.branch
+            search = int(rm.mode[0, 1])
+
+        # look up in table
+        if table is not None:
+            for (value, mask, member) in table:
+                if ((value & search) == (mask & search)):
+                    rm = getattr(rm, member)
+                    break
+
+        if rm.__class__ is self.__class__:
+            raise ValueError(self)
+
+        return rm
 
 
 class SVP64Instruction(PrefixedInstruction):
@@ -1531,171 +1966,6 @@ class SVP64Instruction(PrefixedInstruction):
             bits.append(bit)
         return "".join(map(str, bits))
 
-    def rm(self, db):
-        record = self.record(db=db)
-
-        Rc = False
-        if record.mdwn.operands["Rc"] is not None:
-            Rc = bool(self[record.fields["Rc"]])
-
-        record = self.record(db=db)
-        subvl = self.prefix.rm.subvl
-        rm = self.prefix.rm
-
-        if record.svp64.mode is _SVMode.NORMAL:
-            rm = rm.normal
-            if rm.mode[0:2] == 0b00:
-                if rm.mode[2] == 0b0:
-                    rm = rm.simple
-                else:
-                    if subvl == 0b00:
-                        if rm.mode[3] == 0b0:
-                            rm = rm.smr
-                        else:
-                            rm = rm.pmr
-                    else:
-                        if rm.mode[4] == 0b0:
-                            rm = rm.svmr
-                        else:
-                            rm = rm.pu
-            elif rm.mode[0:2] == 0b01:
-                if Rc:
-                    rm = rm.ffrc1
-                else:
-                    rm = rm.ffrc0
-            elif rm.mode[0:2] == 0b10:
-                if subvl == 0b00:
-                    rm = rm.sat
-                else:
-                    if rm.mode[4]:
-                        rm = rm.satx
-                    else:
-                        rm = rm.satpu
-            elif rm.mode[0:2] == 0b11:
-                if Rc:
-                    rm = rm.prrc1
-                else:
-                    rm = rm.prrc0
-
-        elif record.svp64.mode is _SVMode.LDST_IMM:
-            rm = rm.ldst_imm
-            if rm.mode[0:2] == 0b00:
-                if rm.mode[2] == 0b0:
-                    rm = rm.simple
-                else:
-                    rm = rm.spu
-            elif rm.mode[0:2] == 0b01:
-                if Rc:
-                    rm = rm.ffrc1
-                else:
-                    rm = rm.ffrc0
-            elif rm.mode[0:2] == 0b10:
-                rm = rm.sat
-            elif rm.mode[0:2] == 0b11:
-                if Rc:
-                    rm = rm.prrc1
-                else:
-                    rm = rm.prrc0
-
-        elif record.svp64.mode is _SVMode.LDST_IMM:
-            rm = rm.ldst_idx
-            if rm.mode[0:2] == 0b00:
-                rm = rm.simple
-            elif rm.mode[0:2] == 0b01:
-                rm = rm.stride
-            elif rm.mode[0:2] == 0b10:
-                rm = rm.sat
-            elif rm.mode[0:2] == 0b11:
-                if Rc:
-                    rm = rm.prrc1
-                else:
-                    rm = rm.prrc0
-
-        elif record.svp64.mode is _SVMode.CROP:
-            rm = rm.cr_op
-            if rm[19] == 0b0:
-                if rm[21] == 0b0:
-                    rm = rm.simple
-                else:
-                    if subvl == 0:
-                        rm = rm.smr
-                    else:
-                        if rm[23] == 0b0:
-                            rm = rm.svmr
-                        else:
-                            rm = rm.reserved
-            else:
-                regtype = None
-                for idx in range(0, 4):
-                    for entry in record.svp64.extra[idx]:
-                        if entry.regtype is _SVExtraRegType.DST:
-                            if regtype is not None:
-                                raise ValueError(record.svp64)
-                            regtype = _RegType(entry.reg)
-                if regtype is _RegType.CR_REG:
-                    rm = rm.ff5
-                elif regtype is _RegType.CR_BIT:
-                    rm = rm.ff3
-                else:
-                    raise ValueError(record.svp64)
-
-        elif record.svp64.mode is _SVMode.BRANCH:
-            if rm[19] == 0b0:
-                if rm[20] == 0b0:
-                    rm = rm.simple
-                else:
-                    rm = rm.vls
-            else:
-                if rm[20] == 0b0:
-                    rm = rm.ctr
-                else:
-                    rm = rm.ctrvls
-
-        else:
-            raise ValueError(self)
-
-        table = {
-            NormalRM.simple: "normal: simple",
-            NormalRM.smr: "normal: smr",
-            NormalRM.pmr: "normal: pmr",
-            NormalRM.svmr: "normal: svmr",
-            NormalRM.pu: "normal: pu",
-            NormalRM.ffrc1: "normal: ffrc1",
-            NormalRM.ffrc0: "normal: ffrc0",
-            NormalRM.sat: "normal: sat",
-            NormalRM.satx: "normal: satx",
-            NormalRM.satpu: "normal: satpu",
-            NormalRM.prrc1: "normal: prrc1",
-            NormalRM.prrc0: "normal: prrc0",
-            LDSTImmRM.simple: "ld/st imm: simple",
-            LDSTImmRM.spu: "ld/st imm: spu",
-            LDSTImmRM.ffrc1: "ld/st imm: ffrc1",
-            LDSTImmRM.ffrc0: "ld/st imm: ffrc0",
-            LDSTImmRM.sat: "ld/st imm: sat",
-            LDSTImmRM.prrc1: "ld/st imm: prrc1",
-            LDSTImmRM.prrc0: "ld/st imm: prrc0",
-            LDSTIdxRM.simple: "ld/st idx: simple",
-            LDSTIdxRM.stride: "ld/st idx: stride",
-            LDSTIdxRM.sat: "ld/st idx: sat",
-            LDSTIdxRM.prrc1: "ld/st idx: prrc1",
-            LDSTIdxRM.prrc0: "ld/st idx: prrc0",
-            CROpRM.simple: "simple mode",
-            CROpRM.smr: "scalar reduce mode (mapreduce), SUBVL=1",
-            CROpRM.svmr: "subvector reduce mode, SUBVL>1",
-            CROpRM.reserved: "reserved",
-            CROpRM.ff3: "ffirst 3-bit mode",
-            CROpRM.ff5: "ffirst 5-bit mode",
-            BranchRM.simple: "simple mode",
-            BranchRM.vls: "VLSET mode",
-            BranchRM.ctr: "CTR-test mode",
-            BranchRM.ctrvls: "CTR-test+VLSET mode",
-        }
-        for (cls, desc) in table.items():
-            if isinstance(rm, cls):
-                return (rm, desc)
-
-        raise ValueError(self)
-
     def disassemble(self, db,
             byteorder="little",
             verbosity=Verbosity.NORMAL):
@@ -1707,29 +1977,43 @@ class SVP64Instruction(PrefixedInstruction):
                 blob = " ".join(map(lambda byte: f"{byte:02x}", blob))
                 return f"{blob}    "
 
+        record = self.record(db=db)
         blob_prefix = blob(int(self.prefix))
         blob_suffix = blob(int(self.suffix))
-        record = db[self]
         if record is None or record.svp64 is None:
             yield f"{blob_prefix}.long 0x{int(self.prefix):08x}"
             yield f"{blob_suffix}.long 0x{int(self.suffix):08x}"
             return
 
+        name = f"sv.{record.name}"
+
+        Rc = False
+        if record.mdwn.operands["Rc"] is not None:
+            Rc = bool(record.mdwn.operands["Rc"].value)
+        rm = self.prefix.rm.select(record=record, Rc=Rc)
+
+        # convert specifiers to /x/y/z (sorted lexicographically)
+        specifiers = sorted(rm.specifiers(record=record))
+        if specifiers: # if any add one extra to get the extra "/"
+            specifiers = ([""] + specifiers)
+        specifiers = "/".join(specifiers)
+
+        # convert operands to " ,x,y,z"
         operands = tuple(map(_operator.itemgetter(1),
             self.dynamic_operands(db=db, verbosity=verbosity)))
-        if operands:
-            yield f"{blob_prefix}sv.{record.name} {','.join(operands)}"
-        else:
-            yield f"{blob_prefix}{record.name}"
+        operands = ",".join(operands)
+        if len(operands) > 0: # if any separate with a space
+            operands = (" " + operands)
+
+        yield f"{blob_prefix}{name}{specifiers}{operands}"
         if blob_suffix:
             yield f"{blob_suffix}"
 
-        (rm, rm_desc) = self.rm(db=db)
-
         if verbosity >= Verbosity.VERBOSE:
             indent = (" " * 4)
             binary = self.binary
             spec = self.spec(db=db, prefix="sv.")
+
             yield f"{indent}spec"
             yield f"{indent}{indent}{spec}"
             yield f"{indent}pcode"
@@ -1750,9 +2034,10 @@ class SVP64Instruction(PrefixedInstruction):
             for operand in record.mdwn.operands:
                 yield from operand.disassemble(insn=self, record=record,
                     verbosity=verbosity, indent=indent)
-
             yield f"{indent}RM"
-            yield f"{indent}{indent}{rm_desc}"
+            yield f"{indent}{indent}{rm.__doc__}"
+            for line in rm.disassemble(verbosity=verbosity):
+                yield f"{indent}{indent}{line}"
             yield ""
 
 
@@ -1786,6 +2071,9 @@ class MarkdownDatabase:
     def __iter__(self):
         yield from self.__db.items()
 
+    def __contains__(self, key):
+        return self.__db.__contains__(key)
+
     def __getitem__(self, key):
         return self.__db.__getitem__(key)
 
@@ -1831,63 +2119,64 @@ class PPCDatabase:
                     for insn in parse(stream, factory):
                         records[section][insn.comment].add(insn)
 
-        db = dd(set)
+        sections = dd(set)
         for (section, group) in records.items():
             for records in group.values():
-                db[section].add(PPCMultiRecord(records))
+                sections[section].add(PPCMultiRecord(records))
+
+        db = {}
+        for (section, records) in sections.items():
+            for record in records:
+                def exact_match(names):
+                    for name in names:
+                        if name in mdwndb:
+                            yield name
+
+                def Rc_match(names):
+                    for name in names:
+                        if f"{name}." in mdwndb:
+                            yield f"{name}."
+                        yield name
+
+                def LK_match(names):
+                    if "lk" not in record.flags:
+                        yield from names
+                        return
+
+                    for name in names:
+                        if f"{name}l" in mdwndb:
+                            yield f"{name}l"
+                        yield name
+
+                def AA_match(names):
+                    if record.intop not in {_MicrOp.OP_B, _MicrOp.OP_BC}:
+                        yield from names
+                        return
+
+                    for name in names:
+                        operands = mdwndb[name].operands["AA"]
+                        if ((operands is not None) and
+                                (f"{name}a" in mdwndb)):
+                            yield f"{name}a"
+                        yield name
+
+                def reductor(names, match):
+                    return match(names)
+
+                matches = (exact_match, Rc_match, LK_match, AA_match)
+
+                names = _functools.reduce(reductor, matches, record.names)
+                for name in names:
+                    db[name] = (section, record)
 
         self.__db = db
         self.__mdwndb = mdwndb
 
         return super().__init__()
 
+    @_functools.lru_cache(maxsize=512, typed=False)
     def __getitem__(self, key):
-        def exact_match(key, record):
-            return (key in record.names)
-
-        def Rc_match(key, record):
-            if not key.endswith("."):
-                return False
-
-            if record.Rc is _RCOE.NONE:
-                return False
-
-            return exact_match(key[:-1], record)
-
-        def LK_match(key, record):
-            if not key.endswith("l"):
-                return False
-
-            if "lk" not in record.flags:
-                return False
-
-            return exact_match(key[:-1], record)
-
-        def AA_match(key, record):
-            if not key.endswith("a"):
-                return False
-
-            if record.intop not in {_MicrOp.OP_B, _MicrOp.OP_BC}:
-                return False
-
-            if self.__mdwndb[key].operands["AA"] is None:
-                return False
-
-            return (exact_match(key[:-1], record) or
-                LK_match(key[:-1], record))
-
-        for (section, records) in self.__db.items():
-            for record in records:
-                if exact_match(key, record):
-                    return (section, record)
-
-            for record in records:
-                if (Rc_match(key, record) or
-                        LK_match(key, record) or
-                        AA_match(key, record)):
-                    return (section, record)
-
-        return (None, None)
+        return self.__db.get(key, (None, None))
 
 
 class SVP64Database: