Shorten expected state code for case_extsb in alu_cases unit test
[openpower-isa.git] / src / openpower / decoder / helpers.py
index ed8679d688e46f31ec608252da458ed2bfc8c3db..8caa10689b595ddc77a0f457ccfa9f2875e753a3 100644 (file)
@@ -1,5 +1,6 @@
 import unittest
 import struct
 import unittest
 import struct
+import sys
 from openpower.decoder.selectable_int import (SelectableInt, onebit,
                                               selectconcat)
 from nmutil.divmod import trunc_divs, trunc_rems
 from openpower.decoder.selectable_int import (SelectableInt, onebit,
                                               selectconcat)
 from nmutil.divmod import trunc_divs, trunc_rems
@@ -9,6 +10,7 @@ from openpower.decoder.selectable_int import selectgtu as gtu
 from openpower.decoder.selectable_int import check_extsign
 
 from openpower.util import log
 from openpower.decoder.selectable_int import check_extsign
 
 from openpower.util import log
+import math
 
 trunc_div = floordiv
 trunc_rem = mod
 
 trunc_div = floordiv
 trunc_rem = mod
@@ -18,9 +20,19 @@ MODS = trunc_rems
 """
 Links:
 * https://bugs.libre-soc.org/show_bug.cgi?id=324 - add trunc_div and trunc_rem
 """
 Links:
 * https://bugs.libre-soc.org/show_bug.cgi?id=324 - add trunc_div and trunc_rem
+* https://bugs.libre-soc.org/show_bug.cgi?id=671#c38 - RANGE (and bugfixes)
 """
 
 
 """
 
 
+def RANGE(start, end):
+    if start > end:
+        # reverse direction
+        # auto-subtract-one (sigh) due to python range
+        return range(start, end-1, -1)
+    # auto-add-one (sigh) due to python range
+    return range(start, end+1)
+
+
 def exts(value, bits):
     sign = 1 << (bits - 1)
     return (value & (sign - 1)) - (value & sign)
 def exts(value, bits):
     sign = 1 << (bits - 1)
     return (value & (sign - 1)) - (value & sign)
@@ -77,6 +89,14 @@ def rotl(value, bits, wordlen):
     return ((value << bits) | (value >> (wordlen-bits))) & mask
 
 
     return ((value << bits) | (value >> (wordlen-bits))) & mask
 
 
+def SHL64(value, bits, wordlen=64):
+    if isinstance(bits, SelectableInt):
+        bits = bits.value
+    mask = (1 << wordlen) - 1
+    bits = bits & (wordlen - 1)
+    return SelectableInt((value << bits) & mask, 64)
+
+
 def ROTL64(value, bits):
     return rotl(value, bits, 64)
 
 def ROTL64(value, bits):
     return rotl(value, bits, 64)
 
@@ -152,56 +172,6 @@ def undefined(v):
     """
     return v
 
     """
     return v
 
-def DOUBLE(WORD):
-    """convert incoming WORD to double.  v3.0B p140 section 4.6.2
-    """
-    # result, FRT, start off all zeros
-    log ("WORD", WORD)
-    FRT = SelectableInt(0, 64)
-    z1 = SelectableInt(0, 1)
-    z29 = SelectableInt(0, 29)
-    e = WORD[1:9]
-    m = WORD[9:32]
-    s = WORD[0]
-    log ("word s e m", s, e, m)
-
-    # Normalized Operand
-    if e.value > 0 and e.value  < 255:
-        log ("normalised")
-        FRT[0:2] = WORD[0:2]
-        FRT[2] = ~WORD[1]
-        FRT[3] = ~WORD[1]
-        FRT[4] = ~WORD[1]
-        FRT[5:64] = selectconcat(WORD[2:32], z29)
-
-        # Denormalized Operand
-        if e.value  == 0 and m.value != 0:
-            log ("denormalised")
-            sign = WORD[0]
-            exp = -126
-            frac = selectconcat(z1, WORD[9:32], z29)
-            # normalize the operand
-            while frac[0].value  == 0:
-                frac[0:53] = selectconcat(frac[1:53], z1)
-                exp = exp - 1
-            FRT[0] = sign
-            FRT[1:12] = exp + 1023
-            FRT[12:64] = frac[1:53]
-
-    # Zero / Infinity / NaN
-    if e.value  == 255 or WORD[1:32].value  == 0:
-        log ("z/inf/nan")
-        FRT[0:2] = WORD[0:2]
-        FRT[2] = WORD[1]
-        FRT[3] = WORD[1]
-        FRT[4] = WORD[1]
-        FRT[5:64] = selectconcat(WORD[2:32], z29)
-
-    log ("Double s e m", FRT[0].value, FRT[1:12].value-1023,
-                           FRT[12:64].value)
-
-    return FRT
-
 
 def SINGLE(FRS):
     """convert incoming FRS into 32-bit word.  v3.0B p144 section 4.6.3
 
 def SINGLE(FRS):
     """convert incoming FRS into 32-bit word.  v3.0B p144 section 4.6.3
