power_enums: provide selector type property
[openpower-isa.git] / src / openpower / decoder / power_enums.py
index a40cf55ba55b3e0797cf06621540f352d3c21d75..66298f989b669b5c59cf913e7aadd9081e774389 100644 (file)
@@ -167,6 +167,11 @@ class Form(Enum):
     VA2 = 39
     SVC = 40
     SVR = 41
+    CRB = 42 # crternlogi / crbinlut
+    MM = 43  # [f]minmax[s][.]
+    CW = 44
+    CW2 = 45
+    DCT = 46 # fdmadds
 
 # Simple-V svp64 fields https://libre-soc.org/openpower/sv/svp64/
 
@@ -185,24 +190,32 @@ class SVPType(Enum):
     NONE = 0
     P1 = 1
     P2 = 2
+    P2M = 3 # for mixed EXTRA3/3/2 where MASK_SRC is RM[6,7,18]
 
     @classmethod
     def _missing_(cls, desc):
-        return {"1P": SVPType.P1, "2P": SVPType.P2}.get(desc)
+        return {"1P": SVPType.P1, "2P": SVPType.P2, "2PM": SVPType.P2M}.get(desc)
 
     def __repr__(self):
         return {
             SVPType.NONE: "NONE",
             SVPType.P1: "1P",
             SVPType.P2: "2P",
+            SVPType.P2M: "2PM",
         }[self]
 
 
 @unique
 class SVEType(Enum):
+    """SVEType
+    * EXTRA2 : 0: [10,11] 1: [12,13] 2: [14,15] 3: [16,17] unused: [18]
+    * EXTRA3 : 0: [10,11,12] 1: [13,14,15] mask: [16,17,18] 
+    * EXTRA32: 0: [10,11,12] 1: [13,14,15] 2: [16,17] mask: [6,7,18]
+    """
     NONE = 0
     EXTRA2 = 1
     EXTRA3 = 2
+    EXTRA32 = 3 # mixed EXTRA3 and EXTRA2 using RM bits 6&7 for MASK_SRC
 
     def __repr__(self):
         return self.name
@@ -228,24 +241,18 @@ class SVExtra(Enum):
 
     def __repr__(self):
         return {
-            SVExtra.NONE: "NONE",
-            SVExtra.Idx0: "[0]",
-            SVExtra.Idx1: "[1]",
-            SVExtra.Idx2: "[2]",
-            SVExtra.Idx3: "[3]",
-            SVExtra.Idx_1_2: "[1:2]",
+            SVExtra.NONE: "none",
+            SVExtra.Idx0: "extra0",
+            SVExtra.Idx1: "extra1",
+            SVExtra.Idx2: "extra2",
+            SVExtra.Idx3: "extra3",
+            SVExtra.Idx_1_2: "extra1/extra2",
         }[self]
 
 # Backward compatibility
 SVEXTRA = SVExtra
 
 
-class SVExtraRegType(Enum):
-    NONE = None
-    SRC = 's'
-    DST = 'd'
-
-
 class SVExtraReg(Enum):
     NONE = auto()
     RA = auto()
@@ -273,6 +280,12 @@ class SVExtraReg(Enum):
     BFT = auto()
     WHOLE_REG = auto()
     SPR = auto()
+    RSp = auto()
+    RTp = auto()
+    FRAp = auto()
+    FRBp = auto()
+    FRSp = auto()
+    FRTp = auto()
 
     @classmethod
     def _missing_(cls, desc):
@@ -283,7 +296,29 @@ class SVExtraReg(Enum):
         if isinstance(desc, selectors):
             return cls.__members__.get(desc.name)
 
-        return super()._missing_(desc)
+        return cls.__members__.get(desc)
+
+    @property
+    def alias(self):
+        alias = {
+            SVExtraReg.RSp: SVExtraReg.RS,
+            SVExtraReg.RTp: SVExtraReg.RT,
+            SVExtraReg.FRAp: SVExtraReg.FRA,
+            SVExtraReg.FRBp: SVExtraReg.FRB,
+            SVExtraReg.FRSp: SVExtraReg.FRS,
+            SVExtraReg.FRTp: SVExtraReg.FRT,
+        }.get(self)
+        if alias is not None:
+            return alias
+
+        alias = {
+            SVExtraReg.RA_OR_ZERO: SVExtraReg.RA,
+            SVExtraReg.RT_OR_ZERO: SVExtraReg.RT,
+        }.get(self)
+        if alias is not None:
+            return alias
+
+        return self
 
 
 @unique
