X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fopenpower%2Fdecoder%2Fhelpers.py;h=87b71d99780046a7643d9cd828779eb53e737bf4;hb=dcf4c64a66d5ed33fb10bcfcf65017bef39a4d0f;hp=b93d51bee3068bcca6715c48a696d1af4b60c889;hpb=eb160da0b7805cd782eed94dc4b99fe6e48f74b0;p=openpower-isa.git diff --git a/src/openpower/decoder/helpers.py b/src/openpower/decoder/helpers.py index b93d51be..87b71d99 100644 --- a/src/openpower/decoder/helpers.py +++ b/src/openpower/decoder/helpers.py @@ -8,6 +8,9 @@ from openpower.decoder.selectable_int import selectltu as ltu 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 @@ -27,7 +30,7 @@ def exts(value, bits): 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) @@ -54,7 +57,7 @@ def MULS(a, b): 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 @@ -75,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) @@ -150,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 - print ("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] - print ("word s e m", s, e, m) - - # Normalized Operand - if e.value > 0 and e.value < 255: - print ("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: - print ("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 m.value == 0: - print ("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) - - print ("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 @@ -207,18 +168,27 @@ def SINGLE(FRS): # 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 FRS[1:12].value > 896 or FRS[1:64].value == 0: + 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 FRS[1:12].value >= 874 and FRS[1:12].value <= 896: + if e.value >= 874 and e.value <= 896: sign = FRS[0] - exp = FRS[1:12] - 1023 + exp = e.value - 1023 frac = selectconcat(SelectableInt(1, 1), FRS[12:64]) + log("exp, fract", exp, hex(frac.value)) # denormalize operand - while exp.value < -126: + while exp < -126: frac[0:53] = selectconcat(SelectableInt(0, 1), frac[0:52]) exp = exp + 1 WORD[0] = sign @@ -226,6 +196,8 @@ def SINGLE(FRS): 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 @@ -239,28 +211,152 @@ def fp64toselectable(frt): return SelectableInt(val, 64) -def FPADD(FRA, FRB): +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) - print ("FPADD", FRA, FRB, result, cvt) + cvt = DOUBLE2SINGLE(cvt) + log ("FPADD32", FRA, FRB, float(FRA), "+", float(FRB), "=", result, cvt) + return cvt -def FPSUB(FRA, FRB): +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) - print ("FPSUB", FRA, FRB, result, cvt) + 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 FPMUL(FRA, FRB): - result = float(FRA) * float(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 = signinv(float(FRA) / float(FRB), sign) cvt = fp64toselectable(result) - print ("FPMUL", FRA, FRB, result, cvt) + cvt = DOUBLE2SINGLE(cvt) + log ("FPDIV32", FRA, FRB, result, cvt) + return cvt -def FPDIV(FRA, FRB): - result = float(FRA) / float(FRB) +def FPADD64(FRA, FRB): + result = float(FRA) + float(FRB) cvt = fp64toselectable(result) - print ("FPDIV", FRA, FRB, result, cvt) + 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 @@ -330,10 +426,10 @@ class HelperTests(unittest.TestCase): # extswsli reg, 3, 0 self.assertHex(EXTS64(value_c), 0xffffffff80000000) - def test_FPADD(self): + def test_FPADD32(self): value_a = SelectableInt(0x4014000000000000, 64) # 5.0 value_b = SelectableInt(0x403B4CCCCCCCCCCD, 64) # 27.3 - result = FPADD(value_a, value_b) + result = FPADD32(value_a, value_b) self.assertHex(0x4040266666666666, result) def assertHex(self, a, b): @@ -348,5 +444,5 @@ class HelperTests(unittest.TestCase): if __name__ == '__main__': - print(SelectableInt.__bases__) + log(SelectableInt.__bases__) unittest.main()