grev[w][i][.] pseudo-code works
authorJacob Lifshay <programmerjake@gmail.com>
Tue, 18 Jan 2022 04:58:03 +0000 (20:58 -0800)
committerJacob Lifshay <programmerjake@gmail.com>
Tue, 18 Jan 2022 04:58:03 +0000 (20:58 -0800)
openpower/isa/bitmanip.mdwn
openpower/isatables/minor_5.csv
src/openpower/decoder/isa/caller.py
src/openpower/decoder/power_decoder2.py
src/openpower/decoder/power_enums.py
src/openpower/sv/trans/svp64.py
src/openpower/test/bitmanip/bitmanip_cases.py

index 3f73b0b894583e8cfb2b871988c5b593f6412382..b2b0ad8b638d35ad966410d31365f963f5acbee8 100644 (file)
@@ -29,8 +29,9 @@ X-Form
 Pseudo-code:
 
     result <- [0] * XLEN
+    b <- EXTZ64(RB)
     do i = 0 to XLEN - 1
-      idx <- ((RB) ^ i) % XLEN
+      idx <- b[64-log2(XLEN):63] ^ i
       result[i] <- (RA)[idx]
     RT <- result
 
@@ -49,7 +50,7 @@ Pseudo-code:
 
     result <- [0] * XLEN
     do i = 0 to XLEN - 1
-      idx <- (XBI ^ i) % XLEN
+      idx <- XBI[6-log2(XLEN):5] ^ i
       result[i] <- (RA)[idx]
     RT <- result
 
@@ -66,11 +67,13 @@ X-Form
 
 Pseudo-code:
 
-    result <- [0] * XLEN # MSB half just stays zeroed
+    result <- [0] * (XLEN / 2)
+    a <- (RA)[XLEN/2:XLEN-1]
+    b <- EXTZ64(RB)
     do i = 0 to XLEN / 2 - 1
-      idx <- ((RB) ^ i) % (XLEN / 2)
-      result[i] <- (RA)[idx]
-    RT <- result
+      idx <- b[64-log2(XLEN/2):63] ^ i
+      result[i] <- a[idx]
+    RT <- ([0] * (XLEN / 2)) || result
 
 Special Registers Altered:
 
@@ -85,11 +88,12 @@ X-Form
 
 Pseudo-code:
 
-    result <- [0] * XLEN # MSB half just stays zeroed
+    result <- [0] * (XLEN / 2)
+    a <- (RA)[XLEN/2:XLEN-1]
     do i = 0 to XLEN / 2 - 1
-      idx <- (SH ^ i) % (XLEN / 2)
-      result[i] <- (RA)[idx]
-    RT <- result
+      idx <- SH[5-log2(XLEN/2):4] ^ i
+      result[i] <- a[idx]
+    RT <- ([0] * (XLEN / 2)) || result
 
 Special Registers Altered:
 
index ec0cbc1781c2fcb548173b0381ca85226d366ee1..c0260dbf65e18ac3d4c1abe623becf5c77159810 100644 (file)
@@ -1,6 +1,6 @@
 opcode,unit,internal op,in1,in2,in3,out,CR in,CR out,inv A,inv out,cry in,cry out,ldst len,BR,sgn ext,upd,rsrv,32b,sgn,rc,lk,sgl pipe,comment,form,CONDITIONS,unofficial,comment2
 --------00-,SHIFT_ROT,OP_TERNLOG,RA,RB,RT,RT,NONE,CR0,0,0,ZERO,0,NONE,0,0,0,0,0,0,NONE,0,0,ternlogi,TLI,,1,unofficial until submitted and approved/renumbered by the opf isa wg
