import unittest
+import struct
from openpower.decoder.selectable_int import (SelectableInt, onebit,
selectconcat)
from nmutil.divmod import trunc_divs, trunc_rems
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
DIVS = trunc_divs
def EXTS(value):
""" extends sign bit out from current MSB to all 256 bits
"""
- print ("EXTS", value, type(value))
+ log ("EXTS", value, type(value))
assert isinstance(value, SelectableInt)
return SelectableInt(exts(value.value, value.bits) & ((1 << 256)-1), 256)
a_s = a.value & (1 << (a.bits-1)) != 0
b_s = b.value & (1 << (b.bits-1)) != 0
result = abs(a) * abs(b)
- print("MULS", result, a_s, b_s)
+ log("MULS", result, a_s, b_s)
if a_s == b_s:
return result
return -result
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)
"""
return v
-def DOUBLE(WORD):
- """convert incoming WORD to double. v3.0B p140 section 4.6.2
+
+def SINGLE(FRS):
+ """convert incoming FRS into 32-bit word. v3.0B p144 section 4.6.3
+ """
+ # result - WORD - start off all zeros
+ WORD = SelectableInt(0, 32)
+
+ e = FRS[1:12]
+ m = FRS[12:64]
+ s = FRS[0]
+
+ log ("SINGLE", FRS)
+ log ("s e m", s.value, e.value, m.value)
+
+ #No Denormalization Required (includes Zero / Infinity / NaN)
+ if e.value > 896 or FRS[1:64].value == 0:
+ log("nodenorm", FRS[0:2].value, hex(FRS[5:35].value))
+ WORD[0:2] = FRS[0:2]
+ WORD[2:32] = FRS[5:35]
+
+ #Denormalization Required
+ if e.value >= 874 and e.value <= 896:
+ sign = FRS[0]
+ exp = e.value - 1023
+ frac = selectconcat(SelectableInt(1, 1), FRS[12:64])
+ log("exp, fract", exp, hex(frac.value))
+ # denormalize operand
+ while exp < -126:
+ frac[0:53] = selectconcat(SelectableInt(0, 1), frac[0:52])
+ exp = exp + 1
+ WORD[0] = sign
+ WORD[1:9] = SelectableInt(0, 8)
+ WORD[9:32] = frac[1:24]
+ #else WORD = undefined # return zeros
+
+ log ("WORD", WORD)
+
+ return WORD
+
+# XXX NOTE: these are very quick hacked functions for utterly basic
+# FP support
+
+def fp64toselectable(frt):
+ """convert FP number to 64 bit SelectableInt
"""
- # result, FRT, start off all zeros
- FRT = SelectableInt(0, 64)
- z1 = SelectableInt(0, 1)
- z29 = SelectableInt(0, 29)
- # Normalized Operand
- if WORD[1:9] > 0 and WORD[1:9] < 255:
- 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 WORD[1:9] == 0 and WORD[9:32] != 0:
- sign = WORD[0]
- exp = -126
- frac[0:53] = selectconcat(z1, WORD[9:32], z29)
- # normalize the operand
- while frac[0] == 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 WORD[1:9] == 255 or WORD[1:32] == 0:
- 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)
-
- return FRT
+ b = struct.pack(">d", frt)
+ val = int.from_bytes(b, byteorder='big', signed=False)
+ 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 = 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 = DOUBLE2SINGLE(cvt)
+ log ("FPSUB32", FRA, FRB, float(FRA), "-", float(FRB), "=", result, cvt)
+ return cvt
+
+
+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 = 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 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, 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
+
+
+def FPADD64(FRA, FRB):
+ result = float(FRA) + float(FRB)
+ cvt = fp64toselectable(result)
+ log ("FPADD64", FRA, FRB, result, cvt)
+ return cvt
+
+
+def FPSUB64(FRA, FRB):
+ result = float(FRA) - float(FRB)
+ cvt = fp64toselectable(result)
+ log ("FPSUB64", FRA, FRB, result, cvt)
+ return cvt
+
+
+def FPMUL64(FRA, FRB, sign=1):
+ result = signinv(float(FRA) * float(FRB), sign)
+ cvt = fp64toselectable(result)
+ log ("FPMUL64", FRA, FRB, result, cvt, sign)
+ return cvt
+
+
+def FPDIV64(FRA, FRB, sign=1):
+ result = signinv(float(FRA) / float(FRB), sign)
+ cvt = fp64toselectable(result)
+ 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
# extswsli reg, 3, 0
self.assertHex(EXTS64(value_c), 0xffffffff80000000)
+ def test_FPADD32(self):
+ value_a = SelectableInt(0x4014000000000000, 64) # 5.0
+ value_b = SelectableInt(0x403B4CCCCCCCCCCD, 64) # 27.3
+ result = FPADD32(value_a, value_b)
+ self.assertHex(0x4040266666666666, result)
+
def assertHex(self, a, b):
a_val = a
if isinstance(a, SelectableInt):
if __name__ == '__main__':
- print(SelectableInt.__bases__)
+ log(SelectableInt.__bases__)
unittest.main()