re-convert frsp pseudocode
authorJacob Lifshay <programmerjake@gmail.com>
Thu, 28 Jul 2022 09:50:30 +0000 (02:50 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Thu, 28 Jul 2022 09:50:30 +0000 (02:50 -0700)
Fixes: https://bugs.libre-soc.org/show_bug.cgi?id=896
openpower/isafunctions/double2single.mdwn
src/openpower/decoder/helpers.py

index b731cc04b39ccea3447e6fb6696c84ca84002e1b..1c88612a0ae394b51354ff27508aa28e5174de12 100644 (file)
 The following describes algorithmically the operation of the Floating
 Round to Single-Precision instruction.
 
-<!-- Power ISA Book I Version 3.0B Section A.1 page 775-778 -->
+<!-- OPF_PowerISA_v3.1B.pdf Book I Section A.1 page 1031-1034 -->
 
-    def Round_Single( sign, exp, frac, G, R, X, round_mode ):
+    def FRSP(FRB, FPSCR):
+        if ((FRB)[1:11] <u 897) & ((FRB)[1:63] >u 0) then
+            if FPSCR['UE'] = 0 then
+                return FRSP_Disabled_Exponent_Underflow(FRB, FPSCR)
+            if FPSCR['UE'] = 1 then
+                return FRSP_Enabled_Exponent_Underflow(FRB, FPSCR)
+
+        if ((FRB)[1:11] >u 1150) & ((FRB)[1:11] <u 2047) then
+            if FPSCR['OE'] = 0 then
+                return FRSP_Disabled_Exponent_Overflow(FRB, FPSCR)
+            if FPSCR['OE'] = 1 then
+                return FRSP_Enabled_Exponent_Overflow(FRB, FPSCR)
+
+        if ((FRB)[1:11] >u 896) & ((FRB)[1:11] <u 1151) then
+            return FRSP_Normal_Operand(FRB, FPSCR)
+
+        if (FRB)[1:63] = 0 then
+            return FRSP_Zero_Operand(FRB, FPSCR)
+
+        if (FRB)[1:11] = 2047 then
+            if (FRB)[12:63] = 0 then
+                return FRSP_Infinity_Operand(FRB, FPSCR)
+            if (FRB)[12] = 1 then
+                return FRSP_QNaN_Operand(FRB, FPSCR)
+            if ((FRB)[12] = 0) & ((FRB)[13:63] >u 0) then
+                return FRSP_SNaN_Operand(FRB, FPSCR)
+
+    def FRSP_Disabled_Exponent_Underflow(FRB, FPSCR):
+        sign <- (FRB)[0]
+        frac[0:52] <- 0
+        exp <- 0
+        if (FRB)[1:11] = 0 then
+            exp <- -1022
+            frac[0:52] <- 0b0 || (FRB)[12:63]
+        if (FRB)[1:11] >u 0 then
+            exp <- (FRB)[1:11] - 1023
+            frac[0:52] <- 0b1 || (FRB)[12:63]
+
+        # Denormalize operand:
+        G <- 0b0
+        R <- 0b0
+        X <- 0b0
+        do while exp < -126
+            exp <- exp + 1
+            X <- X | R
+            R <- G
+            G <- frac[52]
+            frac[0:52] <- 0b0 || frac[0:51]
+
+        FPSCR['UX'] <- (frac[24:52] || G || R || X) >u 0
+        exp, frac, FPSCR <- Round_Single(sign, exp, frac[0:52], G, R, X, FPSCR)
+        FPSCR['XX'] <- FPSCR['XX'] | FPSCR['FI']
+        FRT <- [0b0] * 64
+        if frac[0:52] = 0 then
+            FRT[0] <- sign
+            FRT[1:63] <- 0
+            if sign = 0 then FPSCR['FPRF'] <- '+ zero'
+            if sign = 1 then FPSCR['FPRF'] <- '- zero'
+        if frac[0:52] >u 0 then
+            if frac[0] = 1 then
+                if sign = 0 then FPSCR['FPRF'] <- '+ normal number'
+                if sign = 1 then FPSCR['FPRF'] <- '- normal number'
+            if frac[0] = 0 then
+                if sign = 0 then FPSCR['FPRF'] <- '+ denormalized number'
+                if sign = 1 then FPSCR['FPRF'] <- '- denormalized number'
+
+            # Normalize operand:
+            do while frac[0] = 0
+                exp <- exp-1
+                frac[0:52] <- frac[1:52] || 0b0
+
+            FRT[0] <- sign
+            FRT[1:11] <- exp + 1023
+            FRT[12:63] <- frac[1:52]
+        return FRT, FPSCR
+
+    def FRSP_Enabled_Exponent_Underflow(FRB, FPSCR):
+        FPSCR['UX'] <- 1
+        sign <- (FRB)[0]
+        frac <- [0b0] * 53
+        exp <- 0
+        if (FRB)[1:11] = 0 then
+            exp <- -1022
+            frac[0:52] <- 0b0 || (FRB)[12:63]
+        if (FRB)[1:11] >u 0 then
+            exp <- (FRB)[1:11] - 1023
+            frac[0:52] <- 0b1 || (FRB)[12:63]
+
+        # Normalize operand:
+        do while frac[0] = 0
+            exp <- exp - 1
+            frac[0:52] <- frac[1:52] || 0b0
+
+        exp, frac, FPSCR <- Round_Single(sign, exp, frac[0:52], 0b0, 0b0, 0b0, FPSCR)
+        FPSCR['XX'] <- FPSCR['XX'] | FPSCR['FI']
+        exp <- exp + 192
+        FRT <- [0b0] * 64
+        FRT[0] <- sign
+        FRT[1:11] <- exp + 1023
+        FRT[12:63] <- frac[1:52]
+        if sign = 0 then FPSCR['FPRF'] <- '+ normal number'
+        if sign = 1 then FPSCR['FPRF'] <- '- normal number'
+        return FRT, FPSCR
+
+    def FRSP_Disabled_Exponent_Overflow(FRB, FPSCR):
+        FPSCR['OX'] <- 1
+        FRT <- [0b0] * 64
+        if FPSCR['RN'] = 0b00 then             # Round to Nearest
+            if (FRB)[0] = 0 then FRT <- 0x7FF0_0000_0000_0000
+            if (FRB)[0] = 1 then FRT <- 0xFFF0_0000_0000_0000
+            if (FRB)[0] = 0 then FPSCR['FPRF'] <- '+ infinity'
+            if (FRB)[0] = 1 then FPSCR['FPRF'] <- '- infinity'
+        if FPSCR['RN'] = 0b01 then             # Round toward Zero
+            if (FRB)[0] = 0 then FRT <- 0x47EF_FFFF_E000_0000
+            if (FRB)[0] = 1 then FRT <- 0xC7EF_FFFF_E000_0000
+            if (FRB)[0] = 0 then FPSCR['FPRF'] <- '+ normal number'
+            if (FRB)[0] = 1 then FPSCR['FPRF'] <- '- normal number'
+        if FPSCR['RN'] = 0b10 then             # Round toward +Infinity
+            if (FRB)[0] = 0 then FRT <- 0x7FF0_0000_0000_0000
+            if (FRB)[0] = 1 then FRT <- 0xC7EF_FFFF_E000_0000
+            if (FRB)[0] = 0 then FPSCR['FPRF'] <- '+ infinity'
+            if (FRB)[0] = 1 then FPSCR['FPRF'] <- '- normal number'
+        if FPSCR['RN'] = 0b11 then             # Round toward -Infinity
+            if (FRB)[0] = 0 then FRT <- 0x47EF_FFFF_E000_0000
+            if (FRB)[0] = 1 then FRT <- 0xFFF0_0000_0000_0000
+            if (FRB)[0] = 0 then FPSCR['FPRF'] <- '+ normal number'
+            if (FRB)[0] = 1 then FPSCR['FPRF'] <- '- infinity'
+        FPSCR['FR'] <- undefined(0) # FIXME: figure out what values POWER9 uses
+        FPSCR['FI'] <- 1
+        FPSCR['XX'] <- 1
+        return FRT, FPSCR
+
+    def FRSP_Enabled_Exponent_Overflow(FRB, FPSCR):
+        sign <- (FRB)[0]
+        exp <- (FRB)[1:11] - 1023
+        frac <- [0b0] * 53
+        frac[0:52] <- 0b1 || (FRB)[12:63]
+        exp, frac, FPSCR <- Round_Single(sign, exp, frac[0:52], 0b0, 0b0, 0b0, FPSCR)
+        FPSCR['XX'] <- FPSCR['XX'] | FPSCR['FI']
+        # Enabled Overflow:
+        FPSCR['OX'] <- 1
+        exp <- exp - 192
+        FRT <- [0b0] * 64
+        FRT[0] <- sign
+        FRT[1:11] <- exp + 1023
+        FRT[12:63] <- frac[1:52]
+        if sign = 0 then FPSCR['FPRF'] <- '+ normal number'
+        if sign = 1 then FPSCR['FPRF'] <- '- normal number'
+        return FRT, FPSCR
+
+    def FRSP_Zero_Operand(FRB, FPSCR):
+        FRT <- (FRB)
+        if (FRB)[0] = 0 then FPSCR['FPRF'] <- '+ zero'
+        if (FRB)[0] = 1 then FPSCR['FPRF'] <- '- zero'
+        FPSCR['FRFI'] <- 0b00
+        return FRT, FPSCR
+
+    def FRSP_Infinity_Operand(FRB, FPSCR):
+        FRT <- (FRB)
+        if (FRB)[0] = 0 then FPSCR['FPRF'] <- '+ infinity'
+        if (FRB)[0] = 1 then FPSCR['FPRF'] <- '- infinity'
+        FPSCR['FRFI'] <- 0b00
+        return FRT, FPSCR
+
+    def FRSP_QNaN_Operand(FRB, FPSCR):
+        FRT <- (FRB)[0:34] || [0b0] * 29
+        FPSCR['FPRF'] <- 'QNaN'
+        FPSCR['FR'] <- 0b0
+        FPSCR['FI'] <- 0b0
+        return FRT, FPSCR
+
+    def FRSP_SNaN_Operand(FRB, FPSCR):
+        FPSCR['VXSNAN'] <- 1
+        FRT <- [0b0] * 64
+        if FPSCR['VE'] = 0 then
+            FRT[0:11] <- (FRB)[0:11]
+            FRT[12] <- 1
+            FRT[13:63] <- (FRB)[13:34] || [0b0] * 29
+            FPSCR['FPRF'] <- 'QNaN'
+        FPSCR['FR'] <- 0b0
+        FPSCR['FI'] <- 0b0
+        return FRT, FPSCR
+
+    def FRSP_Normal_Operand(FRB, FPSCR):
+        sign <- (FRB)[0]
+        exp <- (FRB)[1:11] - 1023
+        frac <- [0b0] * 53
+        frac[0:52] <- 0b1 || (FRB)[12:63]
+        exp, frac, FPSCR <- Round_Single(sign, exp, frac[0:52], 0b0, 0b0, 0b0, FPSCR)
+        FPSCR['XX'] <- FPSCR['XX'] | FPSCR['FI']
+        if (exp > 127) & (FPSCR['OE'] = 0) then
+            return FRSP_Disabled_Exponent_Overflow(FRB, FPSCR)
+        if (exp > 127) & (FPSCR['OE'] = 1) then
+            return FRSP_Enabled_Overflow(FRB, FPSCR)
+        FRT <- [0b0] * 64
+        FRT[0] <- sign
+        FRT[1:11] <- exp + 1023
+        FRT[12:63] <- frac[1:52]
+        if sign = 0 then FPSCR['FPRF'] <- '+ normal number'
+        if sign = 1 then FPSCR['FPRF'] <- '- normal number'
+        return FRT, FPSCR
+
+    def Round_Single(sign, exp, frac, G, R, X, FPSCR):
         inc <- 0
-        lsb  <- frac[23]
+        lsb <- frac[23]
         gbit <- frac[24]
         rbit <- frac[25]
-        xbit <- (frac[26:52] || G || R || X) != 0
-
-        if round_mode  = 0b00  then           # Round to Nearest
-            if (lsb = 1) & (gbit = 1)              then inc <- 1
-            if (lsb = 0) & (gbit = 1) & (rbit = 1) then inc <- 1
-            if (lsb = 0) & (gbit = 1) & (xbit = 1) then inc <- 1
-        if round_mode  = 0b10  then           # Round toward + Infinity
-            if (sign = 0) & (gbit = 1) then inc <-1
-            if (sign = 0) & (rbit = 1) then inc <-1
-            if (sign = 0) & (xbit = 1) then inc <-1
-        if round_mode  = 0b11  then           # Round toward - Infinity
-            if (sign = 1) & (gbit = 1) then inc <-1
-            if (sign = 1) & (rbit = 1) then inc <-1
-            if (sign = 1) & (xbit = 1) then inc <-1
-
-        # add with carry-out
-        tmp        <- [0]*25
-        tmp[1:24]  <- frac[0:23]
-        tmp[0:24]  <- tmp[0:24] + inc
-        carry_out  <- tmp[0]
-        frac[0:23] <- tmp[1:24]
-        if carry_out = 1 then
-            exp[0:10] <- exp + 1
+        xbit <- (frac[26:52]||G||R||X) != 0
+        if FPSCR['RN'] = 0b00 then                       # Round to Nearest
+            # comparisons ignore u bits
+            if (lsb || gbit) = 0b11 then inc <- 1
+            if (lsb || gbit || rbit) = 0b011 then inc <- 1
+            if (lsb || gbit || xbit) = 0b011 then inc <- 1
+        if FPSCR['RN'] = 0b10 then                       # Round toward + Infinity
+            # comparisons ignore u bits
+            if (sign || gbit) = 0b01 then inc <- 1
+            if (sign || rbit) = 0b01 then inc <- 1
+            if (sign || xbit) = 0b01 then inc <- 1
+        if FPSCR['RN'] = 0b11 then                       # Round toward - Infinity
+            # comparisons ignore u bits
+            if (sign || gbit) = 0b11 then inc <- 1
+            if (sign || rbit) = 0b11 then inc <- 1
+            if (sign || xbit) = 0b11 then inc <- 1
+        frac[0:23] <- frac[0:23] + inc
+        if (inc = 1) & (frac[0:23] = 0) then
             frac[0:23] <- 0b1 || frac[0:22]
-        frac[24:52] <- [0]*29
-        # TODO, later
-        # FPSCR[FR] <- inc
-        # FPSCR[FI] <- gbit || rbit || xbit
-
-    def DOUBLE2SINGLE(FR):
-        if (FR[1:11] <u 897) & (FR[1:63] >u 0) then
-            # exponent underflow
-            mode = 'disabled_exp_underflow'
-            # TODO if FPSCR_UE = 0 then mode = 'disabled_exp_underflow'
-            # TODO if FPSCR_UE = 1 then mode = 'enabled_exp_underflow'
-        else if (FR[1:11] >u 1150) & (FR[1:11] <u 2047) then
-            # exponent overflow
-            mode = 'disabled_exp_overflow'
-            # TODO if FPSCR_OE = 0 then mode = 'disabled_exp_overflow'
-            # TODO if FPSCR_OE = 1 then mode = 'enabled_exp_overflow'
-        else if (FR[1:11] >u 896) & (FR[1:11] <u 1151) then
-            # normal operand
-            mode <- 'normal_operand'
-        else if (FR[1:63] = 0) then
-            # zero operand
-            mode <- 'zero_operand'
-        else if (FR[1:11] = 2047) then
-            # inf / nan
-            if (FR[12:63] = 0) then
-                mode <- 'inf_operand'
-            else if (FR[12] = 1) then
-                mode <- 'qnan_operand'
-            else if (FR[12] = 0) & (FR[13:63] >u 0) then
-                mode <- 'snan_operand'
-
-        frac <- [0]*53
-        exp <- [0]*11
-        result <- [0] * 64
-
-        if mode = 'normal_operand' then
-            sign       <- FR[0]
-            exp <- FR[1:11] - 1023
-            frac[0:52] <- 0b1 || FR[12:63]
-            RN <- 0b00 # TODO
-            Round_Single(sign, exp, frac, 0b0, 0b0, 0b0, RN)
-            # TODO FPSCR[XX] <- FPSCR[XX] || FPSCR[FI]
-            if exp > 127 then
-                mode = 'disabled_exp_overflow'
-                #   if FPSCR_OE = 0 then mode = 'disabled_exp_overflow'
-                #   if FPSCR_OE = 1 then mode = 'enabled_overflow'
-            else
-                result[0] <- sign
-                result[1:11] <- exp + 1023
-                result[12:63] <- frac[1:52]
-                # if sign = 0 then 
-                #    FPSCR[FPRF] <- '+ normal number'
-                # else
-                #    FPSCR[FPRF] <- '- normal number'
-
-        if mode = 'enabled_exp_underflow':
-            sign       <- FR[0]
-            if FR[1:11] = 0 then
-                exp <- 1022
-                frac[0:52] <- 0b0 || FRB[12:63]
-            if FR[1:11] >u 0 then
-                exp <- FRB[1:11] - 1023
-                frac[0:52] <- 0b1 || FRB[12:63]
-            # denormalise operand
-            G = 0b0
-            R = 0b0
-            X = 0b0
-            do while exp < -126
-                exp <- exp + 1
-                X <- R | X
-                R <- G
-                G <- frac[52]
-                frac[0:52] <- frac[1:52] || 0b0
-            # TODO
-            # FPCSR_UX <- (frac[0:52] || G || R || X) >u 0)
-            RN <- 0b00 # TODO
-            Round_Single(sign, exp, frac, G, R, X, RN)
-
-        if mode = 'zero_operand':
-            # Zero Operand
-            result[0]  <- FR[0] # copy sign, the rest is zero
-            # TODO, FPSCR
-            #FPSCR[FR] <- 0b00
-            #FPSCR[FI] <- 0b00
-            #FPSCR[FPRF] <- '+ zero'
-
-        if mode = 'disabled_exp_underflow':
-            if sign = 1 then frac[0:63] <- ¬frac[0:63] + 1
-            # do the loop 0 times if FR = max negative 64-bit integer or
-            #                     if FR = max unsigned 64-bit integer 
-            do while frac[0] = 0
-                frac[0:63] <- frac[1:63] || 0b0
-                exp <- exp - 1
-            # round to nearest
-            RN <- 0b00 # TODO, FPSCR[RN]
-            Round_Float( tgt_precision, sign, exp, frac, RN )
-            # TODO, FPSCR
-            #if sign = 0 then FPSCR[FPRF] <- '+normal number'
-            #if sign = 1 then FPSCR[FPRF] <- '-normal number'
-            result[0]    <- sign
-            result[1:11] <- exp + 1023     # exp + bias
-            result[12:63] <- frac[1:52]
-
-        return result
+            exp <- exp + 1
+        frac[24:52] <- [0b0] * 29
+        FPSCR['FR'] <- inc
+        FPSCR['FI'] <- gbit | rbit | xbit
+        return exp, frac, FPSCR
 
 <!-- Power ISA v3.0B p140 section 4.6.2 -->
 
index 3dba556771aacd8bda20884a14e0c2be4bc66e1a..1929315d563ecf43372b41631cf26b9a1551cae8 100644 (file)
@@ -471,6 +471,19 @@ class ISACallerHelper:
     def EXTSXL(self, value, bits):
         return SelectableInt(exts(value.value, bits), self.XLEN)
 
+    def DOUBLE2SINGLE(self, FRS):
+        # DOUBLE2SINGLE has been renamed to FRSP since it is the
+        # implementation of the frsp instruction.
+        # use SINGLE() or FRSP() instead, or just use struct.pack/unpack
+        FPSCR = {
+            'UE': SelectableInt(0, 1),
+            'OE': SelectableInt(0, 1),
+            'RN': SelectableInt(0, 2),  # round to nearest, ties to even
+            'XX': SelectableInt(0, 1),
+        }
+        FRT, FPSCR = self.FRSP(FRS, FPSCR)
+        return FRT
+
     def __getattr__(self, attr):
         try:
             return globals()[attr]