power_insn: support verbosity levels
[openpower-isa.git] / src / openpower / sv / trans / svp64.py
index 0c3e3f876420a5c05d214b15c97ff68730c47048..7b146fb4ca2a4170abb69f7d4bfcddfe96abc0fa 100644 (file)
@@ -51,8 +51,8 @@ def instruction(*fields):
 CUSTOM_INSNS = {}
 
 
-def _insn(name, *args, **kwargs):
-    return name, args, kwargs
+def _insn(name, **kwargs):
+    return name, kwargs
 
 
 def _custom_insns(*insns):
@@ -61,17 +61,17 @@ def _custom_insns(*insns):
     def decorator(fn):
         FIELDS_ARG = object()
         if len(insns) == 0:
-            insns_ = (fn.__name__, (), {}),
+            insns_ = (fn.__name__, {}),
         else:
             insns_ = insns
-        for name, args, kwargs in insns_:
+        for name, kwargs in insns_:
             if not isinstance(name, str):
                 raise TypeError("instruction name must be a str: {name!r}")
             if name in CUSTOM_INSNS:
                 raise ValueError(f"duplicate instruction mnemonic: {name!r}")
             # use getcallargs to check that arguments work:
-            inspect.getcallargs(fn, FIELDS_ARG, *args, **kwargs)
-            CUSTOM_INSNS[name] = functools.partial(fn, *args, **kwargs)
+            inspect.getcallargs(fn, FIELDS_ARG, **kwargs)
+            CUSTOM_INSNS[name] = functools.partial(fn, **kwargs)
         return fn
     return decorator
 
@@ -153,12 +153,17 @@ def svshape(fields):
     It is *not* a 64-bit-prefixed Vector instruction (no sv.svshape, yet),
     it is a Vector *control* instruction.
 
+    https://libre-soc.org/openpower/sv/remap/#svshape
+
     * svshape SVxd,SVyd,SVzd,SVrm,vf
 
     # 1.6.33 SVM-FORM from fields.txt
     # |0     |6        |11      |16    |21    |25 |26    |31  |
     # | PO   |  SVxd   |   SVyd | SVzd | SVrm |vf |   XO      |
 
+    note that SVrm is not permitted to be 0b0111, 0b1000 or 0b1001.
+    0b0111 is reserved and 0b100- is for svshape2
+
     """
     PO = 22
     XO = 0b011001
@@ -166,6 +171,11 @@ def svshape(fields):
     SVxd -= 1
     SVyd -= 1
     SVzd -= 1
+
+    # check SVrm for reserved (and svshape2) values
+    assert SVrm not in [0b1000, 0b1001], \
+            "svshape reserved SVrm value %s" % bin(SVrm)
+
     return instruction(
         (PO, 0, 5),
         (SVxd, 6, 10),
@@ -177,6 +187,45 @@ def svshape(fields):
     )
 
 
+@_custom_insns()
+def svshape2(fields):
+    """
+    svshape2 is a *32-bit-only* instruction. It updates SVSHAPE and SVSTATE.
+    It is *not* a 64-bit-prefixed Vector instruction (no sv.svshape2, yet),
+    it is a Vector *control* instruction, and is a sort-of hybrid of
+    svshape and svindex, with the key important feature being the "offset".
+
+    https://libre-soc.org/openpower/sv/remap/discussion
+
+    * svshape2 SVo,SVM2yx,rmm,SVd,sk,mm
+
+    # 1.6.35.1 SVM2-FORM from fields.txt
+    # |0     |6     |10   |11      |16    |21 |24|25 |26    |31  |
+    # | PO   | SVo  |SVMyx|   rmm  | SVd  |XO |mm|sk |   XO      |
+
+    note that this fits into the space of svshape and that XO is
+    split across 2 areas.
+
+    """
+    PO = 22
+    XO = 0b011001
+    XO2 = 0b100 # not really XO2 but hey
+    (offs, yx, rmm, SVd, sk, mm) = fields
+    SVd -= 1 # offset by one
+
+    return instruction(
+        (PO, 0, 5),
+        (offs, 6, 9),  # offset (the whole point of adding svshape2)
+        (yx, 10, 10),  # like svindex
+        (rmm, 11, 15), # ditto svindex
+        (SVd, 16, 20), # ditto svindex
+        (XO2, 21, 23), # actually XO split across 2 places...
+        (mm, 24, 24),  # ditto svindex
+        (sk, 25, 25),  # ditto svindex
+        (XO, 26, 31),
+    )
+
+
 @_custom_insns()
 def svindex(fields):
     """
@@ -276,7 +325,7 @@ def fsins(fields, Rc):
     # |0     |6 |7|8|9  |10  |11|12|13  |15|16|17     |20|21    |31  |
     # | PO   |   FRT         |     ///     |   FRB       |   XO |Rc  |
     PO = 59
