From d648bc9ed1fc7403e41011ed2d06ba1d08b0939a Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Thu, 28 Jul 2022 02:50:30 -0700 Subject: [PATCH] re-convert frsp pseudocode Fixes: https://bugs.libre-soc.org/show_bug.cgi?id=896 --- openpower/isafunctions/double2single.mdwn | 358 ++++++++++++++-------- src/openpower/decoder/helpers.py | 13 + 2 files changed, 241 insertions(+), 130 deletions(-) diff --git a/openpower/isafunctions/double2single.mdwn b/openpower/isafunctions/double2single.mdwn index b731cc04..1c88612a 100644 --- a/openpower/isafunctions/double2single.mdwn +++ b/openpower/isafunctions/double2single.mdwn @@ -3,141 +3,239 @@ The following describes algorithmically the operation of the Floating Round to Single-Precision instruction. - + - def Round_Single( sign, exp, frac, G, R, X, round_mode ): + def FRSP(FRB, FPSCR): + if ((FRB)[1:11] 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 896) & ((FRB)[1:11] 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 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 896) & (FR[1:11] 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 diff --git a/src/openpower/decoder/helpers.py b/src/openpower/decoder/helpers.py index 3dba5567..1929315d 100644 --- a/src/openpower/decoder/helpers.py +++ b/src/openpower/decoder/helpers.py @@ -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] -- 2.30.2