@@ -291,156 +326,208 @@ class SVP64PredMode(Enum):
     ALWAYS = 0
     INT = 1
     CR = 2
+    RC1 = 3
 
 
 @unique
 class SVP64PredInt(Enum):
-    ALWAYS = 0
-    R3_UNARY = 1
-    R3 = 2
-    R3_N = 3
-    R10 = 4
-    R10_N = 5
-    R30 = 6
-    R30_N = 7
+    ALWAYS = 0b000
+    R3_UNARY = 0b001
+    R3 = 0b010
+    R3_N = 0b011
+    R10 = 0b100
+    R10_N = 0b101
+    R30 = 0b110
+    R30_N = 0b111
+
+    @classmethod
+    def _missing_(cls, desc):
+        if isinstance(desc, str):
+            value = desc
+            values = {
+                "^r3": cls.R3_UNARY,
+                "r3": cls.R3,
+                "~r3": cls.R3_N,
+                "r10": cls.R10,
+                "~r10": cls.R10_N,
+                "r30": cls.R30,
+                "~r30": cls.R30_N,
+            }
+            if value.startswith("~"):
+                value = f"~{value[1:].strip()}"
+            elif "<<" in value: # 1 << r3
+                (lhs, _, rhs) = value.partition("<<")
+                lhs = lhs.strip().lower()
+                rhs = rhs.strip().lower()
+                if (lhs == "1") and (rhs in ("r3", "%r3")):
+                    value = "^r3"
+
+            return values.get(value)
+
+        return super()._missing_(desc)
+
+    def __str__(self):
+        return {
+            self.__class__.ALWAYS: "",
+            self.__class__.R3_UNARY: "^r3",
+            self.__class__.R3: "r3",
+            self.__class__.R3_N: "~r3",
+            self.__class__.R10: "r10",
+            self.__class__.R10_N: "~r10",
+            self.__class__.R30: "r30",
+            self.__class__.R30_N: "~r30",
+        }[self]
+
+    def __repr__(self):
+        return f"{self.__class__.__name__}({str(self)})"
+
+    def __int__(self):
+        return self.value
+
+    @property
+    def mode(self):
+        return SVP64PredMode.INT
+
+    @property
+    def inv(self):
+        return (self.value & 0b1)
+
+    @property
+    def state(self):
+        return (self.value >> 1)
 
 
-@unique
 class SVP64PredCR(Enum):
     LT = 0
     GE = 1
+    NL = GE
     GT = 2
     LE = 3
+    NG = LE
     EQ = 4
     NE = 5
     SO = 6
+    UN = SO
     NS = 7
+    NU = NS
 
+    @classmethod
+    def _missing_(cls, desc):
+        if isinstance(desc, str):
+            name = desc.upper()
+            return cls.__members__.get(name)
 
-@unique
-class SVP64RMMode(Enum):
-    NORMAL = 0
-    MAPREDUCE = 1
-    FFIRST = 2
-    SATURATE = 3
-    PREDRES = 4
-    BRANCH = 5
+        return super()._missing_(desc)
 
+    def __int__(self):
+        return self.value
 
-@unique
-class SVP64BCPredMode(Enum):
-    NONE = 0
-    MASKZERO = 1
-    MASKONE = 2
+    @property
+    def mode(self):
+        return SVP64PredMode.CR
+
+    @property
+    def inv(self):
+        return (self.value & 0b1)
+
+    @property
+    def state(self):
+        return (self.value >> 1)
 
 
 @unique