@@ -244,38 +214,6 @@ def SINGLE(FRS):
 # XXX NOTE: these are very quick hacked functions for utterly basic
 # FP support
 
 # XXX NOTE: these are very quick hacked functions for utterly basic
 # FP support
 
-def fp64toselectable(frt):
-    """convert FP number to 64 bit SelectableInt
-    """
-    b = struct.pack(">d", frt)
-    val = int.from_bytes(b, byteorder='big', signed=False)
-    return SelectableInt(val, 64)
-
-
-def FPADD32(FRA, FRB):
-    from openpower.decoder.isafunctions.double2single import DOUBLE2SINGLE
-    #return FPADD64(FRA, FRB)
-    #FRA = DOUBLE(SINGLE(FRA))
-    #FRB = DOUBLE(SINGLE(FRB))
-    result = float(FRA) + float(FRB)
-    cvt = fp64toselectable(result)
-    cvt = DOUBLE2SINGLE(cvt)
-    log ("FPADD32", FRA, FRB, result, cvt)
-    return cvt
-
-
-def FPSUB32(FRA, FRB):
-    from openpower.decoder.isafunctions.double2single import DOUBLE2SINGLE
-    #return FPSUB64(FRA, FRB)
-    #FRA = DOUBLE(SINGLE(FRA))
-    #FRB = DOUBLE(SINGLE(FRB))
-    result = float(FRA) - float(FRB)
-    cvt = fp64toselectable(result)
-    cvt = DOUBLE2SINGLE(cvt)
-    log ("FPSUB32", FRA, FRB, result, cvt)
-    return cvt
-
-
 def signinv(res, sign):
     if sign == 1:
         return res
 def signinv(res, sign):
     if sign == 1:
         return res
@@ -285,55 +223,98 @@ def signinv(res, sign):
         return -res
 
 
         return -res
 
 
