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 -->