add pcdec -- doesn't yet work due to broken ISACaller RT/RS output handling
authorJacob Lifshay <programmerjake@gmail.com>
Fri, 23 Sep 2022 03:05:35 +0000 (20:05 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Fri, 23 Sep 2022 03:23:49 +0000 (20:23 -0700)
12 files changed:
openpower/isa/prefix_codes.mdwn [new file with mode: 0644]
openpower/isatables/RM-1P-3S1D.csv
openpower/isatables/fields.text
openpower/isatables/minor_4.csv
src/openpower/decoder/isa/.gitignore
src/openpower/decoder/isa/caller.py
src/openpower/decoder/isa/test_caller_prefix_codes.py [new file with mode: 0644]
src/openpower/decoder/power_enums.py
src/openpower/sv/sv_analysis.py
src/openpower/sv/trans/svp64.py
src/openpower/test/prefix_codes/__init__.py [new file with mode: 0644]
src/openpower/test/prefix_codes/prefix_codes_cases.py [new file with mode: 0644]

diff --git a/openpower/isa/prefix_codes.mdwn b/openpower/isa/prefix_codes.mdwn
new file mode 100644 (file)
index 0000000..f89570a
--- /dev/null
@@ -0,0 +1,52 @@
+<!-- https://libre-soc.org/openpower/prefix_codes/ -->
+
+# [DRAFT] Prefix-code decode
+
+VA2-Form
+
+* pcdec RT,RA,RB,RC,once
+
+Pseudo-code:
+
+    tree[0:63] <- (RA)
+    rb_used <- 0b0
+    in_bits[0:63] <- (RC|0)
+    if in_bits = 0 then
+        in_bits[0:63] <- 1
+    final_in_bits <- in_bits
+    final_rb_used <- rb_used
+    output <- [0] * 64
+    out_byte <- 0
+    decoded[0:7] <- 1
+    so_bit <- 0b0
+    do while out_byte < 8
+        in_bit <- in_bits[63]
+        if in_bits = 1 then
+            if rb_used | (_RB = 0) then
+                leave
+            rb_used <- 0b1
+            in_bit <- (RB)[63]
+            in_bits <- 0b1 || (RB)[0:62]
+        else
+            in_bits <- 0b0 || in_bits[0:62]
+        # walk the binary tree in `tree` from parent to the selected child
+        decoded <- decoded[1:7] || in_bit
+        if decoded <u 64 then
+            if tree[63 - decoded] then
+                final_in_bits <- in_bits
+                final_rb_used <- rb_used
+                output[56 - 8 * out_byte:63 - 8 * out_byte] <- decoded
+                decoded[0:7] <- 1
+                out_byte <- out_byte + 1
+                if once then
+                    leave
+        else
+            so_bit <- 0b1
+            leave
+    RT <- output
+    RS <- final_in_bits
+    CR0 <- final_rb_used || 0b0 || (output = 0) || so_bit
+
+Special Registers Altered:
+
+    CR0
index 55634f360c316555df93ba5f63400996b9f54060..ebc6ce29040193803d354a87d1f7ece17791ad91 100644 (file)
@@ -36,6 +36,8 @@ maddhdu,NORMAL,,1P,EXTRA2,NO,d:RT,s:RA,s:RB,s:RC,RA,RB,RC,RT,0,0,0
 maddld,NORMAL,,1P,EXTRA2,NO,d:RT,s:RA,s:RB,s:RC,RA,RB,RC,RT,0,0,0
 absdacs,NORMAL,,1P,EXTRA2,NO,d:RT;d:CR0,s:RA,s:RB,s:RT,RA,RB,RT,RT,0,CR0,0
 absdacu,NORMAL,,1P,EXTRA2,NO,d:RT;d:CR0,s:RA,s:RB,s:RT,RA,RB,RT,RT,0,CR0,0
+pcdec,NORMAL,,1P,EXTRA2,NO,d:RT;d:CR0,s:RA,s:RB,s:RC,RA,RB,RC,RT,0,CR0,0
+pcdec,NORMAL,,1P,EXTRA2,NO,d:RT;d:CR0,s:RA,s:RB,s:RC,RA,RB,RC,RT,0,CR0,0
 ternlogi,NORMAL,,1P,EXTRA2,NO,d:RT;d:CR0,s:RA,s:RB,s:RT,RA,RB,RT,RT,0,CR0,0
 ffmsubs,NORMAL,,1P,EXTRA2,NO,d:FRT;d:CR1,s:FRA,s:FRB,s:FRC,FRA,FRB,FRC,FRT,0,CR1,0
 ffmadds,NORMAL,,1P,EXTRA2,NO,d:FRT;d:CR1,s:FRA,s:FRB,s:FRC,FRA,FRB,FRC,FRT,0,CR1,0
index 2d3cdb4743d158f383f08fa8d32e8181117d4c57..097eaf96e66dcc4701d409644c6c73a0194a093d 100644 (file)
     | PO    |  VRT |   VRA |   VRB | /|BFA|/ |   XO   |
 
 # 1.6.21.1 VA2-FORM
-    |0      |6     |11     |16     |21  |24|26   |31|
-    | PO    |  RT  |   RA  |   RB  | RC    | XO  |Rc|
+    |0      |6     |11     |16     |21  |24|26  |31  |
+    | PO    |  RT  |   RA  |   RB  | RC    | XO | Rc |
+    | PO    |  RT  |   RA  |   RB  | RC    | XO |once|
 
 # 1.6.22 VC-FORM
     |0      |6     |11     |16     |21|22   |31|
         Field used by XO-form instructions to enable set-
         ting OV and SO in the XER.
         Formats: XO
+    once (31)
+        Once bit. Used by Prefix-code encode/decode instructions.
+        0    Decode/Encode multiple times per instruction.
+        1    Only Decode once per instruction
+        Formats: VA2
     PO (0:5)
         Primary opcode field.
         Formats: all
index 4a4ba21d699662d1b9c07ded6591ef4687cbbff0..75893e674a5743b3c5039a544f2a90363c24c0e6 100644 (file)
@@ -4,3 +4,5 @@ opcode,unit,internal op,in1,in2,in3,out,CR in,CR out,inv A,inv out,cry in,cry ou
 48,ALU,OP_MADDHD,RA,RB,RC,RT,NONE,NONE,0,0,ZERO,0,NONE,0,0,0,0,1,0,NONE,0,0,maddhd,VA,,,
 49,ALU,OP_MADDHDU,RA,RB,RC,RT,NONE,NONE,0,0,ZERO,0,NONE,0,0,0,0,1,0,NONE,0,0,maddhdu,VA,,,
 51,ALU,OP_MADDLD,RA,RB,RC,RT,NONE,NONE,0,0,ZERO,0,NONE,0,0,0,0,1,0,NONE,0,0,maddld,VA,,,
+56,ALU,OP_PCDEC,RA,RB,RC,RT,NONE,CR0,0,0,ZERO,0,NONE,0,0,0,0,1,0,NONE,0,0,pcdec,VA2,,1,unofficial until submitted and approved/renumbered by the opf isa wg
+57,ALU,OP_PCDEC,RA,RB,RC,RT,NONE,CR0,0,0,ZERO,0,NONE,0,0,0,0,1,0,NONE,0,0,pcdec,VA2,,1,unofficial until submitted and approved/renumbered by the opf isa wg
index 2e898065a51df5f100ecfbc48f99277c8a468c42..77066ad8709b55a2597a8bcf1e39542ca43651ef 100644 (file)
@@ -28,5 +28,6 @@
 /svfixedload.py
 /svfparith.py
 /svfpload.py
+/prefix_codes.py
 *.orig
 *.rej
index 0edca8ad8ad0eee1de0b39c03454779770092ef0..a1dc8197ea291eb1809b9867f65fce2da1a4fda4 100644 (file)
@@ -1486,7 +1486,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
                        'svshape', 'svshape2',
                        'grev', 'ternlogi', 'bmask', 'cprop',
                        'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd',
-                       'fmvis', 'fishmv',
+                       'fmvis', 'fishmv', 'pcdec'
                        ]:
             illegal = False
             ins_name = dotstrp