-0010010110-,SHIFT_ROT,OP_GREV,RA,RB,NONE,RT,NONE,CR0,0,0,ZERO,0,NONE,0,0,0,0,0,0,NONE,0,0,grev,X,,1,unofficial until submitted and approved/renumbered by the opf isa wg
--011010110-,SHIFT_ROT,OP_GREV,RA,CONST_XBI,NONE,RT,NONE,CR0,0,0,ZERO,0,NONE,0,0,0,0,0,0,NONE,0,0,grevi,XB,,1,unofficial until submitted and approved/renumbered by the opf isa wg
-0010110110-,SHIFT_ROT,OP_GREV,RA,RB,NONE,RT,NONE,CR0,0,0,ZERO,0,NONE,0,0,0,0,1,0,NONE,0,0,grevw,X,,1,unofficial until submitted and approved/renumbered by the opf isa wg
-0011110110-,SHIFT_ROT,OP_GREV,RA,CONST_SH32,NONE,RT,NONE,CR0,0,0,ZERO,0,NONE,0,0,0,0,1,0,NONE,0,0,grevwi,X,,1,unofficial until submitted and approved/renumbered by the opf isa wg
+0010010110-,SHIFT_ROT,OP_GREV,RA,RB,NONE,RT,NONE,CR0,0,0,ZERO,0,NONE,0,0,0,0,0,0,RC,0,0,grev,X,,1,unofficial until submitted and approved/renumbered by the opf isa wg
+-011010110-,SHIFT_ROT,OP_GREV,RA,CONST_XBI,NONE,RT,NONE,CR0,0,0,ZERO,0,NONE,0,0,0,0,0,0,RC,0,0,grevi,XB,,1,unofficial until submitted and approved/renumbered by the opf isa wg
+0010110110-,SHIFT_ROT,OP_GREV,RA,RB,NONE,RT,NONE,CR0,0,0,ZERO,0,NONE,0,0,0,0,1,0,RC,0,0,grevw,X,,1,unofficial until submitted and approved/renumbered by the opf isa wg
+0011110110-,SHIFT_ROT,OP_GREV,RA,CONST_SH32,NONE,RT,NONE,CR0,0,0,ZERO,0,NONE,0,0,0,0,1,0,RC,0,0,grevwi,X,,1,unofficial until submitted and approved/renumbered by the opf isa wg
index a4b39ef1ddf01d57461af2b042b354de319a9726..804da2a43cc5d95ab09de2a4cacbe1eac6a7501d 100644 (file)
@@ -13,6 +13,7 @@ related bugs:
 * https://bugs.libre-soc.org/show_bug.cgi?id=424
 """
 
+import re
 from nmigen.back.pysim import Settle
 from functools import wraps
 from copy import copy, deepcopy
@@ -1252,7 +1253,8 @@ class ISACaller(ISACallerHelper, ISAFPHelpers):
             illegal = False
             ins_name = 'ffadds'
 
-        if asmop == 'ternlogi':
+        if asmop == 'ternlogi' \
+            or re.fullmatch(r'grevw?i?\.?', asmop or ''):
             illegal = False
             ins_name = asmop
 
index a636fdf5160cbfa680cdbf8ea36bced0304ca7f7..a8ff85329a73f3d217dac2f0c22e9bdf1d0479b9 100644 (file)
@@ -575,7 +575,7 @@ class DecodeOE(Elaboratable):
                         MicrOp.OP_SHL, MicrOp.OP_SHR, MicrOp.OP_RLC,
                         MicrOp.OP_LOAD, MicrOp.OP_STORE,
                         MicrOp.OP_RLCL, MicrOp.OP_RLCR,
-                        MicrOp.OP_EXTSWSLI):
+                        MicrOp.OP_EXTSWSLI, MicrOp.OP_GREV):
                 pass
 
             # all other ops decode OE field
index 757df322760cc7de59d1d91045b861dab11433f3..a0f85b586b28e2ef1a5e5d71ad8195ef0ad982df 100644 (file)
@@ -284,6 +284,8 @@ _insns = [
     "fmul", "fmuls", "fdiv", "fdivs",                   # FP mul / div
     "fmr", "fabs", "fnabs", "fneg", "fcpsgn",           # FP move/abs/neg
     "fsins", "fcoss",                                   # FP SIN/COS
+    'grev', 'grev.', 'grevi', 'grevi.',
+    'grevw', 'grevw.', 'grevwi', 'grevwi.',
     "hrfid", "icbi", "icbt", "isel", "isync",
     "lbarx", "lbz", "lbzcix", "lbzu", "lbzux", "lbzx",  # load byte
     "ld", "ldarx", "ldbrx", "ldu", "ldux", "ldx",       # load double
index 29bfadad37bb6d12acfed43ca8c292601c948b78..65aa1768fc2cff1a615bbd27c33babdb1a96099b 100644 (file)
@@ -297,6 +297,38 @@ class SVP64Asm:
             yield f".4byte {hex(instr)} # {asm}"
             return
 
+        # XXX WARNING THESE ARE NOT APPROVED BY OPF ISA WG
+        # however we are out of space with opcode 22
+        if opcode in ('grev', 'grevi', 'grevw', 'grevwi',
+                      'grev.', 'grevi.', 'grevw.', 'grevwi.'):
+            po = 5
+            # _ matches fields in table at:
+            # https://libre-soc.org/openpower/sv/bitmanip/
+            xo = 0b1_0010_110
+            if 'w' in opcode:
+                xo |= 0b100_000
+            if 'i' in opcode:
+                xo |= 0b1000_000
+            Rc = 1 if '.' in opcode else 0
+            rt = int(fields[0])
+            ra = int(fields[1])
+            rb_imm = int(fields[2])
+            instr = po
+            instr = (instr << 5) | rt
+            instr = (instr << 5) | ra
+            if opcode == 'grevi' or opcode == 'grevi.':
+                assert 0 <= rb_imm < 64
+                instr = (instr << 6) | rb_imm
+                instr = (instr << 9) | xo
+            else:
+                assert 0 <= rb_imm < 32
+                instr = (instr << 5) | rb_imm
+                instr = (instr << 10) | xo
+            instr = (instr << 1) | Rc
+            asm = f"{opcode} {rt}, {ra}, {rb_imm}"
+            yield f".4byte {hex(instr)} # {asm}"
+            return
+
         # identify if is a svp64 mnemonic
         if not opcode.startswith('sv.'):
             yield insn  # unaltered
index f38e06665dc211dd5ba816be1ed19fa629787069..0fcb0d7139e33fdf3fd84851f6877ff925b5a084 100644 (file)
@@ -34,6 +34,36 @@ class BitManipTestCase(TestAccumulatorBase):
         e.intregs[5] = rb
         self.add_case(Program(lst, bigendian), initial_regs, expected=e)
 
+    def do_case_grev(self, w, is_imm, ra, rb):
+        bits = 32 if w else 64
+        masked_rb = rb % bits
+        if is_imm:
+            lst = [f"grev{'w' if w else ''}i. 3, 4, {masked_rb}"]
+        else:
+            lst = [f"grev{'w' if w else ''}. 3, 4, 5"]
+        initial_regs = [0] * 32
+        ra %= 2 ** 64
+        rb %= 2 ** 64
+        initial_regs[4] = ra
+        initial_regs[5] = rb
+        lst = list(SVP64Asm(lst, bigendian))
+        e = ExpectedState(pc=4)
+        expected = 0
+        for i in range(bits):
+            dest_bit = i ^ masked_rb
+            if ra & 2 ** i:
+                expected |= 2 ** dest_bit
+        e.intregs[3] = expected
+        e.intregs[4] = ra
+        e.intregs[5] = rb
+        if expected & 2 ** 63:  # sign extend
+            expected -= 2 ** 64
+        eq = expected == 0
+        gt = expected > 0
+        lt = expected < 0
+        e.crregs[0] = (eq << 1) | (gt << 2) | (lt << 3)
+        self.add_case(Program(lst, bigendian), initial_regs, expected=e)
+
     def case_ternlogi_0(self):
         self.do_case_ternlogi(0x8000_0000_FFFF_0000,
                               0x8000_0000_FF00_FF00,
@@ -49,3 +79,21 @@ class BitManipTestCase(TestAccumulatorBase):
             ra = hash_256(f"ternlogi ra {i}") % 2 ** 64
             rb = hash_256(f"ternlogi rb {i}") % 2 ** 64
             self.do_case_ternlogi(rt, ra, rb, imm)
+
+    def case_grev_random(self):
+        for i in range(100):
+            w = hash_256(f"grev w {i}") & 1
+            is_imm = hash_256(f"grev is_imm {i}") & 1
+            ra = hash_256(f"grev ra {i}") % 2 ** 64
+            rb = hash_256(f"grev rb {i}") % 2 ** 64
+            self.do_case_grev(w, is_imm, ra, rb)
+
+    def case_grevi_1(self):
+        self.do_case_grev(False, True, 14361919363078703450,
+                          8396479064514513069)
+
+    def case_grevi_2(self):
+        self.do_case_grev(True, True, 397097147229333315, 8326716970539357702)
+
+    def case_grevi_3(self):
+        self.do_case_grev(True, True, 0xFFFF_FFFF_0000_0000, 6)