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 check_extsign
from openpower.util import log
+import math
trunc_div = floordiv
trunc_rem = mod
"""
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)
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
- """
- # 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
# 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
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):
"""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
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()