-    XO = 0b1000001110
+    XO = 0b1001001101
     (FRT, FRB) = fields
     return instruction(
         (PO, 0, 5),
@@ -299,7 +348,7 @@ def fcoss(fields, Rc):
     # |0     |6 |7|8|9  |10  |11|12|13  |15|16|17     |20|21    |31  |
     # | PO   |   FRT         |     ///     |   FRB       |   XO |Rc  |
     PO = 59
-    XO = 0b1000101110
+    XO = 0b1001101100
     (FRT, FRB) = fields
     return instruction(
         (PO, 0, 5),
@@ -581,7 +630,7 @@ def decode_imm(field):
         return None, field
 
 
-def crf_extra(etype, regmode, field, extras):
+def crf_extra(etype, rname, extra_idx, regmode, field, extras):
     """takes a CR Field number (CR0-CR127), splits into EXTRA2/3 and v3.0
     the scalar/vector mode (crNN.v or crNN.s) changes both the format
     of the EXTRA2/3 encoding as well as what range of registers is possible.
@@ -635,6 +684,9 @@ def to_number(field):
     return int(field)
 
 
+db = Database(find_wiki_dir())
+
+
 # decodes svp64 assembly listings and creates EXT001 svp64 prefixes
 class SVP64Asm:
     def __init__(self, lst, bigendian=False, macros=None):
@@ -831,7 +883,8 @@ class SVP64Asm:
             # encode SV-CR 3-bit field into extra, v3.0field.
             # 3-bit is for things like BF and BFA
             elif rtype == 'CR_3bit':
-                sv_extra, field = crf_extra(etype, regmode, field, extras)
+                sv_extra, field = crf_extra(etype, rname, extra_idx,
+                                            regmode, field, extras)
 
             # encode SV-CR 5-bit field into extra, v3.0field
             # 5-bit is for things like BA BB BC BT etc.
@@ -841,7 +894,8 @@ class SVP64Asm:
                 cr_subfield = field & 0b11  # record bottom 2 bits for later
                 field = field >> 2         # strip bottom 2 bits
                 # use the exact same 3-bit function for the top 3 bits
-                sv_extra, field = crf_extra(etype, regmode, field, extras)
+                sv_extra, field = crf_extra(etype, rname, extra_idx,
+                                            regmode, field, extras)
                 # reconstruct the actual 5-bit CR field (preserving the
                 # bottom 2 bits, unaltered)
                 field = (field << 2) | cr_subfield
@@ -868,7 +922,6 @@ class SVP64Asm:
         log("extras", extras)
 
         # rright. now we have all the info. start creating SVP64 instruction.
-        db = Database(find_wiki_dir())
         svp64_insn = SVP64Instruction.pair(prefix=0, suffix=0)
         svp64_prefix = svp64_insn.prefix
         svp64_rm = svp64_insn.prefix.rm
@@ -1106,15 +1159,17 @@ class SVP64Asm:
         """
             | 0-1 |  2  |  3   4  |  description              |
             | --- | --- |---------|-------------------------- |
-            | 00  |   0 |  dz  sz | normal mode                      |
+            | 00  |   0 |  dz  sz | simple mode                      |
             | 00  |   1 | 0  RG   | scalar reduce mode (mapreduce), SUBVL=1 |
-            | 00  |   1 | 1  /    | parallel reduce mode (mapreduce), SUBVL=1 |
-            | 00  |   1 | SVM RG  | subvector reduce mode, SUBVL>1   |
+            | 00  |   1 | SVM 0   | subvector reduce mode, SUBVL>1   |
+            | 00  |   1 | SVM 1   | Pack/Unpack mode, SUBVL>1   |
             | 01  | inv | CR-bit  | Rc=1: ffirst CR sel              |
             | 01  | inv | VLi RC1 |  Rc=0: ffirst z/nonz |
-            | 10  |   N | dz   sz |  sat mode: N=0/1 u/s |
+            | 10  |   N | dz   sz |  sat mode: N=0/1 u/s, SUBVL=1 |
+            | 10  |   N | zz   0  |  sat mode: N=0/1 u/s, SUBVL>1 |
+            | 10  |   N | zz   1  |  Pack/Unpack sat mode: N=0/1 u/s, SUBVL>1 |
             | 11  | inv | CR-bit  |  Rc=1: pred-result CR sel |
-            | 11  | inv | dz  RC1 |  Rc=0: pred-result z/nonz |
+            | 11  | inv | zz  RC1 |  Rc=0: pred-result z/nonz |
         """
 
         # https://libre-soc.org/openpower/sv/ldst/
@@ -1326,7 +1381,7 @@ class SVP64Asm:
             opcode |= int(v30b_newfields[1]) << (32-16)  # FRA
             opcode |= int(v30b_newfields[2]) << (32-21)  # FRB
             opcode |= int(v30b_newfields[3]) << (32-26)  # FRC
-            opcode |= 0b01111 << (32-31)   # bits 26-30
+            opcode |= 0b11011 << (32-31)   # bits 26-30
             if rc:
                 opcode |= 1  # Rc, bit 31.
             yield ".long 0x%x" % opcode
@@ -1336,7 +1391,7 @@ class SVP64Asm:
             opcode |= int(v30b_newfields[0]) << (32-11)  # FRT
             opcode |= int(v30b_newfields[1]) << (32-16)  # FRA
             opcode |= int(v30b_newfields[2]) << (32-21)  # FRB
-            opcode |= 0b01101 << (32-31)   # bits 26-30
+            opcode |= 0b1000001100 << (32-31)   # bits 21-30
             if rc:
                 opcode |= 1  # Rc, bit 31.
             yield ".long 0x%x" % opcode
@@ -1532,6 +1587,7 @@ if __name__ == '__main__':
         'sv.andi. *80, *80, 1',
         'sv.ffmadds. 6.v, 2.v, 4.v, 6.v',  # incorrectly inserted 32-bit op
         'sv.ffmadds 6.v, 2.v, 4.v, 6.v',  # correctly converted to .long
+        'svshape2 8, 1, 31, 7, 1, 1',
     ]
     isa = SVP64Asm(lst, macros=macros)
     log("list:\n", "\n\t".join(list(isa)))