move HASK, ROTL32, ROTL64, MASK32, into helper class
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 21 Oct 2022 11:29:33 +0000 (12:29 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 2 Jun 2023 18:51:15 +0000 (19:51 +0100)
src/openpower/decoder/helpers.py

index ba576b1352652e878c3b4ddb703a93666d2a65b0..ea3b659a5db7b3f44461900b8d605f4bc75c0525 100644 (file)
@@ -97,46 +97,6 @@ def SHL64(value, bits, wordlen=64):
     return SelectableInt((value << bits) & mask, 64)
 
 
-def ROTL64(value, bits):
-    return rotl(value, bits, 64)
-
-
-def ROTL32(value, bits):
-    if isinstance(bits, SelectableInt):
-        bits = bits.value
-    if isinstance(value, SelectableInt):
-        value = SelectableInt(value.value, 64)
-    return rotl(value | (value << 32), bits, 64)
-
-
-def MASK32(x, y):
-    if isinstance(x, SelectableInt):
-        x = x.value
-    if isinstance(y, SelectableInt):
-        y = y.value
-    return MASK(x+32, y+32)
-
-
-def MASK(x, y, lim=64):
-    if isinstance(x, SelectableInt):
-        x = x.value
-    if isinstance(y, SelectableInt):
-        y = y.value
-    if x < y:
-        x = lim-x
-        y = (lim-1)-y
-        mask_a = ((1 << x) - 1) & ((1 << lim) - 1)
-        mask_b = ((1 << y) - 1) & ((1 << lim) - 1)
-    elif x == y:
-        return 1 << ((lim-1)-x)
-    else:
-        x = lim-x
-        y = (lim-1)-y
-        mask_a = ((1 << x) - 1) & ((1 << lim) - 1)
-        mask_b = (~((1 << y) - 1)) & ((1 << lim) - 1)
-    return mask_a ^ mask_b
-
-
 def ne(a, b):
     return onebit(a != b)
 
@@ -842,60 +802,146 @@ def log2(val):
     return retval
 
 
+class ISACallerHelper:
+    def __init__(self, XLEN):
+        self.__XLEN = XLEN
+
+    @property
+    def XLEN(self):
+        return self.__XLEN
+
+    def XLCASTS(self, value):
+        return SelectableInt(exts(value.value, self.XLEN), self.XLEN)
+
+    def XLCASTU(self, value):
+        # SelectableInt already takes care of masking out the bits
+        return SelectableInt(value.value, self.XLEN)
+
+    def EXTSXL(self, value, bits):
+        return SelectableInt(exts(value.value, bits), self.XLEN)
+
+    def DOUBLE2SINGLE(self, FRS):
+        """ DOUBLE2SINGLE has been renamed to FRSP since it is the
+            implementation of the frsp instruction.
+            use SINGLE() or FRSP() instead, or just use struct.pack/unpack
+        """
+        FPSCR = {
+            'UE': SelectableInt(0, 1),
+            'OE': SelectableInt(0, 1),
+            'RN': SelectableInt(0, 2),  # round to nearest, ties to even
+            'XX': SelectableInt(0, 1),
+        }
+        FRT, FPSCR = self.FRSP(FRS, FPSCR)
+        return FRT
+
+    def ROTL32(self, value, bits):
+        if isinstance(bits, SelectableInt):
+            bits = bits.value
+        if isinstance(value, SelectableInt):
+            value = SelectableInt(value.value, self.XLEN)
+        value = value | (value << (self.XLEN//2))
+        value = rotl(value, bits, self.XLEN)
+        return value
+
+    def ROTL64(self, value, bits):
+        return rotl(value, bits, self.XLEN)
+
+    def MASK32(self, x, y):
+        if isinstance(x, SelectableInt):
+            x = x.value
+        if isinstance(y, SelectableInt):
+            y = y.value
+        return self.MASK(x+(self.XLEN//2), y+(self.XLEN//2))
+
+    def MASK(self, x, y, lim=None):
+        if lim is None:
+            lim = self.XLEN
+        if isinstance(x, SelectableInt):
+            x = x.value
+        if isinstance(y, SelectableInt):
+            y = y.value
+        if x < y:
+            x = lim-x
+            y = (lim-1)-y
+            mask_a = ((1 << x) - 1) & ((1 << lim) - 1)
+            mask_b = ((1 << y) - 1) & ((1 << lim) - 1)
+        elif x == y:
+            return 1 << ((lim-1)-x)
+        else:
+            x = lim-x
+            y = (lim-1)-y
+            mask_a = ((1 << x) - 1) & ((1 << lim) - 1)
+            mask_b = (~((1 << y) - 1)) & ((1 << lim) - 1)
+        return mask_a ^ mask_b
+
+    def __getattr__(self, attr):
+        """workaround for getting function out of the global namespace
+        within this module, as a way to get functions being transitioned
+        to Helper classes within ISACaller (and therefore pseudocode)
+        """
+        try:
+            return globals()[attr]
+        except KeyError:
+            raise AttributeError(attr)
+
+
 # For these tests I tried to find power instructions that would let me
 # isolate each of these helper operations. So for instance, when I was
 # testing the MASK() function, I chose rlwinm and rldicl because if I
 # set the shift equal to 0 and passed in a value of all ones, the
 # result I got would be exactly the same as the output of MASK()
 
+class HelperTests(unittest.TestCase, ISACallerHelper):
+    def __init__(self, *args, **kwargs):
+        ISACallerHelper.__init__(self, 64) # TODO: dynamic (64/32/16/8)
+        unittest.TestCase.__init__(self, *args, **kwargs)
 
-class HelperTests(unittest.TestCase):
     def test_MASK(self):
         # Verified using rlwinm, rldicl, rldicr in qemu
         # li 1, -1
         # rlwinm reg, 1, 0, 5, 15
-        self.assertHex(MASK(5+32, 15+32), 0x7ff0000)
+        self.assertHex(self.MASK(5+32, 15+32), 0x7ff0000)
         # rlwinm reg, 1, 0, 15, 5
-        self.assertHex(MASK(15+32, 5+32), 0xfffffffffc01ffff)
-        self.assertHex(MASK(30+32, 2+32), 0xffffffffe0000003)
+        self.assertHex(self.MASK(15+32, 5+32), 0xfffffffffc01ffff)
+        self.assertHex(self.MASK(30+32, 2+32), 0xffffffffe0000003)
         # rldicl reg, 1, 0, 37
-        self.assertHex(MASK(37, 63), 0x7ffffff)
-        self.assertHex(MASK(10, 63), 0x3fffffffffffff)
-        self.assertHex(MASK(58, 63), 0x3f)
+        self.assertHex(self.MASK(37, 63), 0x7ffffff)
+        self.assertHex(self.MASK(10, 63), 0x3fffffffffffff)
+        self.assertHex(self.MASK(58, 63), 0x3f)
         # rldicr reg, 1, 0, 37
-        self.assertHex(MASK(0, 37), 0xfffffffffc000000)
-        self.assertHex(MASK(0, 10), 0xffe0000000000000)
-        self.assertHex(MASK(0, 58), 0xffffffffffffffe0)
+        self.assertHex(self.MASK(0, 37), 0xfffffffffc000000)
+        self.assertHex(self.MASK(0, 10), 0xffe0000000000000)
+        self.assertHex(self.MASK(0, 58), 0xffffffffffffffe0)
 
         # li 2, 5
         # slw 1, 1, 2
-        self.assertHex(MASK(32, 63-5), 0xffffffe0)
+        self.assertHex(self.MASK(32, 63-5), 0xffffffe0)
 
-        self.assertHex(MASK(32, 33), 0xc0000000)
-        self.assertHex(MASK(32, 32), 0x80000000)
-        self.assertHex(MASK(33, 33), 0x40000000)
+        self.assertHex(self.MASK(32, 33), 0xc0000000)
+        self.assertHex(self.MASK(32, 32), 0x80000000)
+        self.assertHex(self.MASK(33, 33), 0x40000000)
 
     def test_ROTL64(self):
         # r1 = 0xdeadbeef12345678
         value = 0xdeadbeef12345678
 
         # rldicl reg, 1, 10, 0
-        self.assertHex(ROTL64(value, 10), 0xb6fbbc48d159e37a)
+        self.assertHex(self.ROTL64(value, 10), 0xb6fbbc48d159e37a)
         # rldicl reg, 1, 35, 0
-        self.assertHex(ROTL64(value, 35), 0x91a2b3c6f56df778)
-        self.assertHex(ROTL64(value, 58), 0xe37ab6fbbc48d159)
-        self.assertHex(ROTL64(value, 22), 0xbbc48d159e37ab6f)
+        self.assertHex(self.ROTL64(value, 35), 0x91a2b3c6f56df778)
+        self.assertHex(self.ROTL64(value, 58), 0xe37ab6fbbc48d159)
+        self.assertHex(self.ROTL64(value, 22), 0xbbc48d159e37ab6f)
 
     def test_ROTL32(self):
         # r1 = 0xdeadbeef
-        value = 0xdeadbeef
+        value = SelectableInt(0xdeadbeef, self.XLEN)
 
         # rlwinm reg, 1, 10, 0, 31
-        self.assertHex(ROTL32(value, 10), 0xb6fbbf7a)
+        self.assertHex(self.ROTL32(value, 10), 0xb6fbbf7a)
         # rlwinm reg, 1, 17, 0, 31
-        self.assertHex(ROTL32(value, 17), 0x7ddfbd5b)
-        self.assertHex(ROTL32(value, 25), 0xdfbd5b7d)
-        self.assertHex(ROTL32(value, 30), 0xf7ab6fbb)
+        self.assertHex(self.ROTL32(value, 17), 0x7ddfbd5b)
+        self.assertHex(self.ROTL32(value, 25), 0xdfbd5b7d)
+        self.assertHex(self.ROTL32(value, 30), 0xf7ab6fbb)
 
     def test_EXTS64(self):
         value_a = SelectableInt(0xdeadbeef, 32)  # r1
@@ -903,11 +949,11 @@ class HelperTests(unittest.TestCase):
         value_c = SelectableInt(0x80000000, 32)  # r3
 
         # extswsli reg, 1, 0
-        self.assertHex(EXTS64(value_a), 0xffffffffdeadbeef)
+        self.assertHex(self.EXTS64(value_a), 0xffffffffdeadbeef)
         # extswsli reg, 2, 0
-        self.assertHex(EXTS64(value_b), SelectableInt(value_b.value, 64))
+        self.assertHex(self.EXTS64(value_b), SelectableInt(value_b.value, 64))
         # extswsli reg, 3, 0
-        self.assertHex(EXTS64(value_c), 0xffffffff80000000)
+        self.assertHex(self.EXTS64(value_c), 0xffffffff80000000)
 
     def test_FPADD32(self):
         value_a = SelectableInt(0x4014000000000000, 64)  # 5.0
@@ -926,44 +972,6 @@ class HelperTests(unittest.TestCase):
         return self.assertEqual(a, b, msg)
 
 
-class ISACallerHelper:
-    def __init__(self, XLEN):
-        self.__XLEN = XLEN
-
-    @property
-    def XLEN(self):
-        return self.__XLEN
-
-    def XLCASTS(self, value):
-        return SelectableInt(exts(value.value, self.XLEN), self.XLEN)
-
-    def XLCASTU(self, value):
-        # SelectableInt already takes care of masking out the bits
-        return SelectableInt(value.value, self.XLEN)
-
-    def EXTSXL(self, value, bits):
-        return SelectableInt(exts(value.value, bits), self.XLEN)
-
-    def DOUBLE2SINGLE(self, FRS):
-        """ DOUBLE2SINGLE has been renamed to FRSP since it is the
-            implementation of the frsp instruction.
-            use SINGLE() or FRSP() instead, or just use struct.pack/unpack
-        """
-        FPSCR = {
-            'UE': SelectableInt(0, 1),
-            'OE': SelectableInt(0, 1),
-            'RN': SelectableInt(0, 2),  # round to nearest, ties to even
-            'XX': SelectableInt(0, 1),
-        }
-        FRT, FPSCR = self.FRSP(FRS, FPSCR)
-        return FRT
-
-    def __getattr__(self, attr):
-        try:
-            return globals()[attr]
-        except KeyError:
-            raise AttributeError(attr)
-
 
 if __name__ == '__main__':
     log(SelectableInt.__bases__)