diff --git a/src/openpower/decoder/isa/test_caller_prefix_codes.py b/src/openpower/decoder/isa/test_caller_prefix_codes.py
new file mode 100644 (file)
index 0000000..3918a3e
--- /dev/null
@@ -0,0 +1,25 @@
+""" prefix-codes tests
+"""
+
+import unittest
+from openpower.test.runner import TestRunnerBase
+from openpower.test.prefix_codes.prefix_codes_cases import PrefixCodesCases
+
+# writing the test_caller invocation this way makes it work with pytest
+
+
+# FIXME: fails because ISACaller can't currently handle writing to
+# both RT and RS
+@unittest.expectedFailure
+class TestPrefixCodes(TestRunnerBase):
+    def __init__(self, test):
+        assert test == 'test'
+        super().__init__(PrefixCodesCases().test_data)
+
+    def test(self):
+        # dummy function to make unittest try to test this class
+        pass
+
+
+if __name__ == "__main__":
+    unittest.main()
index 6698de5db10d6614fce649e2b1c4697ada0fb6fe..f2b47f2f42ddb4cfb065045179d03de4bea47f93 100644 (file)
@@ -549,6 +549,7 @@ _insns = [
     "nand", "neg", "nego",
     "nop",
     "nor", "or", "orc", "ori", "oris",
+    "pcdec",
     "popcntb", "popcntd", "popcntw",
     "prtyd", "prtyw",
     "rfid",
@@ -692,6 +693,7 @@ class MicrOp(Enum):
     OP_SVINDEX = 95
     OP_FMVIS = 96
     OP_FISHMV = 97
+    OP_PCDEC = 98
 
 
 @unique
index b64ef7405b8259a2e76bd67195812816093f9b62..9b030098735e2e8d2c936a4792d6ef138e691785 100644 (file)
@@ -602,6 +602,11 @@ def extra_classifier(insn_name, value, name, res, regs):
             res['1'] = 's:RA'  # RA: Rsrc1_EXTRA2
             res['2'] = 's:RB'  # RT: Rsrc2_EXTRA2
             res['3'] = 's:RC'  # RT: Rsrc3_EXTRA2
+        elif regs == ['RA', 'RB', 'RC', 'RT', '', 'CR0']:  # pcdec
+            res['0'] = 'd:RT;d:CR0'  # RT,CR0: Rdest1_EXTRA2
+            res['1'] = 's:RA'  # RA: Rsrc1_EXTRA2
+            res['2'] = 's:RB'  # RT: Rsrc2_EXTRA2
+            res['3'] = 's:RC'  # RT: Rsrc3_EXTRA2
         elif regs == ['RA', 'RB', 'RT', 'RT', '', 'CR0']:  # overwrite 3-in
             res['0'] = 'd:RT;d:CR0'  # RT,CR0: Rdest1_EXTRA2
             res['1'] = 's:RA'  # RA: Rsrc1_EXTRA2
index a5aa7293610e135b4476d02f4bf3446ea49e04e0..20012c2fce44890a8bed1aaedb0ffb4ece319352 100644 (file)
@@ -564,6 +564,25 @@ def fishmv(fields):
     )
 
 
