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 sys
 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
+import math
 
 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
+* 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)
@@ -77,6 +89,14 @@ def rotl(value, bits, wordlen):
     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)
 
@@ -152,56 +172,6 @@ def undefined(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
@@ -244,38 +214,6 @@ def SINGLE(FRS):
 # 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
@@ -285,55 +223,98 @@ def signinv(res, sign):
         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):
@@ -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'
     """
-       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
@@ -461,6 +442,31 @@ 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 __getattr__(self, attr):
+        try:
+            return globals()[attr]
+        except KeyError:
+            raise AttributeError(attr)
+
+
 if __name__ == '__main__':
     log(SelectableInt.__bases__)
     unittest.main()