-class SVP64Predicate(Enum):
-    # Integer
-    BITSEL_R3 = ("^r3", True, 0b00)
-    R3 = ("r3", False, 0b01)
-    R3_INV = ("~r3", True, 0b01)
-    R10 = ("r10", False, 0b10)
-    R10_INV = ("~r10", True, 0b10)
-    R30 = ("r30", False, 0b11)
-    R30_INV = ("~r30", True, 0b11)
-
-    # CR
-    LT = ("lt", False, 0b00)
-    NL = ("nl", True, 0b00)
-    GE = ("ge", True, 0b00)
-    GT = ("gt", False, 0b01)
-    NG = ("ng", True, 0b01)
-    LE = ("le", True, 0b01)
-    EQ = ("eq", False, 0b10)
-    NE = ("ne", True, 0b10)
-    SO = ("so", False, 0b11)
-    UN = ("un", False, 0b11)
-    NS = ("ns", True, 0b11)
-    NU = ("nu", True, 0b11)
-
-    # RC1
-    RC1 = ("RC1", False, 0b1)
-    RC1_INV = ("~RC1", True, 0b1)
+class SVP64PredRC1(Enum):
+    RC1 = 0
+    RC1_N = 1
 
     @classmethod
     def _missing_(cls, desc):
-        if isinstance(desc, str):
-            members = {}
-            for (name, member) in cls.__members__.items():
-                members[str(member)] = member.name
-
-            member = desc
-            if "RC1" not in member:
-                member = member.lower()
-
-            if member.startswith("~"):
-                member = f"~{member[1:].strip()}"
-            elif "<<" in member:
-                # 1 << r3
-                (lhs, _, rhs) = member.partition("<<")
-                lhs = lhs.strip().lower()
-                rhs = rhs.strip().lower()
-                if (lhs == "1") and (rhs in ("r3", "%r3")):
-                    member = "^r3"
-            member = members.get(member, member)
-            return cls[member]
-
-        return super()._missing_(desc)
+        return {
+            "RC1": SVP64PredRC1.RC1,
+            "~RC1": SVP64PredRC1.RC1_N,
+        }.get(desc)
 
-    def __str__(self):
-        return self.value[0]
+    def __int__(self):
+        return 1
 
     @property
-    def type(self):
-        return SVP64PredicateType(self)
+    def mode(self):
+        return SVP64PredMode.RC1
 
     @property
     def inv(self):
-        return self.value[1]
+        return (self is SVP64PredRC1.RC1_N)
 
     @property
     def state(self):
-        return self.value[2]
+        return 1
+
+
+class SVP64Pred(Enum):
+    ALWAYS = SVP64PredInt.ALWAYS
+    R3_UNARY = SVP64PredInt.R3_UNARY
+    R3 = SVP64PredInt.R3
+    R3_N = SVP64PredInt.R3_N
+    R10 = SVP64PredInt.R10
+    R10_N = SVP64PredInt.R10_N
+    R30 = SVP64PredInt.R30
+    R30_N = SVP64PredInt.R30_N
+
+    LT = SVP64PredCR.LT
+    GE = SVP64PredCR.GE
+    GT = SVP64PredCR.GT
+    LE = SVP64PredCR.LE
+    EQ = SVP64PredCR.EQ
+    NE = SVP64PredCR.NE
+    SO = SVP64PredCR.SO
+    NS = SVP64PredCR.NS
+
+    RC1 = SVP64PredRC1.RC1
+    RC1_N = SVP64PredRC1.RC1_N
+
+    @classmethod
+    def _missing_(cls, desc):
+        if isinstance(desc, str):
+            values = {item.value:item for item in cls}
+            for subcls in (SVP64PredInt, SVP64PredCR, SVP64PredRC1):
+                try:
+                    return values.get(subcls(desc))
+                except ValueError:
+                    pass
+            return None
+
+        return super()._missing_(desc)
+
+    def __int__(self):
+        return int(self.value)
 
     @property
-    def mask(self):
-        return ((int(self.state) << 1) | (int(self.inv) << 0))
+    def mode(self):
+        return self.value.mode
 
+    @property
+    def inv(self):
+        return self.value.inv
 
-class SVP64PredicateType(Enum):
-    INTEGER = auto()
-    BITSEL_R3 = INTEGER
-    R3 = INTEGER
-    R3_INV = INTEGER
-    R10 = INTEGER
-    R10_INV = INTEGER
-    R30 = INTEGER
-    R30_INV = INTEGER
+    @property
+    def state(self):
+        return self.value.state
 
