bug 1034: add crternlogi. involved adding a new CR field BFA_BFB_BF sigh
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Wed, 17 Jan 2024 14:56:16 +0000 (14:56 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Wed, 17 Jan 2024 14:56:16 +0000 (14:56 +0000)
openpower/isa/bitmanip.mdwn
openpower/isatables/fields.text
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/decoder/power_svp64.py
src/openpower/insndb/core.py
src/openpower/test/bitmanip/bitmanip_cases.py

index 1f8081d7a2df09c165c982f668f52dc08f4fdec4..88fa79ea8cff4e93d6090424f470e3dcdc600425 100644 (file)
@@ -40,6 +40,30 @@ Special Registers Altered:
 
     CR0                    (if Rc=1)
 
+# Condition Register Ternary Bitwise Logic Immediate
+
+CRB-Form
+
+* crternlogi BF,BFA,BFB,TLI,msk
+
+Pseudo-code:
+
+    bf <- CR[4*BF+32:4*BF+35]
+    bfa <- CR[4*BFA+32:4*BFA+35]
+    bfb <- CR[4*BFB+32:4*BFB+35]
+
+    result <- [0] * 4
+    do i = 0 to 3
+      idx <- bf[i] || bfa[i] || bfb[i]
+      result[i] <- TLI[7-idx]
+    do i = 0 to 3
+        if msk[i] = 1 then
+            CR[4*BF+32+i] <- result[i]
+
+Special Registers Altered:
+
+     CR field BF
+
 # Add With Shift By Immediate
 
 Z23-Form
index 1edbb6a5ea5333e0eae3d1e9d4e0c66132c41e6c..5554ed5e848f92dc0cdac610411f2373697ad953 100644 (file)
     BF (6:8)
          Field used to specify one of the CR fields or one of
          the FPSCR fields to be used as a target.
-         Formats: D, X, XL, XX2, XX3, Z22
+         Formats: D, X, XL, XX2, XX3, Z22, CRB
     BFA (22:24)
          Field used to specify one of the CR fields 
          to be used as a source.
     BFA (11:13)
          Field used to specify one of the CR fields or one of
          the FPSCR fields to be used as a source.
-         Formats: X, XL
+         Formats: X, XL, CRB
+    BFB (16:18)
+         Field used to specify one of the CR fields
+         to be used as a source.
+         Formats: CRB
     BH (19:20)
          Field used to specify a hint in the Branch Condi-
          tional to Link Register and Branch Conditional to
index 742d7b69c0f72551afb4fcba16102ff3b52bc929..bcc96fd27fe33ab11a2ee8dfe439241ff81a19e1 100644 (file)
@@ -1,2 +1,3 @@
 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,RC_ONLY,0,0,ternlogi,TLI,,1,unofficial until submitted and approved/renumbered by the opf isa wg
+--------01-,CR,OP_CRTERNLOG,NONE,NONE,NONE,NONE,BFA_BFB_BF,BF,0,0,ZERO,0,NONE,0,0,0,0,0,0,NONE,0,0,crternlogi,CRB,,1,unofficial until submitted and approved/renumbered by the opf isa wg
index 8e476a289be52a6d43a317f3d2ce9944bdd51df8..dd0b3f263b9c4112b944c946d3f55fa6f56470bf 100644 (file)
@@ -1652,7 +1652,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
             # these are all opcode fields involved in index-selection of CR,
             # and need to do "standard" arithmetic.  CR[BA+32] for example
             # would, if using SelectableInt, only be 5-bit.
-            if name in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']:
+            if name in ['BF', 'BFA', 'BFB', 'BC', 'BA', 'BB', 'BT', 'BI']:
                 self.namespace[name] = val
             else:
                 self.namespace[name] = SelectableInt(val, sig.width)
@@ -2275,7 +2275,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
                        "brh", "brw", "brd",
                        'setvl', 'svindex', 'svremap', 'svstep',
                        'svshape', 'svshape2',
-                       'ternlogi', 'bmask', 'cprop', 'gbbd',
+                       'crternlogi', 'ternlogi', 'bmask', 'cprop', 'gbbd',
                        'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd',
                        'fmvis', 'fishmv', 'pcdec', "maddedu", "divmod2du",
                        "dsld", "dsrd", "maddedus",
index b73fbe761e311e75402de7e8e981a3dff04e8aa4..9e3bca4aa345b1ed676f15e6d9d67da6af44fddb 100644 (file)
@@ -654,6 +654,13 @@ class DecodeCRIn(Elaboratable):
                 comb += self.cr_bitfield_b.ok.eq(1)
                 comb += self.cr_bitfield_o.data.eq(self.dec.BT[2:5])
                 comb += self.cr_bitfield_o.ok.eq(1)
+            with m.Case(CRInSel.BFA_BFB_BF):
+                comb += self.cr_bitfield.data.eq(self.dec.FormCRB.BFA)
+                comb += self.cr_bitfield.ok.eq(1)
+                comb += self.cr_bitfield_b.data.eq(self.dec.FormCRB.BFB)
+                comb += self.cr_bitfield_b.ok.eq(1)
+                comb += self.cr_bitfield_o.data.eq(self.dec.FormCRB.BF)
+                comb += self.cr_bitfield_o.ok.eq(1)
             with m.Case(CRInSel.BC):
                 comb += self.cr_bitfield.data.eq(self.dec.BC[2:5])
                 comb += self.cr_bitfield.ok.eq(1)
@@ -1543,7 +1550,7 @@ class PowerDecode2(PowerDecodeSubset):
                 (e.read_cr1, self.dec_cr_in, "cr_bitfield", ),
                 (e.read_cr2, self.dec_cr_in, "cr_bitfield_b", ),
                 (e.read_cr3, self.dec_cr_in, "cr_bitfield_o", ),
-                    (e.write_cr, self.dec_cr_out, "cr_bitfield", )):
+                (e.write_cr, self.dec_cr_out, "cr_bitfield", )):
                 fromreg = getattr(cr, name)
                 comb += to_reg.data.eq(fromreg.data)
                 comb += to_reg.ok.eq(fromreg.ok)