+@_custom_insns()
+def pcdec(fields):
+    # 1.6.21.1 VA2-FORM
+    #    |0      |6     |11     |16     |21  |24|26  |31  |
+    #    | PO    |  RT  |   RA  |   RB  | RC    | XO |once|
+    PO = 4
+    XO = 0b11100
+    (RT, RA, RB, RC, once) = fields
+    return instruction(
+        (PO, 0, 5),
+        (RT, 6, 10),
+        (RA, 11, 15),
+        (RB, 16, 20),
+        (RC, 21, 25),
+        (XO, 26, 30),
+        (once, 31, 31),
+    )
+
+
 # decode GPR into sv extra
 def get_extra_gpr(etype, regmode, field):
     if regmode == 'scalar':
diff --git a/src/openpower/test/prefix_codes/__init__.py b/src/openpower/test/prefix_codes/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/openpower/test/prefix_codes/prefix_codes_cases.py b/src/openpower/test/prefix_codes/prefix_codes_cases.py
new file mode 100644 (file)
index 0000000..86d54b8
--- /dev/null
@@ -0,0 +1,44 @@
+from openpower.test.common import TestAccumulatorBase
+from openpower.sv.trans.svp64 import SVP64Asm
+from openpower.test.state import ExpectedState
+from openpower.simulator.program import Program
+
+
+def tree_code(code):
+    # type: (str) -> int
+    retval = 1
+    for bit in reversed(code):
+        assert bit in "01"
+        retval = retval * 2 + int(bit)
+    return retval
+
+
+def make_tree(*codes):
+    # type: (*str) -> int
+    retval = 0
+    for code in codes:
+        retval |= 1 << tree_code(code)
+    return retval
+
+
+def code_seq(*codes, prefix1=False):
+    # type: (*str, bool) -> int
+    prefix = "0b1" if prefix1 else "0b"
+    return int(prefix + "".join(reversed(codes)), base=0)
+
+
+class PrefixCodesCases(TestAccumulatorBase):
+    def case_pcdec_simple(self):
+        lst = list(SVP64Asm(["pcdec 4,6,7,5,0"]))
+        gprs = [0] * 32
+        gpr5_codes = ["0", "11", "1001", "101010"]
+        gpr7_codes = ["1001"] * 8 + ["101010", "11"] * 4
+        gprs[5] = code_seq(*gpr5_codes, prefix1=True)
+        gprs[6] = make_tree("0", "11", "1001", "101010")
+        gprs[7] = code_seq(*gpr7_codes)
+        e = ExpectedState(pc=4, int_regs=gprs)
+        e.intregs[4] = int.from_bytes(
+            map(tree_code, (gpr5_codes + gpr7_codes)[:8]), 'little')
+        e.intregs[5] = code_seq(*(gpr5_codes + gpr7_codes)[8:], prefix1=True)
+        e.crregs[0] = 0b1000
+        self.add_case(Program(lst, False), gprs, expected=e)