-    CR = auto()
-    LT = CR
-    NL = CR
-    GE = CR
-    GT = CR
-    NG = CR
-    LE = CR
-    EQ = CR
-    NE = CR
-    SO = CR
-    UN = CR
-    NS = CR
-    NU = CR
-
-    RC1 = auto()
-    RC1_INV = RC1
 
-    @classmethod
-    def _missing_(cls, desc):
-        if isinstance(desc, SVP64Predicate):
-            return cls.__members__.get(desc.name)
+@unique
+class SVP64RMMode(Enum):
+    NORMAL = 0
+    MAPREDUCE = 1
+    FFIRST = 2
+    SATURATE = 3
+    BRANCH = 5
 
-        return super()._missing_(desc)
+
+@unique
+class SVP64BCPredMode(Enum):
+    NONE = 0
+    MASKZERO = 1
+    MASKONE = 2
 
 
 @unique
@@ -520,25 +607,31 @@ class RegType(Enum):
     RB = GPR
     RC = GPR
     RS = GPR
+    RSp = RS
     RT = GPR
+    RTp = RT
 
     FPR = 1
     FRA = FPR
+    FRAp = FRA
     FRB = FPR
+    FRBp = FRB
     FRC = FPR
     FRS = FPR
+    FRSp = FRS
     FRT = FPR
+    FRTp = FRT
 
-    CR_5BIT = 2 # CR field; the CR register is 32-bit
-    BF = CR_5BIT
-    BFA = CR_5BIT
+    CR_3BIT = 2 # CR field; the CR register is 32-bit
+    BF = CR_3BIT
+    BFA = CR_3BIT
 
-    CR_3BIT = 3 # bit of the 32-bit CR register
-    BA = CR_3BIT
-    BB = CR_3BIT
-    BC = CR_3BIT
-    BI = CR_3BIT
-    BT = CR_3BIT
+    CR_5BIT = 3 # bit of the 32-bit CR register
+    BA = CR_5BIT
+    BB = CR_5BIT
+    BC = CR_5BIT
+    BI = CR_5BIT
+    BT = CR_5BIT
 
     XER_BIT = 4   # XER bits, includes OV, OV32, SO, CA, CA32
     OV = XER_BIT
@@ -555,11 +648,6 @@ class RegType(Enum):
         return super()._missing_(value)
 
 
