add more bfp_* functions
authorJacob Lifshay <programmerjake@gmail.com>
Fri, 19 May 2023 06:35:50 +0000 (23:35 -0700)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 2 Jun 2023 18:51:18 +0000 (19:51 +0100)
openpower/isafunctions/bfp.mdwn

index e5ec5ebb258caffb79e87394c71c42ab149fae56..f753805c309844553f24e1a4d1650d92df07e67f 100644 (file)
@@ -620,3 +620,128 @@ section 7.6.2.2
                 # TODO: spec says this is logical shift right:
                 significand <- significand[0:127] / pow(2, 127 - exponent)
                 return significand[0:127]
+
+    def bfp64_CONVERT_FROM_BFP(x):
+        # x is a floating-point value represented in the binary floating-point
+        # working format.
+
+        result <- [0] * 64
+        if x.class.QNaN = 1 then
+            result[0] <- x.sign
+            result[1:11] <- 0b111_1111_1111
+            result[12:63] <- x.significand[1:52]
+        else if x.class.Infinity = 1 then
+            result[0] <- x.sign
+            result[1:11] <- 0b111_1111_1111
+            result[12:63] <- 0
+        else if x.class.Zero = 1 then
+            result[0] <- x.sign
+            result[1:63] <- 0
+        else if (x.exponent < -1022) & (FPSCR.UE = 0) then
+            result[0] <- x.sign
+            sh_cnt <- -1022 - x.exponent
+            result[1:11] <- 0b000_0000_0000
+            # TODO: spec says this is shift right
+            result[12:63] <- x.significand[1:52] / pow(2, sh_cnt)
+        else if (x.exponent < -1022) & (FPSCR.UE = 1) then
+            result[0:63] <- undefined(0)  # TODO: which undefined value to use?
+        else if (x.exponent > 1023) & (FPSCR.OE = 1) then
+            result[0:63] <- undefined(0)  # TODO: which undefined value to use?
+        else
+            result[0] <- x.sign
+            result[1:11] <- x.exponent + 1023
+            result[12:63] <- x.significand[1:52]
+        return result
+
+    def bfp_ROUND_TO_BFP64(ro, rmode, x):
+        # x is a normalized binary floating-point value that is represented in
+        # the binary floating-point working format and has unbounded exponent
+        # range and significand precision.
+        # ro is a 1-bit unsigned integer and rmode is a 2-bit unsigned integer,
+        # together specifying one of five rounding modes to be used in
+        # rounding z.
+        #
+        # ro=0 rmode=0b00  Round to Nearest Even
+        # ro=0 rmode=0b01  Round towards Zero
+        # ro=0 rmode=0b10  Round towards +Infinity
+        # ro=0 rmode=0b11  Round towards -Infinity
+        # ro=1             Round to Odd
+        #
+        # Return the value x rounded to double-precision under control of the
+        # specified rounding mode.
+
+        if x.class.QNaN then return x
+        if x.class.Infinity then return x
+        if x.class.Zero then return x
+        if bfp_COMPARE_LT(bfp_ABSOLUTE(x), bfp_NMIN_BFP64()) then
+            if FPSCR.UE=0 then
+                x <- bfp_DENORM(-1022, x)
+                if (ro=0) & (rmode=0b00) then r <- bfp_ROUND_NEAR_EVEN(53, x)
+                if (ro=0) & (rmode=0b01) then r <- bfp_ROUND_TRUNC(53, x)
+                if (ro=0) & (rmode=0b10) then r <- bfp_ROUND_CEIL(53, x)
+                if (ro=0) & (rmode=0b11) then r <- bfp_ROUND_FLOOR(53, x)
+                if  ro=1                 then r <- bfp_ROUND_ODD(53, x)
+                ux_flag <- xx_flag
+                return r
+            else
+                x.exponent <- x.exponent + 1536
+                ux_flag <- 1
+        if (ro=0) & (rmode=0b00) then r <- bfp_ROUND_NEAR_EVEN(53, x)
+        if (ro=0) & (rmode=0b01) then r <- bfp_ROUND_TRUNC(53, x)
+        if (ro=0) & (rmode=0b10) then r <- bfp_ROUND_CEIL(53, x)
+        if (ro=0) & (rmode=0b11) then r <- bfp_ROUND_FLOOR(53, x)
+        if  ro=1                 then r <- bfp_ROUND_ODD(53, x)
+        if bfp_ABSOLUTE(r) > bfp_NMAX_BFP64() then
+            if FPSCR.OE=0 then
+                if x.sign then
+                    if (ro=0) & (rmode=0b00) then r <- bfp_INFINITY()
+                    if (ro=0) & (rmode=0b01) then r <- bfp_NMAX_BFP64()
+                    if (ro=0) & (rmode=0b10) then r <- bfp_NMAX_BFP64()
+                    if (ro=0) & (rmode=0b11) then r <- bfp_INFINITY()
+                    if  ro=1                 then r <- bfp_NMAX_BFP64()
+                else
+                    if (ro=0) & (rmode=0b00) then r <- bfp_INFINITY()
+                    if (ro=0) & (rmode=0b01) then r <- bfp_NMAX_BFP64()
+                    if (ro=0) & (rmode=0b10) then r <- bfp_INFINITY()
+                    if (ro=0) & (rmode=0b11) then r <- bfp_NMAX_BFP64()
+                    if  ro=1                 then r <- bfp_NMAX_BFP64()
+                r.sign <- x.sign
+                ox_flag <- 0b1
+                xx_flag <- 0b1
+                inc_flag <- undefined(0)  # TODO: which undefined value to use?
+                return r
+            else
+                r.exponent <- r.exponent - 1536
+                ox_flag <- 1
+        return r
+
+    def bfp_INFINITY():
+        # The value +Infinity represented in the binary floating-point working
+        # format.
+        r <- BFPState()
+        r.class.Infinity <- 1
+        return r
+
+    def bfp_NMAX_BFP32():
+        # Return the largest finite single-precision floating-point value
+        # (i.e., 2^128 - 2^(128-24)) in the binary floating-point working
+        # format.
+        return bfp_CONVERT_FROM_BFP32(0x7F7F_FFFF)
+
+    def bfp_NMAX_BFP64():
+        # Return the largest finite double-precision floating-point value
+        # (i.e., 2^1024 - 2^(1024-53)) in the binary floating-point working
+        # format.
+        return bfp_CONVERT_FROM_BFP64(0x7FEF_FFFF_FFFF_FFFF)
+
+    def bfp_NMIN_BFP32():
+        # Return the smallest positive normalized single-precision
+        # floating-point value, 2^-126, represented in the binary
+        # floating-point working format.
+        return bfp_CONVERT_FROM_BFP32(0x0080_0000)
+
+    def bfp_NMIN_BFP64():
+        # Return the smallest positive normalized double-precision
+        # floating-point value, 2^-1022, represented in the binary
+        # floating-point working format.
+        return bfp_CONVERT_FROM_BFP64(0x0010_0000_0000_0000)