add some bfp_* functions -- this isn't yet enough to run fcvt*
authorJacob Lifshay <programmerjake@gmail.com>
Fri, 12 May 2023 06:48:06 +0000 (23:48 -0700)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 2 Jun 2023 18:51:18 +0000 (19:51 +0100)
openpower/isafunctions/bfp.mdwn [new file with mode: 0644]

diff --git a/openpower/isafunctions/bfp.mdwn b/openpower/isafunctions/bfp.mdwn
new file mode 100644 (file)
index 0000000..0ed4a84
--- /dev/null
@@ -0,0 +1,314 @@
+# binary-floating-point helper functions
+
+`bfp_*` and related functions as needed by fcvt* from PowerISA v3.1B Book I
+section 7.6.2.2
+
+    def reset_xflags():
+        vxsnan_flag <- 0
+        vximz_flag <- 0
+        vxidi_flag <- 0
+        vxisi_flag <- 0
+        vxzdz_flag <- 0
+        vxsqrt_flag <- 0
+        vxcvi_flag <- 0
+        vxvc_flag <- 0
+        ox_flag <- 0
+        ux_flag <- 0
+        xx_flag <- 0
+        zx_flag <- 0
+
+    def bfp_CONVERT_FROM_BFP64(x):
+        # x is a binary floating-point value represented in
+        # double-precision format.
+        exponent <- x[1:11]
+        fraction <- x[12:63]
+
+        result <- BFPState()
+        result.sign <- 0
+        result.exponent <- 0
+        result.significand <- 0
+        result.class.SNaN <- 0
+        result.class.QNaN <- 0
+        result.class.Infinity <- 0
+        result.class.Zero <- 0
+        result.class.Denormal <- 0
+        result.class.Normal <- 0
+        if (exponent = 2047) & (fraction[0] = 0) & (fraction != 0) then
+            # x is a SNaN
+            result.class.SNaN <- 1
+            result.sign <- x[0]
+            result.significand[0] <- 0
+            result.significand[1:52] <- fraction
+        else if (exponent = 2047) & (fraction[0] != 0) & (fraction != 0) then
+            # x is a QNaN
+            result.class.QNaN <- 1
+            result.sign <- x[0]
+            result.significand[0] <- 0
+            result.significand[1:52] <- fraction
+        else if (exponent = 2047) & (fraction = 0) then
+            # is an Infinity
+            result.class.Infinity <- 1
+            result.sign <- x[0]
+        else if (exponent = 0) & (fraction = 0) then
+            # x is a Zero
+            result.class.Zero <- 1
+            result.sign <- x[0]
+        else if (exponent = 0) & (fraction != 0) then
+            # x is a Denormal
+            result.class.Denormal <- 1
+            result.sign <- x[0]
+            result.exp <- -1022
+            result.significand[0] <- 0
+            result.significand[1:52] <- fraction
+            do while result.significand[0] != 1
+                result.significand <- result.significand * 2
+                result.exponent <- result.exponent - 1
+        else
+            result.class.Normal <- 1
+            result.sign <- x[0]
+            result.exponent <- exponent - 1023
+            result.significand[0] <- 1
+            result.significand[1:52] <- fraction
+        return result
+
+    def bfp_CONVERT_FROM_SI32(x):
+        # x is an integer value represented in signed word integer format.
+
+        result <- BFPState()
+        result.sign <- 0
+        result.exponent <- 0
+        result.significand <- 0
+        result.class.SNaN <- 0
+        result.class.QNaN <- 0
+        result.class.Infinity <- 0
+        result.class.Zero <- 0
+        result.class.Denormal <- 0
+        result.class.Normal <- 0
+
+        if x = 0x0000_0000 then
+            result.class.Zero <- 1
+        else
+            result.class.Normal <- 1
+            result.sign <- x[0]
+            result.exponent <- 32
+            result.significand[0:32] <- EXTS(x)
+
+            if result.significand[0] = 1 then
+                result.sign <- 1
+                result.significand[0:32] <- -result.significand[0:32]
+            do while result.significand[0] = 0
+                result.significand <- result.significand * 2
+                result.exponent <- result.exponent - 1
+        return result
+
+    def bfp_CONVERT_FROM_SI64(x):
+        # x is an integer value represented in signed double-word integer
+        # format.
+
+        result <- BFPState()
+        result.sign <- 0
+        result.exponent <- 0
+        result.significand <- 0
+        result.class.SNaN <- 0
+        result.class.QNaN <- 0
+        result.class.Infinity <- 0
+        result.class.Zero <- 0
+        result.class.Denormal <- 0
+        result.class.Normal <- 0
+
+        if x = 0x0000_0000_0000_0000 then
+            result.class.Zero <- 1
+        else
+            result.class.Normal <- 1
+            result.sign <- x[0]
+            result.exponent <- 64
+            result.significand[0:64] <- EXTS(x)
+
+            if result.significand[0] = 1 then
+                result.sign <- 1
+                result.significand[0:64] <- -result.significand[0:64]
+            do while result.significand[0] = 0
+                result.significand <- result.significand * 2
+                result.exponent <- result.exponent - 1
+        return result
+
+    def bfp_CONVERT_FROM_UI128(x):
+        # x is a 128-bit unsigned integer value.
+
+        result <- BFPState()
+        result.sign <- 0
+        result.exponent <- 0
+        result.significand <- 0
+        result.class.SNaN <- 0
+        result.class.QNaN <- 0
+        result.class.Infinity <- 0
+        result.class.Zero <- 0
+        result.class.Denormal <- 0
+        result.class.Normal <- 0
+
+        if x = 0x0000_0000_0000_0000_0000_0000_0000_0000 then
+            result.class.Zero <- 1
+        else
+            result.class.Normal <- 1
+            result.sign <- 0
+            result.exponent <- 128
+            result.significand[0:128] <- 0b0 || x
+            do while result.significand[0] = 0
+                result.significand <- result.significand * 2
+                result.exponent <- result.exponent - 1
+        return result
+
+    def bfp_ROUND_TO_INTEGER(rmode, x):
+        # x is a binary floating-point value that is represented in the
+        # binary floating-point working format and has
+        # unbounded exponent range and significand precision.
+
+        if IsSNaN(x) then vxsnan_flag <- 1
+        if IsNaN(x) & ¬IsSNaN(x) then return x
+        if IsSNaN(x) then
+            result <- x
+            result.class.SNaN <- 0
+            result.class.QNaN <- 1
+            return result
+        if IsInf(x) | IsZero(x) then return x
+        result <- x
+        result.class.Denormal <- 0
+        result.class.Normal <- 0
+        exact <- 0
+        halfway <- 0
+        more_than_halfway <- 0
+        even <- 0
+        if result.exponent < -1 then
+            # all values have magnitude < 0.5
+            result.significand <- 0
+            result.exponent <- 0
+            even <- 1
+        else if result.exponent = -1 then
+            if result.significand[0] = 1 then
+                result.significand[0] <- 0
+                if result.significand = 0 then halfway <- 1
+                else more_than_halfway <- 1
+            result.significand <- 0
+            result.exponent <- 0
+            even <- 1
+        else
+            result.significand <- 0
+            int_part <- x.significand[0:x.exponent]
+            result.significand[0:x.exponent] <- int_part
+            even <- int_part[x.exponent]
+            temp <- x.significand
+            temp[0:x.exponent] <- 0
+            if temp = 0 then exact <- 1
+            if temp[x.exponent + 1] = 1 then
+                temp[x.exponent + 1] <- 0
+                if temp = 0 then halfway <- 1
+                else more_than_halfway <- 1
+        if rmode = 0b000 then  # Round to Nearest Even
+            round_up <- (even & halfway) | more_than_halfway
+        if rmode = 0b001 then  # Round towards Zero
+            round_up <- 0
+        if rmode = 0b010 then  # Round towards +Infinity
+            round_up <- (x.sign = 0) & ¬exact
+        if rmode = 0b011 then  # Round towards -Infinity
+            round_up <- (x.sign = 1) & ¬exact
+        if rmode = 0b100 then  # Round to Nearest Away
+            round_up <- halfway | more_than_halfway
+        if round_up then
+            inc_flag <- 1
+            temp <- BFPState()
+            temp.significand <- 0
+            temp.significand[result.exponent] <- 1
+            result.significand <- result.significand + temp.significand
+            if result.significand >= 2 then
+                result.significand <- truediv(result.significand, 2)
+                result.exponent <- result.exponent + 1
+        else inc_flag <- 0  # TODO: does the spec specify this?
+        if result.significand = 0 then result.class.Zero <- 1
+        else result.class.Normal <- 1
+        if ¬bfp_COMPARE_EQ(result, x) then xx_flag <- 1
+        else xx_flag <- 0  # TODO: does the spec specify this?
+        return result
+
+    def bfp_ROUND_TO_INTEGER_NEAR_EVEN(x):
+        return bfp_ROUND_TO_INTEGER(0b000, x)
+
+    def bfp_ROUND_TO_INTEGER_TRUNC(x):
+        return bfp_ROUND_TO_INTEGER(0b001, x)
+
+    def bfp_ROUND_TO_INTEGER_CEIL(x):
+        return bfp_ROUND_TO_INTEGER(0b010, x)
+
+    def bfp_ROUND_TO_INTEGER_FLOOR(x):
+        return bfp_ROUND_TO_INTEGER(0b011, x)
+
+    def bfp_ROUND_TO_INTEGER_NEAR_AWAY(x):
+        return bfp_ROUND_TO_INTEGER(0b100, x)
+
+    def bfp_COMPARE_EQ(x, y):
+        # x is a binary floating-point value represented in the
+        # binary floating-point working format.
+        # y is a binary floating-point value represented in the
+        # binary floating-point working format.
+
+        if IsNaN(x) | IsNaN(y) then
+            return 0b0
+        if IsZero(x) & IsZero(y) then
+            return 0b1
+        if IsZero(x) | IsZero(y) then
+            return 0b0
+        if x.sign != y.sign then
+            return 0b0
+        if x.exponent != y.exponent then
+            return 0b0
+        return x.significand = y.significand
+
+    def bfp_COMPARE_GT(x, y):
+        # x is a binary floating-point value represented in the
+        # binary floating-point working format.
+        # y is a binary floating-point value represented in the
+        # binary floating-point working format.
+
+        if IsNaN(x) | IsNaN(y) then
+            return 0b0
+        if IsZero(x) & IsZero(y) then
+            return 0b0
+        if IsZero(x) then
+            return IsNeg(y)
+        if IsZero(y) then
+            return ¬IsNeg(x)
+        if x.sign != y.sign then
+            return IsNeg(y)
+        if x.exponent != y.exponent then
+            if x.sign = 1 then return x.exponent < y.exponent
+            return x.exponent > y.exponent
+        if x.sign = 1 then return x.significand < y.significand
+        return x.significand > y.significand
+
+    def bfp_COMPARE_LT(x, y):
+        # x is a binary floating-point value represented in the
+        # binary floating-point working format.
+        # y is a binary floating-point value represented in the
+        # binary floating-point working format.
+
+        if IsNaN(x) | IsNaN(y) then
+            return 0b0
+        if IsZero(x) & IsZero(y) then
+            return 0b0
+        if IsZero(x) then
+            return ¬IsNeg(y)
+        if IsZero(y) then
+            return IsNeg(x)
+        if x.sign != y.sign then
+            return IsNeg(x)
+        if x.exponent != y.exponent then
+            if x.sign = 1 then return x.exponent > y.exponent
+            return x.exponent < y.exponent
+        if x.sign = 1 then return x.significand > y.significand
+        return x.significand < y.significand
+
+    def bfp_ABSOLUTE(x):
+        # x is a binary floating-point value represented in the
+        # binary floating-point working format.
+        result <- x
+        result.sign <- 0
+        return result
\ No newline at end of file