-def FPMUL32(FRA, FRB, sign=1):
-    from openpower.decoder.isafunctions.double2single import DOUBLE2SINGLE
-    #return FPMUL64(FRA, FRB)
-    FRA = DOUBLE(SINGLE(FRA))
-    FRB = DOUBLE(SINGLE(FRB))
-    result = signinv(float(FRA) * float(FRB), sign)
-    log ("FPMUL32", FRA, FRB, float(FRA), float(FRB), result, sign)
-    cvt = fp64toselectable(result)
-    cvt = DOUBLE2SINGLE(cvt)
-    log ("      cvt", cvt)
-    return cvt
-
-
-def FPMULADD32(FRA, FRC, FRB, mulsign, addsign):
-    from openpower.decoder.isafunctions.double2single import DOUBLE2SINGLE
-    #return FPMUL64(FRA, FRB)
-    #FRA = DOUBLE(SINGLE(FRA))
-    #FRB = DOUBLE(SINGLE(FRB))
-    if addsign == 1:
-        if mulsign == 1:
-            result = float(FRA) * float(FRC) + float(FRB) # fmadds
-        elif mulsign == -1:
-            result = -(float(FRA) * float(FRC) - float(FRB))  # fnmsubs
-    elif addsign == -1:
-        if mulsign == 1:
-            result = float(FRA) * float(FRC) - float(FRB) # fmsubs
-        elif mulsign == -1:
-            result = -(float(FRA) * float(FRC) + float(FRB))  # fnmadds
-    elif addsign == 0:
-        result = 0.0
-    log ("FPMULADD32", FRA, FRB, FRC,
-                       float(FRA), float(FRB), float(FRC),
-                       result)
-    cvt = fp64toselectable(result)
-    cvt = DOUBLE2SINGLE(cvt)
-    log ("      cvt", cvt)
-    return cvt
+def fp64toselectable(frt):
+    """convert FP number to 64 bit SelectableInt
+    """
+    b = struct.pack(">d", frt)
+    val = int.from_bytes(b, byteorder='big', signed=False)
+    return SelectableInt(val, 64)
 
 
 
 
-def FPDIV32(FRA, FRB, sign=1):
-    from openpower.decoder.isafunctions.double2single import DOUBLE2SINGLE
-    #return FPDIV64(FRA, FRB)
-    #FRA = DOUBLE(SINGLE(FRA))
-    #FRB = DOUBLE(SINGLE(FRB))
-    result = signinv(float(FRA) / float(FRB), sign)
-    cvt = fp64toselectable(result)
-    cvt = DOUBLE2SINGLE(cvt)
-    log ("FPDIV32", FRA, FRB, result, cvt)
-    return cvt
+class ISAFPHelpers:
+
+    def FPSIN32(self, FRB):
+        #FRB = DOUBLE(SINGLE(FRB))
+        result = math.sin(float(FRB))
+        cvt = fp64toselectable(result)
+        cvt = self.DOUBLE2SINGLE(cvt)
+        log ("FPSIN32", FRB, float(FRB), "=", result, cvt)
+        return cvt
+
+    def FPCOS32(self, FRB):
+        #FRB = DOUBLE(SINGLE(FRB))
+        result = math.cos(float(FRB))
+        cvt = fp64toselectable(result)
+        cvt = self.DOUBLE2SINGLE(cvt)
+        log ("FPCOS32", FRB, float(FRB), "=", result, cvt)
+        return cvt
+
+    def FPADD32(self, FRA, FRB):
+        #return FPADD64(FRA, FRB)
+        #FRA = DOUBLE(SINGLE(FRA))
+        #FRB = DOUBLE(SINGLE(FRB))
+        result = float(FRA) + float(FRB)
+        cvt = fp64toselectable(result)
+        cvt = self.DOUBLE2SINGLE(cvt)
+        log ("FPADD32", FRA, FRB, float(FRA), "+", float(FRB), "=", result, cvt)
+        return cvt
+
+    def FPSUB32(self, FRA, FRB):
+        #return FPSUB64(FRA, FRB)
+        #FRA = DOUBLE(SINGLE(FRA))
+        #FRB = DOUBLE(SINGLE(FRB))
+        result = float(FRA) - float(FRB)
+        cvt = fp64toselectable(result)
+        cvt = self.DOUBLE2SINGLE(cvt)
+        log ("FPSUB32", FRA, FRB, float(FRA), "-", float(FRB), "=", result, cvt)
+        return cvt
+
+    def FPMUL32(self, FRA, FRB, sign=1):
+        #return FPMUL64(FRA, FRB)
+        FRA = self.DOUBLE(SINGLE(FRA))
+        FRB = self.DOUBLE(SINGLE(FRB))
+        result = signinv(float(FRA) * float(FRB), sign)
+        log ("FPMUL32", FRA, FRB, float(FRA), float(FRB), result, sign)
+        cvt = fp64toselectable(result)
+        cvt = self.DOUBLE2SINGLE(cvt)
+        log ("      cvt", cvt)
+        return cvt
+
+    def FPMULADD32(self, FRA, FRC, FRB, mulsign, addsign):
+        #return FPMUL64(FRA, FRB)
+        #FRA = DOUBLE(SINGLE(FRA))
+        #FRB = DOUBLE(SINGLE(FRB))
+        if addsign == 1:
+            if mulsign == 1:
+                result = float(FRA) * float(FRC) + float(FRB) # fmadds
+            elif mulsign == -1:
+                result = -(float(FRA) * float(FRC) - float(FRB))  # fnmsubs
+        elif addsign == -1:
+            if mulsign == 1:
+                result = float(FRA) * float(FRC) - float(FRB) # fmsubs
+            elif mulsign == -1:
+                result = -(float(FRA) * float(FRC) + float(FRB))  # fnmadds
+        elif addsign == 0:
+            result = 0.0
+        log ("FPMULADD32 FRA FRC FRB", FRA, FRC, FRB)
+        log ("      FRA", float(FRA))
+        log ("      FRC", float(FRC))
+        log ("      FRB", float(FRB))
+        log ("      (FRA*FRC)+FRB=", mulsign, addsign, result)
+        cvt = fp64toselectable(result)
+        cvt = self.DOUBLE2SINGLE(cvt)
+        log ("      cvt", cvt)
+        return cvt
+
+    def FPDIV32(self, FRA, FRB, sign=1):
+        #return FPDIV64(FRA, FRB)
+        #FRA = DOUBLE(SINGLE(FRA))
+        #FRB = DOUBLE(SINGLE(FRB))
+        result = signinv(float(FRA) / float(FRB), sign)
+        cvt = fp64toselectable(result)
+        cvt = self.DOUBLE2SINGLE(cvt)
+        log ("FPDIV32", FRA, FRB, result, cvt)
+        return cvt
 
 
 def FPADD64(FRA, FRB):
 
 
 def FPADD64(FRA, FRB):
@@ -369,12 +350,12 @@ def bitrev(val, VL):
     """Returns the integer whose value is the reverse of the lowest
     'width' bits of the integer 'val'
     """
     """Returns the integer whose value is the reverse of the lowest
     'width' bits of the integer 'val'
     """
-       result = 0
-    width = VL.bit_length()
-       for _ in range(width):
-               result = (result << 1) | (val & 1)
-               val >>= 1
-       return result
+    result = 0
+    width = VL.bit_length()-1
+    for _ in range(width):
+        result = (result << 1) | (val & 1)
+        val >>= 1
+    return result
 
 
 # For these tests I tried to find power instructions that would let me
 
 
 # For these tests I tried to find power instructions that would let me
@@ -461,6 +442,31 @@ class HelperTests(unittest.TestCase):
         return self.assertEqual(a, b, msg)
 
 
         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 __getattr__(self, attr):
+        try:
+            return globals()[attr]
+        except KeyError:
+            raise AttributeError(attr)
+
+
 if __name__ == '__main__':
     log(SelectableInt.__bases__)
     unittest.main()
 if __name__ == '__main__':
     log(SelectableInt.__bases__)
     unittest.main()