-class CRType(Enum):
-    CR5BIT = 0
-    CR3BIT = 1
-
-
 FPTRANS_INSNS = (
     "fatan2", "fatan2s",
     "fatan2pi", "fatan2pis",
@@ -601,22 +689,25 @@ FPTRANS_INSNS = (
     "fasinh", "fasinhs",
     "facosh", "facoshs",
     "fatanh", "fatanhs",
-    "fminnum08", "fminnum08s",
-    "fmaxnum08", "fmaxnum08s",
-    "fmin19", "fmin19s",
-    "fmax19", "fmax19s",
-    "fminnum19", "fminnum19s",
-    "fmaxnum19", "fmaxnum19s",
-    "fminc", "fmincs",
-    "fmaxc", "fmaxcs",
-    "fminmagnum08", "fminmagnum08s",
-    "fmaxmagnum08", "fmaxmagnum08s",
-    "fminmag19", "fminmag19s",
-    "fmaxmag19", "fmaxmag19s",
-    "fminmagnum19", "fminmagnum19s",
-    "fmaxmagnum19", "fmaxmagnum19s",
-    "fminmagc", "fminmagcs",
-    "fmaxmagc", "fmaxmagcs",
+    # fmin*/fmax* need to be replaced with fminmax
+    # https://bugs.libre-soc.org/show_bug.cgi?id=1057
+    # commented for now to make space for fmv/cvt
+    # "fminnum08", "fminnum08s",
+    # "fmaxnum08", "fmaxnum08s",
+    # "fmin19", "fmin19s",
+    # "fmax19", "fmax19s",
+    # "fminnum19", "fminnum19s",
+    # "fmaxnum19", "fmaxnum19s",
+    # "fminc", "fmincs",
+    # "fmaxc", "fmaxcs",
+    # "fminmagnum08", "fminmagnum08s",
+    # "fmaxmagnum08", "fmaxmagnum08s",
+    # "fminmag19", "fminmag19s",
+    # "fmaxmag19", "fmaxmag19s",
+    # "fminmagnum19", "fminmagnum19s",
+    # "fmaxmagnum19", "fmaxmagnum19s",
+    # "fminmagc", "fminmagcs",
+    # "fmaxmagc", "fmaxmagcs",
     "fmod", "fmods",
     "fremainder", "fremainders",
 )
@@ -628,6 +719,7 @@ _insns = [
     "NONE", "add", "addc", "addco", "adde", "addeo",
     "addi", "addic", "addic.", "addis",
     "addme", "addmeo", "addo", "addze", "addzeo",
+    "addex",
     "addg6s",
     "and", "andc", "andi.", "andis.",
     "attn",
@@ -651,7 +743,7 @@ _insns = [
     "divmod2du",
     "divw", "divwe", "divweo",
     "divweu", "divweuo", "divwo", "divwu", "divwuo",
-    "dsld", "dsrd",
+    "dsld", "dsld.", "dsrd", "dsrd.",
     "eieio", "eqv",
     "extsb", "extsh", "extsw", "extswsli",
     "fadd", "fadds", "fsub", "fsubs",                   # FP add / sub
@@ -664,6 +756,10 @@ _insns = [
     "fmr", "fabs", "fnabs", "fneg", "fcpsgn",           # FP move/abs/neg
     "fmvis",                                            # FP load immediate
     "fishmv",                                           # Float Replace Lower-Half Single, Immediate
+    "fcvttg", "fcvttgo", "fcvttgs", "fcvttgso",
+    "fmvtg", "fmvtgs",
+    "fcvtfg", "fcvtfgs",
+    "fmvfg", "fmvfgs",
     'grev', 'grev.', 'grevi', 'grevi.',
     'grevw', 'grevw.', 'grevwi', 'grevwi.',
     "hrfid", "icbi", "icbt", "isel", "isync",
@@ -683,9 +779,11 @@ _insns = [
     # "lwzbr", "lwzubr", # more load word SVP64 bit-reversed
     "maddedu", "maddedus",
     "maddhd", "maddhdu", "maddld",                      # INT multiply-and-add
+    "maddsubrs",         # Integer DCT Butterfly Add Sub and Round Shift
+    "maddrs",            # Integer DCT Butterfly Add and Accumulate and Round Shift
     "mcrf", "mcrxr", "mcrxrx", "mfcr/mfocrf",           # CR mvs
     "mfmsr", "mfspr",
-    "mins", "maxs", "minu", "maxu",                     # AV bitmanip
+    "minmax",                     # AV bitmanip
     "modsd", "modsw", "modud", "moduw",
     "mtcrf/mtocrf", "mtmsr", "mtmsrd", "mtspr",
     "mulhd", "mulhdu", "mulhw", "mulhwu", "mulld", "mulldo",
@@ -707,7 +805,7 @@ _insns = [
     "svshape2",  # https://libre-soc.org/openpower/sv/remap/discussion TODO
     "svstep",  # https://libre-soc.org/openpower/sv/setvl
     "sim_cfg",
-    "shadd", "shadduw",
+    "sadd", "saddw", "sadduw",
     "slbia", "sld", "slw", "srad", "sradi",
     "sraw", "srawi", "srd", "srw",
     "stb", "stbcix", "stbcx", "stbu", "stbux", "stbx",
@@ -844,21 +942,45 @@ class MicrOp(Enum):
     OP_DSHL = 101
     OP_DSHR = 102
     OP_SHADD = 103
+    OP_MADDSUBRS = 104
+    OP_MADDRS = 105
+
+
+class SelType(Enum):
+    NONE = None
+    SRC = 's'
+    DST = 'd'
+
+    def __repr__(self):
+        return {
+            SelType.NONE: "none",
+            SelType.SRC: "src",
+            SelType.DST: "dst",
+        }[self]
 
 
-@unique
 class In1Sel(Enum):
     NONE = 0
     RA = 1
     RA_OR_ZERO = 2
     SPR = 3
     RS = 4  # for some ALU/Logical operations
+    RSp = RS
     FRA = 5
+    FRAp = FRA
     FRS = 6
-    CIA = 7 # for addpcis
+    FRSp = FRS
+    FRT = 7
+    CIA = 8 # for addpcis
+    RT = 9
+
+    @property
+    def type(self):
+        if self is In1Sel.NONE:
+            return SelType.NONE
+        return SelType.SRC
 
 
-@unique
 class In2Sel(Enum):
     NONE = 0
     RB = 1
@@ -874,35 +996,62 @@ class In2Sel(Enum):
     CONST_SH32 = 11
     SPR = 12
     RS = 13  # for shiftrot (M-Form)
+    RSp = RS
     FRB = 14
+    FRBp = FRB
     CONST_SVD = 15  # for SVD-Form
     CONST_SVDS = 16  # for SVDS-Form
     CONST_XBI = 17
     CONST_DXHI4 = 18 # for addpcis
     CONST_DQ = 19 # for ld/st-quad
 
+    @property
+    def type(self):
+        if self is In2Sel.NONE:
+            return SelType.NONE
+        return SelType.SRC
+
 
-@unique
 class In3Sel(Enum):
     NONE = 0
     RS = 1
+    RSp = RS
     RB = 2  # for shiftrot (M-Form)
     FRS = 3
+    FRSp = FRS
     FRC = 4
     RC = 5  # for SVP64 bit-reverse LD/ST
     RT = 6  # for ternlog[i]
+    RTp = RT
+    FRA = 7
+
+    @property
+    def type(self):
+        if self is In3Sel.NONE:
+            return SelType.NONE
+        return SelType.SRC
 
 
-@unique
 class OutSel(Enum):
     NONE = 0
     RT = 1
+    RTp = RT
     RA = 2
     SPR = 3
     RT_OR_ZERO = 4
     FRT = 5
+    FRTp = FRT
     FRS = 6
+    FRSp = FRS
     RS = 7
+    RSp = RS
+    FRA = 8
+
+    @property
+    def type(self):
+        if self is OutSel.NONE:
+            return SelType.NONE
+        return SelType.DST
 
 
 @unique
@@ -953,12 +1102,24 @@ class CRInSel(Enum):
     CR1 = 7
     BA = 8
 
+    @property
+    def type(self):
+        if self is CRInSel.NONE:
+            return SelType.NONE
+        return SelType.SRC
+
 
 @unique
 class CRIn2Sel(Enum):
     NONE = 0
     BB = 1
 
+    @property
+    def type(self):
+        if self is CRIn2Sel.NONE:
+            return SelType.NONE
+        return SelType.SRC
+
 
 @unique
 class CROutSel(Enum):
@@ -969,6 +1130,12 @@ class CROutSel(Enum):
     WHOLE_REG = 4
     CR1 = 5
 
+    @property
+    def type(self):
+        if self is CROutSel.NONE:
+            return SelType.NONE
+        return SelType.DST
+
 
 # SPRs - Special-Purpose Registers.  See V3.0B Figure 18 p971 and
 # http://libre-riscv.org/openpower/isatables/sprs.csv
@@ -1020,6 +1187,23 @@ XER_bits = {
 
 MSRSpec = namedtuple("MSRSpec", ["dr", "pr", "sf"])
 
+# flags for bfp_* functions
+BFP_FLAG_NAMES = (
+    'vxsnan_flag',
+    'vximz_flag',
+    'vxidi_flag',
+    'vxisi_flag',
+    'vxzdz_flag',
+    'vxsqrt_flag',
+    'vxcvi_flag',
+    'vxvc_flag',
+    'ox_flag',
+    'ux_flag',
+    'xx_flag',
+    'zx_flag',
+    'inc_flag',
+)
+
 if __name__ == '__main__':
     # find out what the heck is in SPR enum :)
     print("sprs full", len(SPRfull))