index c0c1ddcacdb8bb48762caf9e460fb090cc63c40e..e6876f62ebca3972ed7777ce8f757c3c335be563 100644 (file)
@@ -278,6 +278,7 @@ class Reg(Enum):
     CR1 = auto()
     BF = auto()
     BFA = auto()
+    BFB = auto()
     BA = auto()
     BB = auto()
     BC = auto()
@@ -652,6 +653,7 @@ class RegType(Enum):
     CR_3BIT = 2 # CR field; the CR register is 32-bit
     BF = CR_3BIT
     BFA = CR_3BIT
+    BFB = CR_3BIT
 
     CR_5BIT = 3 # bit of the 32-bit CR register
     BA = CR_5BIT
@@ -747,6 +749,7 @@ _insns = [
     "cprop", # AV bitmanip
     "crand", "crandc", "creqv",
     "crnand", "crnor", "cror", "crorc", "crxor",
+    "crternlogi", # ternary bitmanip
     "darn",
     "dcbf", "dcbst", "dcbt", "dcbtst", "dcbz",
     "divd", "divde", "divdeo", "divdeu",
@@ -965,6 +968,7 @@ class MicrOp(Enum):
     OP_PEXT = 110
     OP_SETBC = 111
     OP_BMAT = 112 # bmatflip/xor/and - known by many names (vgbbd in Power)
+    OP_CRTERNLOG = 113
 
 
 class SelType(Enum):
@@ -1138,6 +1142,7 @@ class CRInSel(Enum):
     WHOLE_REG = 6
     CR1 = 7
     BA = 8
+    BFA_BFB_BF = 9
 
     def __str__(self):
         return self.name
index 5c36f03e1556ae5857e59c820fd1ec2600ee7ff9..97463b6a606072281749ce77ae32da6fee1cbf05 100644 (file)
@@ -8,7 +8,7 @@ import os
 
 # identifies register by type
 def is_CR_3bit(regname):
-    return regname in ['BF', 'BFA']
+    return regname in ['BF', 'BFA', 'BFB']
 
 def is_CR_5bit(regname):
     return regname in ['BA', 'BB', 'BC', 'BI', 'BT']
@@ -155,6 +155,11 @@ class SVP64RM:
                 index1 = svp64_src.get('BA', None)
                 index2 = svp64_src.get('BB', None)
                 entry['sv_cr_in'] = "Idx_%d_%d" % (index1, index2)
+            elif cr_in == 'BFA_BFB_BF':
+                index1 = svp64_src.get('BFA', None)
+                index2 = svp64_src.get('BFB', None)
+                index3 = svp64_src.get('BF', None)
+                entry['sv_cr_in'] = "Idx_%d_%d_%d" % (index1, index2, index3)
 
             # CRout a lot easier.  ignore WHOLE_REG for now
             cr_out = entry['CR out']
index f441cf8bada4ad875800f68f5cf3e2874cced6c1..4a7f4feb5ad9e92320c5b14e77002a684974dc67 100644 (file)
@@ -391,6 +391,11 @@ class SVP64Record(Dataclass):
             record["cr_in"] = "BA"
             record["cr_in2"] = "BB"
             del record["CR in"]
+        elif record["CR in"] == "BFA_BFB_BF":
+            record["cr_in"] = "BFA"
+            record["cr_in2"] = "BFB"
+            #record["cr_out"] = "BF" # only use BFA_BFB_BF when BF is a dest
+            del record["CR in"]
 
         extra = []
         for idx in range(0, 4):
@@ -458,6 +463,15 @@ class SVP64Record(Dataclass):
                 regs[key] = _Reg(sels[key])
                 seltype[key] = _SelType.SRC
 
+        # should only be used when BF is also a destination
+        if sels["cr_in"] is _CRInSel.BFA_BFB_BF:
+            sels["cr_in"] = _CRIn2Sel.BFA
+            sels["cr_in2"] = _CRIn2Sel.BFB
+            idxs["cr_in2"] = idxs["cr_in"]
+            for key in ("cr_in", "cr_in2"):
+                regs[key] = _Reg(sels[key])
+                seltype[key] = _SelType.SRC
+
         records = {}
         for key in keys:
             records[key] = {
index e9f6bb46e2b10bcf42625ffe6a54364ac71c20d1..ba685b2e5e99724eb8e574343926a2f2ffdbb8b7 100644 (file)
@@ -4,7 +4,7 @@ from openpower.endian import bigendian
 from openpower.simulator.program import Program
 from openpower.test.state import ExpectedState
 from nmutil.sim_util import hash_256
-from openpower.decoder.isa.caller import SVP64State
+from openpower.decoder.isa.caller import SVP64State, CRFields
 from openpower.util import log
 import struct
 import itertools
@@ -32,6 +32,54 @@ class BitManipTestCase(TestAccumulatorBase):
 
         self.add_case(Program(lst, bigendian), initial_regs, expected=e)
 
+    def do_case_crternlogi(self, bf, bfa, bfb, imm, mask):
+        lst = [f"crternlogi 3,4,5,%d,%d" % (imm, mask)]
+        # set up CR
+        bf %= 2 ** 4
+        bfa %= 2 ** 4
+        bfb %= 2 ** 4
+        cr = CRFields()
+        cr.crl[3][0:4] = bf
+        cr.crl[4][0:4]  = bfa
+        cr.crl[5][0:4]  = bfb
+        initial_cr = cr.cr.asint()
+        print("initial cr", bin(initial_cr), bf, bfa, bfb)
+        print("mask tli", bin(mask), bin(imm))
+
+        lst = list(SVP64Asm(lst, bigendian))
+        e = ExpectedState(pc=4)
+        expected = bf&~mask # start at BF, mask overwrites masked bits only
+        checks = (bfb, bfa, bf) # LUT positions 1<<0=bfb 1<<1=bfa 1<<2=bf
+        for i in range(4):
+            lut_index = 0
+            for j, check in enumerate(checks):
+                if check & (1<<i):
+                    lut_index |= 1<<j
+            maskbit = (mask >> i) & 0b1
+            if (imm & (1<<lut_index)) and maskbit:
+                expected |= 1<<i
+        e.crregs[3] = expected
+        e.crregs[4] = bfa
+        e.crregs[5] = bfb
+        self.add_case(Program(lst, bigendian), initial_regs=None, expected=e,
+                                       initial_cr=initial_cr)
+
+    def case_crternlogi_0(self):
+        self.do_case_crternlogi(0b1111,
+                                0b1100,
+                                0b1010,
+                                0x80, 0b1111)
+
+    def case_crternlogi_random(self):
+        for i in range(100):
+            rc = bool(hash_256(f"crternlogi rc {i}") & 1)
+            imm = hash_256(f"crternlogi imm {i}") & 0xFF
+            bf = hash_256(f"crternlogi bf {i}") % 2 ** 4
+            bfa = hash_256(f"crternlogi bfa {i}") % 2 ** 4
+            bfb = hash_256(f"crternlogi bfb {i}") % 2 ** 4
+            msk = hash_256(f"crternlogi msk {i}") % 2 ** 4
+            self.do_case_crternlogi(bf, bfa, bfb, imm, msk)
+
     def do_case_ternlogi(self, rc, rt, ra, rb, imm):
         rc_dot = "." if rc else ""
         lst = [f"ternlogi{rc_dot} 3, 4, 5, {imm}"]