test_caller_bcd: fix and refactor addg6s test loop
[openpower-isa.git] / src / openpower / decoder / helpers.py
index 5440217f9f70be7a3b4d138cd65da4b97b0d4cc0..87b71d99780046a7643d9cd828779eb53e737bf4 100644 (file)
@@ -9,6 +9,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
@@ -77,6 +78,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 +161,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
@@ -252,68 +211,109 @@ def fp64toselectable(frt):
     return SelectableInt(val, 64)
 
 
+def FPSIN32(FRB):
+    from openpower.decoder.isafunctions.double2single import DOUBLE2SINGLE
+    #FRB = DOUBLE(SINGLE(FRB))
+    result = math.sin(float(FRB))
+    cvt = fp64toselectable(result)
+    cvt = DOUBLE2SINGLE(cvt)
+    log ("FPSIN32", FRB, float(FRB), "=", result, cvt)
+    return cvt
+
+
+def FPCOS32(FRB):
+    from openpower.decoder.isafunctions.double2single import DOUBLE2SINGLE
+    #FRB = DOUBLE(SINGLE(FRB))
+    result = math.cos(float(FRB))
+    cvt = fp64toselectable(result)
+    cvt = DOUBLE2SINGLE(cvt)
+    log ("FPCOS32", FRB, float(FRB), "=", result, cvt)
+    return cvt
+
+
 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 = DOUBLE(SINGLE(cvt))
-    log ("FPADD32", FRA, FRB, result, cvt)
+    cvt = DOUBLE2SINGLE(cvt)
+    log ("FPADD32", FRA, FRB, float(FRA), "+", float(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 = DOUBLE(SINGLE(cvt))
-    log ("FPSUB32", FRA, FRB, result, cvt)
+    cvt = DOUBLE2SINGLE(cvt)
+    log ("FPSUB32", FRA, FRB, float(FRA), "-", float(FRB), "=", result, cvt)
     return cvt
 
 
-def FPMUL32(FRA, FRB):
+def signinv(res, sign):
+    if sign == 1:
+        return res
+    if sign == 0:
+        return 0.0
+    if sign == -1:
+        return -res
+
+
+def FPMUL32(FRA, FRB, sign=1):
     from openpower.decoder.isafunctions.double2single import DOUBLE2SINGLE
+    from openpower.decoder.isafunctions.double2single import DOUBLE
     #return FPMUL64(FRA, FRB)
-    #FRA = DOUBLE(SINGLE(FRA))
-    #FRB = DOUBLE(SINGLE(FRB))
-    result = float(FRA) * float(FRB)
-    log ("FPMUL32", FRA, FRB, float(FRA), float(FRB), result)
+    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, FRB, FRC, sign):
+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 sign == 1:
-        result = float(FRA) * float(FRB) + float(FRC)
-    elif sign == -1:
-        result = float(FRA) * float(FRB) - float(FRC)
-    elif sign == 0:
-        result = float(FRA) * float(FRB)
-    log ("FPMULADD32", FRA, FRB, FRC,
-                       float(FRA), float(FRB), float(FRC),
-                       result)
+    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 = DOUBLE2SINGLE(cvt)
     log ("      cvt", cvt)
     return cvt
 
 
-def FPDIV32(FRA, FRB):
+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 = float(FRA) / float(FRB)
+    result = signinv(float(FRA) / float(FRB), sign)
     cvt = fp64toselectable(result)
-    cvt = DOUBLE(SINGLE(cvt))
+    cvt = DOUBLE2SINGLE(cvt)
     log ("FPDIV32", FRA, FRB, result, cvt)
     return cvt
 
@@ -332,20 +332,33 @@ def FPSUB64(FRA, FRB):
     return cvt
 
 
-def FPMUL64(FRA, FRB):
-    result = float(FRA) * float(FRB)
+def FPMUL64(FRA, FRB, sign=1):
+    result = signinv(float(FRA) * float(FRB), sign)
     cvt = fp64toselectable(result)
-    log ("FPMUL64", FRA, FRB, result, cvt)
+    log ("FPMUL64", FRA, FRB, result, cvt, sign)
     return cvt
 
 
-def FPDIV64(FRA, FRB):
-    result = float(FRA) / float(FRB)
+def FPDIV64(FRA, FRB, sign=1):
+    result = signinv(float(FRA) / float(FRB), sign)
     cvt = fp64toselectable(result)
-    log ("FPDIV64", FRA, FRB, result, cvt)
+    log ("FPDIV64", FRA, FRB, result, cvt, sign)
     return cvt
 
 
+
+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()-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
 # isolate each of these helper operations. So for instance, when I was
 # testing the MASK() function, I chose rlwinm and rldicl because if I