From 01a56f3b7934acbbc0fd7b7088fe83b18722934b Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Fri, 21 Oct 2022 12:29:33 +0100 Subject: [PATCH] move HASK, ROTL32, ROTL64, MASK32, into helper class --- src/openpower/decoder/helpers.py | 216 ++++++++++++++++--------------- 1 file changed, 112 insertions(+), 104 deletions(-) diff --git a/src/openpower/decoder/helpers.py b/src/openpower/decoder/helpers.py index ba576b13..ea3b659a 100644 --- a/src/openpower/decoder/helpers.py +++ b/src/openpower/decoder/helpers.py @@ -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__) -- 2.30.2