[PATCH] ARM: 2837/2: Re: ARM: Make NWFPE preempt safe

Patch from Richard Purdie

NWFPE used global variables which meant it wasn't safe for use with
preemptive kernels. This patch removes them and communicates the
information between functions in a preempt safe manner. Generation
of some exceptions was broken and this has also been corrected.
Tests with glibc's maths test suite show no change in the results
before/after this patch.

Signed-off-by: Richard Purdie <rpurdie@rpsys.net>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by Richard Purdie and committed by Russell King f148af25 1fcf8448

+304 -304
+12 -12
arch/arm/nwfpe/double_cpdo.c
··· 40 float64 float64_pow(float64 rFn, float64 rFm); 41 float64 float64_pol(float64 rFn, float64 rFm); 42 43 - static float64 float64_rsf(float64 rFn, float64 rFm) 44 { 45 - return float64_sub(rFm, rFn); 46 } 47 48 - static float64 float64_rdv(float64 rFn, float64 rFm) 49 { 50 - return float64_div(rFm, rFn); 51 } 52 53 - static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = { 54 [ADF_CODE >> 20] = float64_add, 55 [MUF_CODE >> 20] = float64_mul, 56 [SUF_CODE >> 20] = float64_sub, ··· 65 [FRD_CODE >> 20] = float64_rdv, 66 }; 67 68 - static float64 float64_mvf(float64 rFm) 69 { 70 return rFm; 71 } 72 73 - static float64 float64_mnf(float64 rFm) 74 { 75 union float64_components u; 76 ··· 84 return u.f64; 85 } 86 87 - static float64 float64_abs(float64 rFm) 88 { 89 union float64_components u; 90 ··· 98 return u.f64; 99 } 100 101 - static float64 (*const monadic_double[16])(float64 rFm) = { 102 [MVF_CODE >> 20] = float64_mvf, 103 [MNF_CODE >> 20] = float64_mnf, 104 [ABS_CODE >> 20] = float64_abs, ··· 108 [NRM_CODE >> 20] = float64_mvf, 109 }; 110 111 - unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd) 112 { 113 FPA11 *fpa11 = GET_FPA11(); 114 float64 rFm; ··· 151 } 152 153 if (dyadic_double[opc_mask_shift]) { 154 - rFd->fDouble = dyadic_double[opc_mask_shift](rFn, rFm); 155 } else { 156 return 0; 157 } 158 } else { 159 if (monadic_double[opc_mask_shift]) { 160 - rFd->fDouble = monadic_double[opc_mask_shift](rFm); 161 } else { 162 return 0; 163 }
··· 40 float64 float64_pow(float64 rFn, float64 rFm); 41 float64 float64_pol(float64 rFn, float64 rFm); 42 43 + static float64 float64_rsf(struct roundingData *roundData, float64 rFn, float64 rFm) 44 { 45 + return float64_sub(roundData, rFm, rFn); 46 } 47 48 + static float64 float64_rdv(struct roundingData *roundData, float64 rFn, float64 rFm) 49 { 50 + return float64_div(roundData, rFm, rFn); 51 } 52 53 + static float64 (*const dyadic_double[16])(struct roundingData*, float64 rFn, float64 rFm) = { 54 [ADF_CODE >> 20] = float64_add, 55 [MUF_CODE >> 20] = float64_mul, 56 [SUF_CODE >> 20] = float64_sub, ··· 65 [FRD_CODE >> 20] = float64_rdv, 66 }; 67 68 + static float64 float64_mvf(struct roundingData *roundData,float64 rFm) 69 { 70 return rFm; 71 } 72 73 + static float64 float64_mnf(struct roundingData *roundData,float64 rFm) 74 { 75 union float64_components u; 76 ··· 84 return u.f64; 85 } 86 87 + static float64 float64_abs(struct roundingData *roundData,float64 rFm) 88 { 89 union float64_components u; 90 ··· 98 return u.f64; 99 } 100 101 + static float64 (*const monadic_double[16])(struct roundingData *, float64 rFm) = { 102 [MVF_CODE >> 20] = float64_mvf, 103 [MNF_CODE >> 20] = float64_mnf, 104 [ABS_CODE >> 20] = float64_abs, ··· 108 [NRM_CODE >> 20] = float64_mvf, 109 }; 110 111 + unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd) 112 { 113 FPA11 *fpa11 = GET_FPA11(); 114 float64 rFm; ··· 151 } 152 153 if (dyadic_double[opc_mask_shift]) { 154 + rFd->fDouble = dyadic_double[opc_mask_shift](roundData, rFn, rFm); 155 } else { 156 return 0; 157 } 158 } else { 159 if (monadic_double[opc_mask_shift]) { 160 + rFd->fDouble = monadic_double[opc_mask_shift](roundData, rFm); 161 } else { 162 return 0; 163 }
+12 -12
arch/arm/nwfpe/extended_cpdo.c
··· 35 floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm); 36 floatx80 floatx80_pol(floatx80 rFn, floatx80 rFm); 37 38 - static floatx80 floatx80_rsf(floatx80 rFn, floatx80 rFm) 39 { 40 - return floatx80_sub(rFm, rFn); 41 } 42 43 - static floatx80 floatx80_rdv(floatx80 rFn, floatx80 rFm) 44 { 45 - return floatx80_div(rFm, rFn); 46 } 47 48 - static floatx80 (*const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) = { 49 [ADF_CODE >> 20] = floatx80_add, 50 [MUF_CODE >> 20] = floatx80_mul, 51 [SUF_CODE >> 20] = floatx80_sub, ··· 60 [FRD_CODE >> 20] = floatx80_rdv, 61 }; 62 63 - static floatx80 floatx80_mvf(floatx80 rFm) 64 { 65 return rFm; 66 } 67 68 - static floatx80 floatx80_mnf(floatx80 rFm) 69 { 70 rFm.high ^= 0x8000; 71 return rFm; 72 } 73 74 - static floatx80 floatx80_abs(floatx80 rFm) 75 { 76 rFm.high &= 0x7fff; 77 return rFm; 78 } 79 80 - static floatx80 (*const monadic_extended[16])(floatx80 rFm) = { 81 [MVF_CODE >> 20] = floatx80_mvf, 82 [MNF_CODE >> 20] = floatx80_mnf, 83 [ABS_CODE >> 20] = floatx80_abs, ··· 87 [NRM_CODE >> 20] = floatx80_mvf, 88 }; 89 90 - unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd) 91 { 92 FPA11 *fpa11 = GET_FPA11(); 93 floatx80 rFm; ··· 138 } 139 140 if (dyadic_extended[opc_mask_shift]) { 141 - rFd->fExtended = dyadic_extended[opc_mask_shift](rFn, rFm); 142 } else { 143 return 0; 144 } 145 } else { 146 if (monadic_extended[opc_mask_shift]) { 147 - rFd->fExtended = monadic_extended[opc_mask_shift](rFm); 148 } else { 149 return 0; 150 }
··· 35 floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm); 36 floatx80 floatx80_pol(floatx80 rFn, floatx80 rFm); 37 38 + static floatx80 floatx80_rsf(struct roundingData *roundData, floatx80 rFn, floatx80 rFm) 39 { 40 + return floatx80_sub(roundData, rFm, rFn); 41 } 42 43 + static floatx80 floatx80_rdv(struct roundingData *roundData, floatx80 rFn, floatx80 rFm) 44 { 45 + return floatx80_div(roundData, rFm, rFn); 46 } 47 48 + static floatx80 (*const dyadic_extended[16])(struct roundingData*, floatx80 rFn, floatx80 rFm) = { 49 [ADF_CODE >> 20] = floatx80_add, 50 [MUF_CODE >> 20] = floatx80_mul, 51 [SUF_CODE >> 20] = floatx80_sub, ··· 60 [FRD_CODE >> 20] = floatx80_rdv, 61 }; 62 63 + static floatx80 floatx80_mvf(struct roundingData *roundData, floatx80 rFm) 64 { 65 return rFm; 66 } 67 68 + static floatx80 floatx80_mnf(struct roundingData *roundData, floatx80 rFm) 69 { 70 rFm.high ^= 0x8000; 71 return rFm; 72 } 73 74 + static floatx80 floatx80_abs(struct roundingData *roundData, floatx80 rFm) 75 { 76 rFm.high &= 0x7fff; 77 return rFm; 78 } 79 80 + static floatx80 (*const monadic_extended[16])(struct roundingData*, floatx80 rFm) = { 81 [MVF_CODE >> 20] = floatx80_mvf, 82 [MNF_CODE >> 20] = floatx80_mnf, 83 [ABS_CODE >> 20] = floatx80_abs, ··· 87 [NRM_CODE >> 20] = floatx80_mvf, 88 }; 89 90 + unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd) 91 { 92 FPA11 *fpa11 = GET_FPA11(); 93 floatx80 rFm; ··· 138 } 139 140 if (dyadic_extended[opc_mask_shift]) { 141 + rFd->fExtended = dyadic_extended[opc_mask_shift](roundData, rFn, rFm); 142 } else { 143 return 0; 144 } 145 } else { 146 if (monadic_extended[opc_mask_shift]) { 147 + rFd->fExtended = monadic_extended[opc_mask_shift](roundData, rFm); 148 } else { 149 return 0; 150 }
+11 -19
arch/arm/nwfpe/fpa11.c
··· 51 fpa11->fpsr = FP_EMULATOR | BIT_AC; 52 } 53 54 - void SetRoundingMode(const unsigned int opcode) 55 { 56 switch (opcode & MASK_ROUNDING_MODE) { 57 default: 58 case ROUND_TO_NEAREST: 59 - float_rounding_mode = float_round_nearest_even; 60 - break; 61 62 case ROUND_TO_PLUS_INFINITY: 63 - float_rounding_mode = float_round_up; 64 - break; 65 66 case ROUND_TO_MINUS_INFINITY: 67 - float_rounding_mode = float_round_down; 68 - break; 69 70 case ROUND_TO_ZERO: 71 - float_rounding_mode = float_round_to_zero; 72 - break; 73 } 74 } 75 76 - void SetRoundingPrecision(const unsigned int opcode) 77 { 78 #ifdef CONFIG_FPE_NWFPE_XP 79 switch (opcode & MASK_ROUNDING_PRECISION) { 80 case ROUND_SINGLE: 81 - floatx80_rounding_precision = 32; 82 - break; 83 84 case ROUND_DOUBLE: 85 - floatx80_rounding_precision = 64; 86 - break; 87 88 case ROUND_EXTENDED: 89 - floatx80_rounding_precision = 80; 90 - break; 91 92 default: 93 - floatx80_rounding_precision = 80; 94 } 95 #endif 96 } 97 98 void nwfpe_init_fpa(union fp_state *fp) ··· 97 #endif 98 memset(fpa11, 0, sizeof(FPA11)); 99 resetFPA11(); 100 - SetRoundingMode(ROUND_TO_NEAREST); 101 - SetRoundingPrecision(ROUND_EXTENDED); 102 fpa11->initflag = 1; 103 } 104
··· 51 fpa11->fpsr = FP_EMULATOR | BIT_AC; 52 } 53 54 + int8 SetRoundingMode(const unsigned int opcode) 55 { 56 switch (opcode & MASK_ROUNDING_MODE) { 57 default: 58 case ROUND_TO_NEAREST: 59 + return float_round_nearest_even; 60 61 case ROUND_TO_PLUS_INFINITY: 62 + return float_round_up; 63 64 case ROUND_TO_MINUS_INFINITY: 65 + return float_round_down; 66 67 case ROUND_TO_ZERO: 68 + return float_round_to_zero; 69 } 70 } 71 72 + int8 SetRoundingPrecision(const unsigned int opcode) 73 { 74 #ifdef CONFIG_FPE_NWFPE_XP 75 switch (opcode & MASK_ROUNDING_PRECISION) { 76 case ROUND_SINGLE: 77 + return 32; 78 79 case ROUND_DOUBLE: 80 + return 64; 81 82 case ROUND_EXTENDED: 83 + return 80; 84 85 default: 86 + return 80; 87 } 88 #endif 89 + return 80; 90 } 91 92 void nwfpe_init_fpa(union fp_state *fp) ··· 103 #endif 104 memset(fpa11, 0, sizeof(FPA11)); 105 resetFPA11(); 106 fpa11->initflag = 1; 107 } 108
+9 -2
arch/arm/nwfpe/fpa11.h
··· 37 /* includes */ 38 #include "fpsr.h" /* FP control and status register definitions */ 39 #include "milieu.h" 40 #include "softfloat.h" 41 42 #define typeNone 0x00 ··· 91 initialised. */ 92 } FPA11; 93 94 - extern void SetRoundingMode(const unsigned int); 95 - extern void SetRoundingPrecision(const unsigned int); 96 extern void nwfpe_init_fpa(union fp_state *fp); 97 98 #endif
··· 37 /* includes */ 38 #include "fpsr.h" /* FP control and status register definitions */ 39 #include "milieu.h" 40 + 41 + struct roundingData { 42 + int8 mode; 43 + int8 precision; 44 + signed char exception; 45 + }; 46 + 47 #include "softfloat.h" 48 49 #define typeNone 0x00 ··· 84 initialised. */ 85 } FPA11; 86 87 + extern int8 SetRoundingMode(const unsigned int); 88 + extern int8 SetRoundingPrecision(const unsigned int); 89 extern void nwfpe_init_fpa(union fp_state *fp); 90 91 #endif
+17 -11
arch/arm/nwfpe/fpa11_cpdo.c
··· 24 #include "fpa11.h" 25 #include "fpopcode.h" 26 27 - unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd); 28 - unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd); 29 - unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd); 30 31 unsigned int EmulateCPDO(const unsigned int opcode) 32 { 33 FPA11 *fpa11 = GET_FPA11(); 34 FPREG *rFd; 35 unsigned int nType, nDest, nRc; 36 37 /* Get the destination size. If not valid let Linux perform 38 an invalid instruction trap. */ ··· 41 if (typeNone == nDest) 42 return 0; 43 44 - SetRoundingMode(opcode); 45 46 /* Compare the size of the operands in Fn and Fm. 47 Choose the largest size and perform operations in that size, ··· 66 67 switch (nType) { 68 case typeSingle: 69 - nRc = SingleCPDO(opcode, rFd); 70 break; 71 case typeDouble: 72 - nRc = DoubleCPDO(opcode, rFd); 73 break; 74 #ifdef CONFIG_FPE_NWFPE_XP 75 case typeExtended: 76 - nRc = ExtendedCPDO(opcode, rFd); 77 break; 78 #endif 79 default: ··· 96 case typeSingle: 97 { 98 if (typeDouble == nType) 99 - rFd->fSingle = float64_to_float32(rFd->fDouble); 100 else 101 - rFd->fSingle = floatx80_to_float32(rFd->fExtended); 102 } 103 break; 104 ··· 107 if (typeSingle == nType) 108 rFd->fDouble = float32_to_float64(rFd->fSingle); 109 else 110 - rFd->fDouble = floatx80_to_float64(rFd->fExtended); 111 } 112 break; 113 ··· 124 #else 125 if (nDest != nType) { 126 if (nDest == typeSingle) 127 - rFd->fSingle = float64_to_float32(rFd->fDouble); 128 else 129 rFd->fDouble = float32_to_float64(rFd->fSingle); 130 } 131 #endif 132 } 133 134 return nRc; 135 }
··· 24 #include "fpa11.h" 25 #include "fpopcode.h" 26 27 + unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd); 28 + unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd); 29 + unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd); 30 31 unsigned int EmulateCPDO(const unsigned int opcode) 32 { 33 FPA11 *fpa11 = GET_FPA11(); 34 FPREG *rFd; 35 unsigned int nType, nDest, nRc; 36 + struct roundingData roundData; 37 38 /* Get the destination size. If not valid let Linux perform 39 an invalid instruction trap. */ ··· 40 if (typeNone == nDest) 41 return 0; 42 43 + roundData.mode = SetRoundingMode(opcode); 44 + roundData.precision = SetRoundingPrecision(opcode); 45 + roundData.exception = 0; 46 47 /* Compare the size of the operands in Fn and Fm. 48 Choose the largest size and perform operations in that size, ··· 63 64 switch (nType) { 65 case typeSingle: 66 + nRc = SingleCPDO(&roundData, opcode, rFd); 67 break; 68 case typeDouble: 69 + nRc = DoubleCPDO(&roundData, opcode, rFd); 70 break; 71 #ifdef CONFIG_FPE_NWFPE_XP 72 case typeExtended: 73 + nRc = ExtendedCPDO(&roundData, opcode, rFd); 74 break; 75 #endif 76 default: ··· 93 case typeSingle: 94 { 95 if (typeDouble == nType) 96 + rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble); 97 else 98 + rFd->fSingle = floatx80_to_float32(&roundData, rFd->fExtended); 99 } 100 break; 101 ··· 104 if (typeSingle == nType) 105 rFd->fDouble = float32_to_float64(rFd->fSingle); 106 else 107 + rFd->fDouble = floatx80_to_float64(&roundData, rFd->fExtended); 108 } 109 break; 110 ··· 121 #else 122 if (nDest != nType) { 123 if (nDest == typeSingle) 124 + rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble); 125 else 126 rFd->fDouble = float32_to_float64(rFd->fSingle); 127 } 128 #endif 129 } 130 + 131 + if (roundData.exception) 132 + float_raise(roundData.exception); 133 134 return nRc; 135 }
+14 -8
arch/arm/nwfpe/fpa11_cpdt.c
··· 96 } 97 } 98 99 - static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem) 100 { 101 FPA11 *fpa11 = GET_FPA11(); 102 union { ··· 106 107 switch (fpa11->fType[Fn]) { 108 case typeDouble: 109 - val.f = float64_to_float32(fpa11->fpreg[Fn].fDouble); 110 break; 111 112 #ifdef CONFIG_FPE_NWFPE_XP 113 case typeExtended: 114 - val.f = floatx80_to_float32(fpa11->fpreg[Fn].fExtended); 115 break; 116 #endif 117 ··· 122 put_user(val.i[0], pMem); 123 } 124 125 - static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem) 126 { 127 FPA11 *fpa11 = GET_FPA11(); 128 union { ··· 137 138 #ifdef CONFIG_FPE_NWFPE_XP 139 case typeExtended: 140 - val.f = floatx80_to_float64(fpa11->fpreg[Fn].fExtended); 141 break; 142 #endif 143 ··· 259 { 260 unsigned int __user *pBase, *pAddress, *pFinal; 261 unsigned int nRc = 1, write_back = WRITE_BACK(opcode); 262 263 - SetRoundingMode(ROUND_TO_NEAREST); 264 265 pBase = (unsigned int __user *) readRegister(getRn(opcode)); 266 if (REG_PC == getRn(opcode)) { ··· 284 285 switch (opcode & MASK_TRANSFER_LENGTH) { 286 case TRANSFER_SINGLE: 287 - storeSingle(getFd(opcode), pAddress); 288 break; 289 case TRANSFER_DOUBLE: 290 - storeDouble(getFd(opcode), pAddress); 291 break; 292 #ifdef CONFIG_FPE_NWFPE_XP 293 case TRANSFER_EXTENDED: ··· 297 default: 298 nRc = 0; 299 } 300 301 if (write_back) 302 writeRegister(getRn(opcode), (unsigned long) pFinal);
··· 96 } 97 } 98 99 + static inline void storeSingle(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem) 100 { 101 FPA11 *fpa11 = GET_FPA11(); 102 union { ··· 106 107 switch (fpa11->fType[Fn]) { 108 case typeDouble: 109 + val.f = float64_to_float32(roundData, fpa11->fpreg[Fn].fDouble); 110 break; 111 112 #ifdef CONFIG_FPE_NWFPE_XP 113 case typeExtended: 114 + val.f = floatx80_to_float32(roundData, fpa11->fpreg[Fn].fExtended); 115 break; 116 #endif 117 ··· 122 put_user(val.i[0], pMem); 123 } 124 125 + static inline void storeDouble(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem) 126 { 127 FPA11 *fpa11 = GET_FPA11(); 128 union { ··· 137 138 #ifdef CONFIG_FPE_NWFPE_XP 139 case typeExtended: 140 + val.f = floatx80_to_float64(roundData, fpa11->fpreg[Fn].fExtended); 141 break; 142 #endif 143 ··· 259 { 260 unsigned int __user *pBase, *pAddress, *pFinal; 261 unsigned int nRc = 1, write_back = WRITE_BACK(opcode); 262 + struct roundingData roundData; 263 264 + roundData.mode = SetRoundingMode(opcode); 265 + roundData.precision = SetRoundingPrecision(opcode); 266 + roundData.exception = 0; 267 268 pBase = (unsigned int __user *) readRegister(getRn(opcode)); 269 if (REG_PC == getRn(opcode)) { ··· 281 282 switch (opcode & MASK_TRANSFER_LENGTH) { 283 case TRANSFER_SINGLE: 284 + storeSingle(&roundData, getFd(opcode), pAddress); 285 break; 286 case TRANSFER_DOUBLE: 287 + storeDouble(&roundData, getFd(opcode), pAddress); 288 break; 289 #ifdef CONFIG_FPE_NWFPE_XP 290 case TRANSFER_EXTENDED: ··· 294 default: 295 nRc = 0; 296 } 297 + 298 + if (roundData.exception) 299 + float_raise(roundData.exception); 300 301 if (write_back) 302 writeRegister(getRn(opcode), (unsigned long) pFinal);
+19 -9
arch/arm/nwfpe/fpa11_cprt.c
··· 33 extern flag float64_is_nan(float64); 34 extern flag float32_is_nan(float32); 35 36 - void SetRoundingMode(const unsigned int opcode); 37 - 38 unsigned int PerformFLT(const unsigned int opcode); 39 unsigned int PerformFIX(const unsigned int opcode); 40 ··· 75 unsigned int PerformFLT(const unsigned int opcode) 76 { 77 FPA11 *fpa11 = GET_FPA11(); 78 - SetRoundingMode(opcode); 79 - SetRoundingPrecision(opcode); 80 81 switch (opcode & MASK_ROUNDING_PRECISION) { 82 case ROUND_SINGLE: 83 { 84 fpa11->fType[getFn(opcode)] = typeSingle; 85 - fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(readRegister(getRd(opcode))); 86 } 87 break; 88 ··· 109 return 0; 110 } 111 112 return 1; 113 } 114 ··· 119 { 120 FPA11 *fpa11 = GET_FPA11(); 121 unsigned int Fn = getFm(opcode); 122 123 - SetRoundingMode(opcode); 124 125 switch (fpa11->fType[Fn]) { 126 case typeSingle: 127 { 128 - writeRegister(getRd(opcode), float32_to_int32(fpa11->fpreg[Fn].fSingle)); 129 } 130 break; 131 132 case typeDouble: 133 { 134 - writeRegister(getRd(opcode), float64_to_int32(fpa11->fpreg[Fn].fDouble)); 135 } 136 break; 137 138 #ifdef CONFIG_FPE_NWFPE_XP 139 case typeExtended: 140 { 141 - writeRegister(getRd(opcode), floatx80_to_int32(fpa11->fpreg[Fn].fExtended)); 142 } 143 break; 144 #endif ··· 149 default: 150 return 0; 151 } 152 153 return 1; 154 }
··· 33 extern flag float64_is_nan(float64); 34 extern flag float32_is_nan(float32); 35 36 unsigned int PerformFLT(const unsigned int opcode); 37 unsigned int PerformFIX(const unsigned int opcode); 38 ··· 77 unsigned int PerformFLT(const unsigned int opcode) 78 { 79 FPA11 *fpa11 = GET_FPA11(); 80 + struct roundingData roundData; 81 + 82 + roundData.mode = SetRoundingMode(opcode); 83 + roundData.precision = SetRoundingPrecision(opcode); 84 + roundData.exception = 0; 85 86 switch (opcode & MASK_ROUNDING_PRECISION) { 87 case ROUND_SINGLE: 88 { 89 fpa11->fType[getFn(opcode)] = typeSingle; 90 + fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(&roundData, readRegister(getRd(opcode))); 91 } 92 break; 93 ··· 108 return 0; 109 } 110 111 + if (roundData.exception) 112 + float_raise(roundData.exception); 113 + 114 return 1; 115 } 116 ··· 115 { 116 FPA11 *fpa11 = GET_FPA11(); 117 unsigned int Fn = getFm(opcode); 118 + struct roundingData roundData; 119 120 + roundData.mode = SetRoundingMode(opcode); 121 + roundData.precision = SetRoundingPrecision(opcode); 122 + roundData.exception = 0; 123 124 switch (fpa11->fType[Fn]) { 125 case typeSingle: 126 { 127 + writeRegister(getRd(opcode), float32_to_int32(&roundData, fpa11->fpreg[Fn].fSingle)); 128 } 129 break; 130 131 case typeDouble: 132 { 133 + writeRegister(getRd(opcode), float64_to_int32(&roundData, fpa11->fpreg[Fn].fDouble)); 134 } 135 break; 136 137 #ifdef CONFIG_FPE_NWFPE_XP 138 case typeExtended: 139 { 140 + writeRegister(getRd(opcode), floatx80_to_int32(&roundData, fpa11->fpreg[Fn].fExtended)); 141 } 142 break; 143 #endif ··· 142 default: 143 return 0; 144 } 145 + 146 + if (roundData.exception) 147 + float_raise(roundData.exception); 148 149 return 1; 150 }
+6 -9
arch/arm/nwfpe/fpmodule.c
··· 116 code to access data in user space in some other source files at the 117 moment (grep for get_user / put_user calls). --philb] 118 119 - float_exception_flags is a global variable in SoftFloat. 120 - 121 This function is called by the SoftFloat routines to raise a floating 122 point exception. We check the trap enable byte in the FPSR, and raise 123 a SIGFPE exception if necessary. If not the relevant bits in the ··· 127 register unsigned int fpsr, cumulativeTraps; 128 129 #ifdef CONFIG_DEBUG_USER 130 - printk(KERN_DEBUG 131 - "NWFPE: %s[%d] takes exception %08x at %p from %08lx\n", 132 - current->comm, current->pid, flags, 133 - __builtin_return_address(0), GET_USERREG()->ARM_pc); 134 #endif 135 - 136 - /* Keep SoftFloat exception flags up to date. */ 137 - float_exception_flags |= flags; 138 139 /* Read fpsr and initialize the cumulativeTraps. */ 140 fpsr = readFPSR();
··· 116 code to access data in user space in some other source files at the 117 moment (grep for get_user / put_user calls). --philb] 118 119 This function is called by the SoftFloat routines to raise a floating 120 point exception. We check the trap enable byte in the FPSR, and raise 121 a SIGFPE exception if necessary. If not the relevant bits in the ··· 129 register unsigned int fpsr, cumulativeTraps; 130 131 #ifdef CONFIG_DEBUG_USER 132 + /* Ignore inexact errors as there are far too many of them to log */ 133 + if (flags & ~BIT_IXC) 134 + printk(KERN_DEBUG 135 + "NWFPE: %s[%d] takes exception %08x at %p from %08lx\n", 136 + current->comm, current->pid, flags, 137 + __builtin_return_address(0), GET_USERREG()->ARM_pc); 138 #endif 139 140 /* Read fpsr and initialize the cumulativeTraps. */ 141 fpsr = readFPSR();
+12 -12
arch/arm/nwfpe/single_cpdo.c
··· 36 float32 float32_pow(float32 rFn, float32 rFm); 37 float32 float32_pol(float32 rFn, float32 rFm); 38 39 - static float32 float32_rsf(float32 rFn, float32 rFm) 40 { 41 - return float32_sub(rFm, rFn); 42 } 43 44 - static float32 float32_rdv(float32 rFn, float32 rFm) 45 { 46 - return float32_div(rFm, rFn); 47 } 48 49 - static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = { 50 [ADF_CODE >> 20] = float32_add, 51 [MUF_CODE >> 20] = float32_mul, 52 [SUF_CODE >> 20] = float32_sub, ··· 60 [FRD_CODE >> 20] = float32_rdv, 61 }; 62 63 - static float32 float32_mvf(float32 rFm) 64 { 65 return rFm; 66 } 67 68 - static float32 float32_mnf(float32 rFm) 69 { 70 return rFm ^ 0x80000000; 71 } 72 73 - static float32 float32_abs(float32 rFm) 74 { 75 return rFm & 0x7fffffff; 76 } 77 78 - static float32 (*const monadic_single[16])(float32 rFm) = { 79 [MVF_CODE >> 20] = float32_mvf, 80 [MNF_CODE >> 20] = float32_mnf, 81 [ABS_CODE >> 20] = float32_abs, ··· 85 [NRM_CODE >> 20] = float32_mvf, 86 }; 87 88 - unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd) 89 { 90 FPA11 *fpa11 = GET_FPA11(); 91 float32 rFm; ··· 108 if (fpa11->fType[Fn] == typeSingle && 109 dyadic_single[opc_mask_shift]) { 110 rFn = fpa11->fpreg[Fn].fSingle; 111 - rFd->fSingle = dyadic_single[opc_mask_shift](rFn, rFm); 112 } else { 113 return 0; 114 } 115 } else { 116 if (monadic_single[opc_mask_shift]) { 117 - rFd->fSingle = monadic_single[opc_mask_shift](rFm); 118 } else { 119 return 0; 120 }
··· 36 float32 float32_pow(float32 rFn, float32 rFm); 37 float32 float32_pol(float32 rFn, float32 rFm); 38 39 + static float32 float32_rsf(struct roundingData *roundData, float32 rFn, float32 rFm) 40 { 41 + return float32_sub(roundData, rFm, rFn); 42 } 43 44 + static float32 float32_rdv(struct roundingData *roundData, float32 rFn, float32 rFm) 45 { 46 + return float32_div(roundData, rFm, rFn); 47 } 48 49 + static float32 (*const dyadic_single[16])(struct roundingData *, float32 rFn, float32 rFm) = { 50 [ADF_CODE >> 20] = float32_add, 51 [MUF_CODE >> 20] = float32_mul, 52 [SUF_CODE >> 20] = float32_sub, ··· 60 [FRD_CODE >> 20] = float32_rdv, 61 }; 62 63 + static float32 float32_mvf(struct roundingData *roundData, float32 rFm) 64 { 65 return rFm; 66 } 67 68 + static float32 float32_mnf(struct roundingData *roundData, float32 rFm) 69 { 70 return rFm ^ 0x80000000; 71 } 72 73 + static float32 float32_abs(struct roundingData *roundData, float32 rFm) 74 { 75 return rFm & 0x7fffffff; 76 } 77 78 + static float32 (*const monadic_single[16])(struct roundingData*, float32 rFm) = { 79 [MVF_CODE >> 20] = float32_mvf, 80 [MNF_CODE >> 20] = float32_mnf, 81 [ABS_CODE >> 20] = float32_abs, ··· 85 [NRM_CODE >> 20] = float32_mvf, 86 }; 87 88 + unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd) 89 { 90 FPA11 *fpa11 = GET_FPA11(); 91 float32 rFm; ··· 108 if (fpa11->fType[Fn] == typeSingle && 109 dyadic_single[opc_mask_shift]) { 110 rFn = fpa11->fpreg[Fn].fSingle; 111 + rFd->fSingle = dyadic_single[opc_mask_shift](roundData, rFn, rFm); 112 } else { 113 return 0; 114 } 115 } else { 116 if (monadic_single[opc_mask_shift]) { 117 + rFd->fSingle = monadic_single[opc_mask_shift](roundData, rFm); 118 } else { 119 return 0; 120 }
+163 -171
arch/arm/nwfpe/softfloat.c
··· 36 37 /* 38 ------------------------------------------------------------------------------- 39 - Floating-point rounding mode, extended double-precision rounding precision, 40 - and exception flags. 41 - ------------------------------------------------------------------------------- 42 - */ 43 - int8 float_rounding_mode = float_round_nearest_even; 44 - int8 floatx80_rounding_precision = 80; 45 - int8 float_exception_flags; 46 - 47 - /* 48 - ------------------------------------------------------------------------------- 49 Primitive arithmetic functions, including multi-word arithmetic, and 50 division and square root approximations. (Can be specialized to target if 51 desired.) ··· 67 positive or negative integer is returned. 68 ------------------------------------------------------------------------------- 69 */ 70 - static int32 roundAndPackInt32( flag zSign, bits64 absZ ) 71 { 72 int8 roundingMode; 73 flag roundNearestEven; 74 int8 roundIncrement, roundBits; 75 int32 z; 76 77 - roundingMode = float_rounding_mode; 78 roundNearestEven = ( roundingMode == float_round_nearest_even ); 79 roundIncrement = 0x40; 80 if ( ! roundNearestEven ) { ··· 97 z = absZ; 98 if ( zSign ) z = - z; 99 if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { 100 - float_exception_flags |= float_flag_invalid; 101 return zSign ? 0x80000000 : 0x7FFFFFFF; 102 } 103 - if ( roundBits ) float_exception_flags |= float_flag_inexact; 104 return z; 105 106 } ··· 214 Binary Floating-point Arithmetic. 215 ------------------------------------------------------------------------------- 216 */ 217 - static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) 218 { 219 int8 roundingMode; 220 flag roundNearestEven; 221 int8 roundIncrement, roundBits; 222 flag isTiny; 223 224 - roundingMode = float_rounding_mode; 225 roundNearestEven = ( roundingMode == float_round_nearest_even ); 226 roundIncrement = 0x40; 227 if ( ! roundNearestEven ) { ··· 244 || ( ( zExp == 0xFD ) 245 && ( (sbits32) ( zSig + roundIncrement ) < 0 ) ) 246 ) { 247 - float_raise( float_flag_overflow | float_flag_inexact ); 248 return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 ); 249 } 250 if ( zExp < 0 ) { ··· 255 shift32RightJamming( zSig, - zExp, &zSig ); 256 zExp = 0; 257 roundBits = zSig & 0x7F; 258 - if ( isTiny && roundBits ) float_raise( float_flag_underflow ); 259 } 260 } 261 - if ( roundBits ) float_exception_flags |= float_flag_inexact; 262 zSig = ( zSig + roundIncrement )>>7; 263 zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); 264 if ( zSig == 0 ) zExp = 0; ··· 277 ------------------------------------------------------------------------------- 278 */ 279 static float32 280 - normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) 281 { 282 int8 shiftCount; 283 284 shiftCount = countLeadingZeros32( zSig ) - 1; 285 - return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<<shiftCount ); 286 287 } 288 ··· 385 Binary Floating-point Arithmetic. 386 ------------------------------------------------------------------------------- 387 */ 388 - static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) 389 { 390 int8 roundingMode; 391 flag roundNearestEven; 392 int16 roundIncrement, roundBits; 393 flag isTiny; 394 395 - roundingMode = float_rounding_mode; 396 roundNearestEven = ( roundingMode == float_round_nearest_even ); 397 roundIncrement = 0x200; 398 if ( ! roundNearestEven ) { ··· 417 ) { 418 //register int lr = __builtin_return_address(0); 419 //printk("roundAndPackFloat64 called from 0x%08x\n",lr); 420 - float_raise( float_flag_overflow | float_flag_inexact ); 421 return packFloat64( zSign, 0x7FF, 0 ) - ( roundIncrement == 0 ); 422 } 423 if ( zExp < 0 ) { ··· 428 shift64RightJamming( zSig, - zExp, &zSig ); 429 zExp = 0; 430 roundBits = zSig & 0x3FF; 431 - if ( isTiny && roundBits ) float_raise( float_flag_underflow ); 432 } 433 } 434 - if ( roundBits ) float_exception_flags |= float_flag_inexact; 435 zSig = ( zSig + roundIncrement )>>10; 436 zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven ); 437 if ( zSig == 0 ) zExp = 0; ··· 450 ------------------------------------------------------------------------------- 451 */ 452 static float64 453 - normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) 454 { 455 int8 shiftCount; 456 457 shiftCount = countLeadingZeros64( zSig ) - 1; 458 - return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<<shiftCount ); 459 460 } 461 ··· 562 */ 563 static floatx80 564 roundAndPackFloatx80( 565 - int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 566 ) 567 { 568 - int8 roundingMode; 569 flag roundNearestEven, increment, isTiny; 570 int64 roundIncrement, roundMask, roundBits; 571 572 - roundingMode = float_rounding_mode; 573 roundNearestEven = ( roundingMode == float_round_nearest_even ); 574 if ( roundingPrecision == 80 ) goto precision80; 575 if ( roundingPrecision == 64 ) { ··· 614 shift64RightJamming( zSig0, 1 - zExp, &zSig0 ); 615 zExp = 0; 616 roundBits = zSig0 & roundMask; 617 - if ( isTiny && roundBits ) float_raise( float_flag_underflow ); 618 - if ( roundBits ) float_exception_flags |= float_flag_inexact; 619 zSig0 += roundIncrement; 620 if ( (sbits64) zSig0 < 0 ) zExp = 1; 621 roundIncrement = roundMask + 1; ··· 626 return packFloatx80( zSign, zExp, zSig0 ); 627 } 628 } 629 - if ( roundBits ) float_exception_flags |= float_flag_inexact; 630 zSig0 += roundIncrement; 631 if ( zSig0 < roundIncrement ) { 632 ++zExp; ··· 663 ) { 664 roundMask = 0; 665 overflow: 666 - float_raise( float_flag_overflow | float_flag_inexact ); 667 if ( ( roundingMode == float_round_to_zero ) 668 || ( zSign && ( roundingMode == float_round_up ) ) 669 || ( ! zSign && ( roundingMode == float_round_down ) ) ··· 680 || ( zSig0 < LIT64( 0xFFFFFFFFFFFFFFFF ) ); 681 shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 ); 682 zExp = 0; 683 - if ( isTiny && zSig1 ) float_raise( float_flag_underflow ); 684 - if ( zSig1 ) float_exception_flags |= float_flag_inexact; 685 if ( roundNearestEven ) { 686 increment = ( (sbits64) zSig1 < 0 ); 687 } ··· 701 return packFloatx80( zSign, zExp, zSig0 ); 702 } 703 } 704 - if ( zSig1 ) float_exception_flags |= float_flag_inexact; 705 if ( increment ) { 706 ++zSig0; 707 if ( zSig0 == 0 ) { ··· 731 */ 732 static floatx80 733 normalizeRoundAndPackFloatx80( 734 - int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 735 ) 736 { 737 int8 shiftCount; ··· 745 shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 ); 746 zExp -= shiftCount; 747 return 748 - roundAndPackFloatx80( roundingPrecision, zSign, zExp, zSig0, zSig1 ); 749 750 } 751 ··· 758 according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 759 ------------------------------------------------------------------------------- 760 */ 761 - float32 int32_to_float32( int32 a ) 762 { 763 flag zSign; 764 765 if ( a == 0 ) return 0; 766 if ( a == 0x80000000 ) return packFloat32( 1, 0x9E, 0 ); 767 zSign = ( a < 0 ); 768 - return normalizeRoundAndPackFloat32( zSign, 0x9C, zSign ? - a : a ); 769 770 } 771 ··· 831 largest integer with the same sign as `a' is returned. 832 ------------------------------------------------------------------------------- 833 */ 834 - int32 float32_to_int32( float32 a ) 835 { 836 flag aSign; 837 int16 aExp, shiftCount; ··· 847 zSig = aSig; 848 zSig <<= 32; 849 if ( 0 < shiftCount ) shift64RightJamming( zSig, shiftCount, &zSig ); 850 - return roundAndPackInt32( aSign, zSig ); 851 852 } 853 ··· 880 return 0x80000000; 881 } 882 else if ( aExp <= 0x7E ) { 883 - if ( aExp | aSig ) float_exception_flags |= float_flag_inexact; 884 return 0; 885 } 886 aSig = ( aSig | 0x00800000 )<<8; 887 z = aSig>>( - shiftCount ); 888 if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) { 889 - float_exception_flags |= float_flag_inexact; 890 } 891 return aSign ? - z : z; 892 ··· 964 Floating-point Arithmetic. 965 ------------------------------------------------------------------------------- 966 */ 967 - float32 float32_round_to_int( float32 a ) 968 { 969 flag aSign; 970 int16 aExp; ··· 979 } 980 return a; 981 } 982 if ( aExp <= 0x7E ) { 983 if ( (bits32) ( a<<1 ) == 0 ) return a; 984 - float_exception_flags |= float_flag_inexact; 985 aSign = extractFloat32Sign( a ); 986 - switch ( float_rounding_mode ) { 987 case float_round_nearest_even: 988 if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) { 989 return packFloat32( aSign, 0x7F, 0 ); ··· 1001 lastBitMask <<= 0x96 - aExp; 1002 roundBitsMask = lastBitMask - 1; 1003 z = a; 1004 - roundingMode = float_rounding_mode; 1005 if ( roundingMode == float_round_nearest_even ) { 1006 z += lastBitMask>>1; 1007 if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; ··· 1011 } 1012 } 1013 z &= ~ roundBitsMask; 1014 - if ( z != a ) float_exception_flags |= float_flag_inexact; 1015 return z; 1016 1017 } ··· 1025 Floating-point Arithmetic. 1026 ------------------------------------------------------------------------------- 1027 */ 1028 - static float32 addFloat32Sigs( float32 a, float32 b, flag zSign ) 1029 { 1030 int16 aExp, bExp, zExp; 1031 bits32 aSig, bSig, zSig; ··· 1084 ++zExp; 1085 } 1086 roundAndPack: 1087 - return roundAndPackFloat32( zSign, zExp, zSig ); 1088 1089 } 1090 ··· 1097 Standard for Binary Floating-point Arithmetic. 1098 ------------------------------------------------------------------------------- 1099 */ 1100 - static float32 subFloat32Sigs( float32 a, float32 b, flag zSign ) 1101 { 1102 int16 aExp, bExp, zExp; 1103 bits32 aSig, bSig, zSig; ··· 1114 if ( expDiff < 0 ) goto bExpBigger; 1115 if ( aExp == 0xFF ) { 1116 if ( aSig | bSig ) return propagateFloat32NaN( a, b ); 1117 - float_raise( float_flag_invalid ); 1118 return float32_default_nan; 1119 } 1120 if ( aExp == 0 ) { ··· 1123 } 1124 if ( bSig < aSig ) goto aBigger; 1125 if ( aSig < bSig ) goto bBigger; 1126 - return packFloat32( float_rounding_mode == float_round_down, 0, 0 ); 1127 bExpBigger: 1128 if ( bExp == 0xFF ) { 1129 if ( bSig ) return propagateFloat32NaN( a, b ); ··· 1160 zExp = aExp; 1161 normalizeRoundAndPack: 1162 --zExp; 1163 - return normalizeRoundAndPackFloat32( zSign, zExp, zSig ); 1164 1165 } 1166 ··· 1171 Binary Floating-point Arithmetic. 1172 ------------------------------------------------------------------------------- 1173 */ 1174 - float32 float32_add( float32 a, float32 b ) 1175 { 1176 flag aSign, bSign; 1177 1178 aSign = extractFloat32Sign( a ); 1179 bSign = extractFloat32Sign( b ); 1180 if ( aSign == bSign ) { 1181 - return addFloat32Sigs( a, b, aSign ); 1182 } 1183 else { 1184 - return subFloat32Sigs( a, b, aSign ); 1185 } 1186 1187 } ··· 1193 for Binary Floating-point Arithmetic. 1194 ------------------------------------------------------------------------------- 1195 */ 1196 - float32 float32_sub( float32 a, float32 b ) 1197 { 1198 flag aSign, bSign; 1199 1200 aSign = extractFloat32Sign( a ); 1201 bSign = extractFloat32Sign( b ); 1202 if ( aSign == bSign ) { 1203 - return subFloat32Sigs( a, b, aSign ); 1204 } 1205 else { 1206 - return addFloat32Sigs( a, b, aSign ); 1207 } 1208 1209 } ··· 1215 for Binary Floating-point Arithmetic. 1216 ------------------------------------------------------------------------------- 1217 */ 1218 - float32 float32_mul( float32 a, float32 b ) 1219 { 1220 flag aSign, bSign, zSign; 1221 int16 aExp, bExp, zExp; ··· 1235 return propagateFloat32NaN( a, b ); 1236 } 1237 if ( ( bExp | bSig ) == 0 ) { 1238 - float_raise( float_flag_invalid ); 1239 return float32_default_nan; 1240 } 1241 return packFloat32( zSign, 0xFF, 0 ); ··· 1243 if ( bExp == 0xFF ) { 1244 if ( bSig ) return propagateFloat32NaN( a, b ); 1245 if ( ( aExp | aSig ) == 0 ) { 1246 - float_raise( float_flag_invalid ); 1247 return float32_default_nan; 1248 } 1249 return packFloat32( zSign, 0xFF, 0 ); ··· 1265 zSig <<= 1; 1266 --zExp; 1267 } 1268 - return roundAndPackFloat32( zSign, zExp, zSig ); 1269 1270 } 1271 ··· 1276 IEC/IEEE Standard for Binary Floating-point Arithmetic. 1277 ------------------------------------------------------------------------------- 1278 */ 1279 - float32 float32_div( float32 a, float32 b ) 1280 { 1281 flag aSign, bSign, zSign; 1282 int16 aExp, bExp, zExp; ··· 1293 if ( aSig ) return propagateFloat32NaN( a, b ); 1294 if ( bExp == 0xFF ) { 1295 if ( bSig ) return propagateFloat32NaN( a, b ); 1296 - float_raise( float_flag_invalid ); 1297 return float32_default_nan; 1298 } 1299 return packFloat32( zSign, 0xFF, 0 ); ··· 1305 if ( bExp == 0 ) { 1306 if ( bSig == 0 ) { 1307 if ( ( aExp | aSig ) == 0 ) { 1308 - float_raise( float_flag_invalid ); 1309 return float32_default_nan; 1310 } 1311 - float_raise( float_flag_divbyzero ); 1312 return packFloat32( zSign, 0xFF, 0 ); 1313 } 1314 normalizeFloat32Subnormal( bSig, &bExp, &bSig ); ··· 1332 if ( ( zSig & 0x3F ) == 0 ) { 1333 zSig |= ( ( (bits64) bSig ) * zSig != ( (bits64) aSig )<<32 ); 1334 } 1335 - return roundAndPackFloat32( zSign, zExp, zSig ); 1336 1337 } 1338 ··· 1343 according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 1344 ------------------------------------------------------------------------------- 1345 */ 1346 - float32 float32_rem( float32 a, float32 b ) 1347 { 1348 flag aSign, bSign, zSign; 1349 int16 aExp, bExp, expDiff; ··· 1363 if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { 1364 return propagateFloat32NaN( a, b ); 1365 } 1366 - float_raise( float_flag_invalid ); 1367 return float32_default_nan; 1368 } 1369 if ( bExp == 0xFF ) { ··· 1372 } 1373 if ( bExp == 0 ) { 1374 if ( bSig == 0 ) { 1375 - float_raise( float_flag_invalid ); 1376 return float32_default_nan; 1377 } 1378 normalizeFloat32Subnormal( bSig, &bExp, &bSig ); ··· 1435 } 1436 zSign = ( (sbits32) aSig < 0 ); 1437 if ( zSign ) aSig = - aSig; 1438 - return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig ); 1439 1440 } 1441 ··· 1446 Floating-point Arithmetic. 1447 ------------------------------------------------------------------------------- 1448 */ 1449 - float32 float32_sqrt( float32 a ) 1450 { 1451 flag aSign; 1452 int16 aExp, zExp; ··· 1459 if ( aExp == 0xFF ) { 1460 if ( aSig ) return propagateFloat32NaN( a, 0 ); 1461 if ( ! aSign ) return a; 1462 - float_raise( float_flag_invalid ); 1463 return float32_default_nan; 1464 } 1465 if ( aSign ) { 1466 if ( ( aExp | aSig ) == 0 ) return a; 1467 - float_raise( float_flag_invalid ); 1468 return float32_default_nan; 1469 } 1470 if ( aExp == 0 ) { ··· 1490 } 1491 } 1492 shift32RightJamming( zSig, 1, &zSig ); 1493 - return roundAndPackFloat32( 0, zExp, zSig ); 1494 1495 } 1496 ··· 1652 largest integer with the same sign as `a' is returned. 1653 ------------------------------------------------------------------------------- 1654 */ 1655 - int32 float64_to_int32( float64 a ) 1656 { 1657 flag aSign; 1658 int16 aExp, shiftCount; ··· 1665 if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); 1666 shiftCount = 0x42C - aExp; 1667 if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); 1668 - return roundAndPackInt32( aSign, aSig ); 1669 1670 } 1671 ··· 1696 goto invalid; 1697 } 1698 else if ( 52 < shiftCount ) { 1699 - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; 1700 return 0; 1701 } 1702 aSig |= LIT64( 0x0010000000000000 ); ··· 1706 if ( aSign ) z = - z; 1707 if ( ( z < 0 ) ^ aSign ) { 1708 invalid: 1709 - float_exception_flags |= float_flag_invalid; 1710 return aSign ? 0x80000000 : 0x7FFFFFFF; 1711 } 1712 if ( ( aSig<<shiftCount ) != savedASig ) { 1713 - float_exception_flags |= float_flag_inexact; 1714 } 1715 return z; 1716 ··· 1727 largest positive integer is returned. 1728 ------------------------------------------------------------------------------- 1729 */ 1730 - int32 float64_to_uint32( float64 a ) 1731 { 1732 flag aSign; 1733 int16 aExp, shiftCount; ··· 1740 if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); 1741 shiftCount = 0x42C - aExp; 1742 if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); 1743 - return roundAndPackInt32( aSign, aSig ); 1744 } 1745 1746 /* ··· 1769 goto invalid; 1770 } 1771 else if ( 52 < shiftCount ) { 1772 - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; 1773 return 0; 1774 } 1775 aSig |= LIT64( 0x0010000000000000 ); ··· 1779 if ( aSign ) z = - z; 1780 if ( ( z < 0 ) ^ aSign ) { 1781 invalid: 1782 - float_exception_flags |= float_flag_invalid; 1783 return aSign ? 0x80000000 : 0x7FFFFFFF; 1784 } 1785 if ( ( aSig<<shiftCount ) != savedASig ) { 1786 - float_exception_flags |= float_flag_inexact; 1787 } 1788 return z; 1789 } ··· 1796 Arithmetic. 1797 ------------------------------------------------------------------------------- 1798 */ 1799 - float32 float64_to_float32( float64 a ) 1800 { 1801 flag aSign; 1802 int16 aExp; ··· 1816 zSig |= 0x40000000; 1817 aExp -= 0x381; 1818 } 1819 - return roundAndPackFloat32( aSign, aExp, zSig ); 1820 1821 } 1822 ··· 1863 Floating-point Arithmetic. 1864 ------------------------------------------------------------------------------- 1865 */ 1866 - float64 float64_round_to_int( float64 a ) 1867 { 1868 flag aSign; 1869 int16 aExp; ··· 1880 } 1881 if ( aExp <= 0x3FE ) { 1882 if ( (bits64) ( a<<1 ) == 0 ) return a; 1883 - float_exception_flags |= float_flag_inexact; 1884 aSign = extractFloat64Sign( a ); 1885 - switch ( float_rounding_mode ) { 1886 case float_round_nearest_even: 1887 if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) { 1888 return packFloat64( aSign, 0x3FF, 0 ); ··· 1900 lastBitMask <<= 0x433 - aExp; 1901 roundBitsMask = lastBitMask - 1; 1902 z = a; 1903 - roundingMode = float_rounding_mode; 1904 if ( roundingMode == float_round_nearest_even ) { 1905 z += lastBitMask>>1; 1906 if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; ··· 1911 } 1912 } 1913 z &= ~ roundBitsMask; 1914 - if ( z != a ) float_exception_flags |= float_flag_inexact; 1915 return z; 1916 1917 } ··· 1925 Floating-point Arithmetic. 1926 ------------------------------------------------------------------------------- 1927 */ 1928 - static float64 addFloat64Sigs( float64 a, float64 b, flag zSign ) 1929 { 1930 int16 aExp, bExp, zExp; 1931 bits64 aSig, bSig, zSig; ··· 1984 ++zExp; 1985 } 1986 roundAndPack: 1987 - return roundAndPackFloat64( zSign, zExp, zSig ); 1988 1989 } 1990 ··· 1997 Standard for Binary Floating-point Arithmetic. 1998 ------------------------------------------------------------------------------- 1999 */ 2000 - static float64 subFloat64Sigs( float64 a, float64 b, flag zSign ) 2001 { 2002 int16 aExp, bExp, zExp; 2003 bits64 aSig, bSig, zSig; ··· 2014 if ( expDiff < 0 ) goto bExpBigger; 2015 if ( aExp == 0x7FF ) { 2016 if ( aSig | bSig ) return propagateFloat64NaN( a, b ); 2017 - float_raise( float_flag_invalid ); 2018 return float64_default_nan; 2019 } 2020 if ( aExp == 0 ) { ··· 2023 } 2024 if ( bSig < aSig ) goto aBigger; 2025 if ( aSig < bSig ) goto bBigger; 2026 - return packFloat64( float_rounding_mode == float_round_down, 0, 0 ); 2027 bExpBigger: 2028 if ( bExp == 0x7FF ) { 2029 if ( bSig ) return propagateFloat64NaN( a, b ); ··· 2060 zExp = aExp; 2061 normalizeRoundAndPack: 2062 --zExp; 2063 - return normalizeRoundAndPackFloat64( zSign, zExp, zSig ); 2064 2065 } 2066 ··· 2071 Binary Floating-point Arithmetic. 2072 ------------------------------------------------------------------------------- 2073 */ 2074 - float64 float64_add( float64 a, float64 b ) 2075 { 2076 flag aSign, bSign; 2077 2078 aSign = extractFloat64Sign( a ); 2079 bSign = extractFloat64Sign( b ); 2080 if ( aSign == bSign ) { 2081 - return addFloat64Sigs( a, b, aSign ); 2082 } 2083 else { 2084 - return subFloat64Sigs( a, b, aSign ); 2085 } 2086 2087 } ··· 2093 for Binary Floating-point Arithmetic. 2094 ------------------------------------------------------------------------------- 2095 */ 2096 - float64 float64_sub( float64 a, float64 b ) 2097 { 2098 flag aSign, bSign; 2099 2100 aSign = extractFloat64Sign( a ); 2101 bSign = extractFloat64Sign( b ); 2102 if ( aSign == bSign ) { 2103 - return subFloat64Sigs( a, b, aSign ); 2104 } 2105 else { 2106 - return addFloat64Sigs( a, b, aSign ); 2107 } 2108 2109 } ··· 2115 for Binary Floating-point Arithmetic. 2116 ------------------------------------------------------------------------------- 2117 */ 2118 - float64 float64_mul( float64 a, float64 b ) 2119 { 2120 flag aSign, bSign, zSign; 2121 int16 aExp, bExp, zExp; ··· 2133 return propagateFloat64NaN( a, b ); 2134 } 2135 if ( ( bExp | bSig ) == 0 ) { 2136 - float_raise( float_flag_invalid ); 2137 return float64_default_nan; 2138 } 2139 return packFloat64( zSign, 0x7FF, 0 ); ··· 2141 if ( bExp == 0x7FF ) { 2142 if ( bSig ) return propagateFloat64NaN( a, b ); 2143 if ( ( aExp | aSig ) == 0 ) { 2144 - float_raise( float_flag_invalid ); 2145 return float64_default_nan; 2146 } 2147 return packFloat64( zSign, 0x7FF, 0 ); ··· 2163 zSig0 <<= 1; 2164 --zExp; 2165 } 2166 - return roundAndPackFloat64( zSign, zExp, zSig0 ); 2167 2168 } 2169 ··· 2174 the IEC/IEEE Standard for Binary Floating-point Arithmetic. 2175 ------------------------------------------------------------------------------- 2176 */ 2177 - float64 float64_div( float64 a, float64 b ) 2178 { 2179 flag aSign, bSign, zSign; 2180 int16 aExp, bExp, zExp; ··· 2193 if ( aSig ) return propagateFloat64NaN( a, b ); 2194 if ( bExp == 0x7FF ) { 2195 if ( bSig ) return propagateFloat64NaN( a, b ); 2196 - float_raise( float_flag_invalid ); 2197 return float64_default_nan; 2198 } 2199 return packFloat64( zSign, 0x7FF, 0 ); ··· 2205 if ( bExp == 0 ) { 2206 if ( bSig == 0 ) { 2207 if ( ( aExp | aSig ) == 0 ) { 2208 - float_raise( float_flag_invalid ); 2209 return float64_default_nan; 2210 } 2211 - float_raise( float_flag_divbyzero ); 2212 return packFloat64( zSign, 0x7FF, 0 ); 2213 } 2214 normalizeFloat64Subnormal( bSig, &bExp, &bSig ); ··· 2234 } 2235 zSig |= ( rem1 != 0 ); 2236 } 2237 - return roundAndPackFloat64( zSign, zExp, zSig ); 2238 2239 } 2240 ··· 2245 according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 2246 ------------------------------------------------------------------------------- 2247 */ 2248 - float64 float64_rem( float64 a, float64 b ) 2249 { 2250 flag aSign, bSign, zSign; 2251 int16 aExp, bExp, expDiff; ··· 2263 if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { 2264 return propagateFloat64NaN( a, b ); 2265 } 2266 - float_raise( float_flag_invalid ); 2267 return float64_default_nan; 2268 } 2269 if ( bExp == 0x7FF ) { ··· 2272 } 2273 if ( bExp == 0 ) { 2274 if ( bSig == 0 ) { 2275 - float_raise( float_flag_invalid ); 2276 return float64_default_nan; 2277 } 2278 normalizeFloat64Subnormal( bSig, &bExp, &bSig ); ··· 2320 } 2321 zSign = ( (sbits64) aSig < 0 ); 2322 if ( zSign ) aSig = - aSig; 2323 - return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig ); 2324 2325 } 2326 ··· 2331 Floating-point Arithmetic. 2332 ------------------------------------------------------------------------------- 2333 */ 2334 - float64 float64_sqrt( float64 a ) 2335 { 2336 flag aSign; 2337 int16 aExp, zExp; ··· 2345 if ( aExp == 0x7FF ) { 2346 if ( aSig ) return propagateFloat64NaN( a, a ); 2347 if ( ! aSign ) return a; 2348 - float_raise( float_flag_invalid ); 2349 return float64_default_nan; 2350 } 2351 if ( aSign ) { 2352 if ( ( aExp | aSig ) == 0 ) return a; 2353 - float_raise( float_flag_invalid ); 2354 return float64_default_nan; 2355 } 2356 if ( aExp == 0 ) { ··· 2381 } 2382 } 2383 shift64RightJamming( zSig, 1, &zSig ); 2384 - return roundAndPackFloat64( 0, zExp, zSig ); 2385 2386 } 2387 ··· 2545 overflows, the largest integer with the same sign as `a' is returned. 2546 ------------------------------------------------------------------------------- 2547 */ 2548 - int32 floatx80_to_int32( floatx80 a ) 2549 { 2550 flag aSign; 2551 int32 aExp, shiftCount; ··· 2558 shiftCount = 0x4037 - aExp; 2559 if ( shiftCount <= 0 ) shiftCount = 1; 2560 shift64RightJamming( aSig, shiftCount, &aSig ); 2561 - return roundAndPackInt32( aSign, aSig ); 2562 2563 } 2564 ··· 2589 goto invalid; 2590 } 2591 else if ( 63 < shiftCount ) { 2592 - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; 2593 return 0; 2594 } 2595 savedASig = aSig; ··· 2598 if ( aSign ) z = - z; 2599 if ( ( z < 0 ) ^ aSign ) { 2600 invalid: 2601 - float_exception_flags |= float_flag_invalid; 2602 return aSign ? 0x80000000 : 0x7FFFFFFF; 2603 } 2604 if ( ( aSig<<shiftCount ) != savedASig ) { 2605 - float_exception_flags |= float_flag_inexact; 2606 } 2607 return z; 2608 ··· 2616 Floating-point Arithmetic. 2617 ------------------------------------------------------------------------------- 2618 */ 2619 - float32 floatx80_to_float32( floatx80 a ) 2620 { 2621 flag aSign; 2622 int32 aExp; ··· 2633 } 2634 shift64RightJamming( aSig, 33, &aSig ); 2635 if ( aExp || aSig ) aExp -= 0x3F81; 2636 - return roundAndPackFloat32( aSign, aExp, aSig ); 2637 2638 } 2639 ··· 2645 Floating-point Arithmetic. 2646 ------------------------------------------------------------------------------- 2647 */ 2648 - float64 floatx80_to_float64( floatx80 a ) 2649 { 2650 flag aSign; 2651 int32 aExp; ··· 2662 } 2663 shift64RightJamming( aSig, 1, &zSig ); 2664 if ( aExp || aSig ) aExp -= 0x3C01; 2665 - return roundAndPackFloat64( aSign, aExp, zSig ); 2666 2667 } 2668 ··· 2674 Binary Floating-point Arithmetic. 2675 ------------------------------------------------------------------------------- 2676 */ 2677 - floatx80 floatx80_round_to_int( floatx80 a ) 2678 { 2679 flag aSign; 2680 int32 aExp; ··· 2694 && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) { 2695 return a; 2696 } 2697 - float_exception_flags |= float_flag_inexact; 2698 aSign = extractFloatx80Sign( a ); 2699 - switch ( float_rounding_mode ) { 2700 case float_round_nearest_even: 2701 if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 ) 2702 ) { ··· 2720 lastBitMask <<= 0x403E - aExp; 2721 roundBitsMask = lastBitMask - 1; 2722 z = a; 2723 - roundingMode = float_rounding_mode; 2724 if ( roundingMode == float_round_nearest_even ) { 2725 z.low += lastBitMask>>1; 2726 if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; ··· 2735 ++z.high; 2736 z.low = LIT64( 0x8000000000000000 ); 2737 } 2738 - if ( z.low != a.low ) float_exception_flags |= float_flag_inexact; 2739 return z; 2740 2741 } ··· 2749 Floating-point Arithmetic. 2750 ------------------------------------------------------------------------------- 2751 */ 2752 - static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) 2753 { 2754 int32 aExp, bExp, zExp; 2755 bits64 aSig, bSig, zSig0, zSig1; ··· 2805 roundAndPack: 2806 return 2807 roundAndPackFloatx80( 2808 - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); 2809 2810 } 2811 ··· 2818 Standard for Binary Floating-point Arithmetic. 2819 ------------------------------------------------------------------------------- 2820 */ 2821 - static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) 2822 { 2823 int32 aExp, bExp, zExp; 2824 bits64 aSig, bSig, zSig0, zSig1; ··· 2836 if ( (bits64) ( ( aSig | bSig )<<1 ) ) { 2837 return propagateFloatx80NaN( a, b ); 2838 } 2839 - float_raise( float_flag_invalid ); 2840 z.low = floatx80_default_nan_low; 2841 z.high = floatx80_default_nan_high; 2842 return z; ··· 2848 zSig1 = 0; 2849 if ( bSig < aSig ) goto aBigger; 2850 if ( aSig < bSig ) goto bBigger; 2851 - return packFloatx80( float_rounding_mode == float_round_down, 0, 0 ); 2852 bExpBigger: 2853 if ( bExp == 0x7FFF ) { 2854 if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); ··· 2874 normalizeRoundAndPack: 2875 return 2876 normalizeRoundAndPackFloatx80( 2877 - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); 2878 2879 } 2880 ··· 2885 Standard for Binary Floating-point Arithmetic. 2886 ------------------------------------------------------------------------------- 2887 */ 2888 - floatx80 floatx80_add( floatx80 a, floatx80 b ) 2889 { 2890 flag aSign, bSign; 2891 2892 aSign = extractFloatx80Sign( a ); 2893 bSign = extractFloatx80Sign( b ); 2894 if ( aSign == bSign ) { 2895 - return addFloatx80Sigs( a, b, aSign ); 2896 } 2897 else { 2898 - return subFloatx80Sigs( a, b, aSign ); 2899 } 2900 2901 } ··· 2907 IEC/IEEE Standard for Binary Floating-point Arithmetic. 2908 ------------------------------------------------------------------------------- 2909 */ 2910 - floatx80 floatx80_sub( floatx80 a, floatx80 b ) 2911 { 2912 flag aSign, bSign; 2913 2914 aSign = extractFloatx80Sign( a ); 2915 bSign = extractFloatx80Sign( b ); 2916 if ( aSign == bSign ) { 2917 - return subFloatx80Sigs( a, b, aSign ); 2918 } 2919 else { 2920 - return addFloatx80Sigs( a, b, aSign ); 2921 } 2922 2923 } ··· 2929 IEC/IEEE Standard for Binary Floating-point Arithmetic. 2930 ------------------------------------------------------------------------------- 2931 */ 2932 - floatx80 floatx80_mul( floatx80 a, floatx80 b ) 2933 { 2934 flag aSign, bSign, zSign; 2935 int32 aExp, bExp, zExp; ··· 2955 if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); 2956 if ( ( aExp | aSig ) == 0 ) { 2957 invalid: 2958 - float_raise( float_flag_invalid ); 2959 z.low = floatx80_default_nan_low; 2960 z.high = floatx80_default_nan_high; 2961 return z; ··· 2978 } 2979 return 2980 roundAndPackFloatx80( 2981 - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); 2982 2983 } 2984 ··· 2989 according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 2990 ------------------------------------------------------------------------------- 2991 */ 2992 - floatx80 floatx80_div( floatx80 a, floatx80 b ) 2993 { 2994 flag aSign, bSign, zSign; 2995 int32 aExp, bExp, zExp; ··· 3020 if ( bSig == 0 ) { 3021 if ( ( aExp | aSig ) == 0 ) { 3022 invalid: 3023 - float_raise( float_flag_invalid ); 3024 z.low = floatx80_default_nan_low; 3025 z.high = floatx80_default_nan_high; 3026 return z; 3027 } 3028 - float_raise( float_flag_divbyzero ); 3029 return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); 3030 } 3031 normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); ··· 3059 } 3060 return 3061 roundAndPackFloatx80( 3062 - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); 3063 3064 } 3065 ··· 3070 according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 3071 ------------------------------------------------------------------------------- 3072 */ 3073 - floatx80 floatx80_rem( floatx80 a, floatx80 b ) 3074 { 3075 flag aSign, bSign, zSign; 3076 int32 aExp, bExp, expDiff; ··· 3098 if ( bExp == 0 ) { 3099 if ( bSig == 0 ) { 3100 invalid: 3101 - float_raise( float_flag_invalid ); 3102 z.low = floatx80_default_nan_low; 3103 z.high = floatx80_default_nan_high; 3104 return z; ··· 3155 aSig1 = alternateASig1; 3156 zSign = ! zSign; 3157 } 3158 return 3159 normalizeRoundAndPackFloatx80( 3160 - 80, zSign, bExp + expDiff, aSig0, aSig1 ); 3161 3162 } 3163 ··· 3169 for Binary Floating-point Arithmetic. 3170 ------------------------------------------------------------------------------- 3171 */ 3172 - floatx80 floatx80_sqrt( floatx80 a ) 3173 { 3174 flag aSign; 3175 int32 aExp, zExp; ··· 3189 if ( aSign ) { 3190 if ( ( aExp | aSig0 ) == 0 ) return a; 3191 invalid: 3192 - float_raise( float_flag_invalid ); 3193 z.low = floatx80_default_nan_low; 3194 z.high = floatx80_default_nan_high; 3195 return z; ··· 3234 } 3235 return 3236 roundAndPackFloatx80( 3237 - floatx80_rounding_precision, 0, zExp, zSig0, zSig1 ); 3238 3239 } 3240 ··· 3256 ) { 3257 if ( floatx80_is_signaling_nan( a ) 3258 || floatx80_is_signaling_nan( b ) ) { 3259 - float_raise( float_flag_invalid ); 3260 } 3261 return 0; 3262 } ··· 3286 || ( ( extractFloatx80Exp( b ) == 0x7FFF ) 3287 && (bits64) ( extractFloatx80Frac( b )<<1 ) ) 3288 ) { 3289 - float_raise( float_flag_invalid ); 3290 return 0; 3291 } 3292 aSign = extractFloatx80Sign( a ); ··· 3320 || ( ( extractFloatx80Exp( b ) == 0x7FFF ) 3321 && (bits64) ( extractFloatx80Frac( b )<<1 ) ) 3322 ) { 3323 - float_raise( float_flag_invalid ); 3324 return 0; 3325 } 3326 aSign = extractFloatx80Sign( a ); ··· 3353 || ( ( extractFloatx80Exp( b ) == 0x7FFF ) 3354 && (bits64) ( extractFloatx80Frac( b )<<1 ) ) 3355 ) { 3356 - float_raise( float_flag_invalid ); 3357 return 0; 3358 } 3359 return ··· 3384 ) { 3385 if ( floatx80_is_signaling_nan( a ) 3386 || floatx80_is_signaling_nan( b ) ) { 3387 - float_raise( float_flag_invalid ); 3388 } 3389 return 0; 3390 } ··· 3421 ) { 3422 if ( floatx80_is_signaling_nan( a ) 3423 || floatx80_is_signaling_nan( b ) ) { 3424 - float_raise( float_flag_invalid ); 3425 } 3426 return 0; 3427 }
··· 36 37 /* 38 ------------------------------------------------------------------------------- 39 Primitive arithmetic functions, including multi-word arithmetic, and 40 division and square root approximations. (Can be specialized to target if 41 desired.) ··· 77 positive or negative integer is returned. 78 ------------------------------------------------------------------------------- 79 */ 80 + static int32 roundAndPackInt32( struct roundingData *roundData, flag zSign, bits64 absZ ) 81 { 82 int8 roundingMode; 83 flag roundNearestEven; 84 int8 roundIncrement, roundBits; 85 int32 z; 86 87 + roundingMode = roundData->mode; 88 roundNearestEven = ( roundingMode == float_round_nearest_even ); 89 roundIncrement = 0x40; 90 if ( ! roundNearestEven ) { ··· 107 z = absZ; 108 if ( zSign ) z = - z; 109 if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { 110 + roundData->exception |= float_flag_invalid; 111 return zSign ? 0x80000000 : 0x7FFFFFFF; 112 } 113 + if ( roundBits ) roundData->exception |= float_flag_inexact; 114 return z; 115 116 } ··· 224 Binary Floating-point Arithmetic. 225 ------------------------------------------------------------------------------- 226 */ 227 + static float32 roundAndPackFloat32( struct roundingData *roundData, flag zSign, int16 zExp, bits32 zSig ) 228 { 229 int8 roundingMode; 230 flag roundNearestEven; 231 int8 roundIncrement, roundBits; 232 flag isTiny; 233 234 + roundingMode = roundData->mode; 235 roundNearestEven = ( roundingMode == float_round_nearest_even ); 236 roundIncrement = 0x40; 237 if ( ! roundNearestEven ) { ··· 254 || ( ( zExp == 0xFD ) 255 && ( (sbits32) ( zSig + roundIncrement ) < 0 ) ) 256 ) { 257 + roundData->exception |= float_flag_overflow | float_flag_inexact; 258 return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 ); 259 } 260 if ( zExp < 0 ) { ··· 265 shift32RightJamming( zSig, - zExp, &zSig ); 266 zExp = 0; 267 roundBits = zSig & 0x7F; 268 + if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow; 269 } 270 } 271 + if ( roundBits ) roundData->exception |= float_flag_inexact; 272 zSig = ( zSig + roundIncrement )>>7; 273 zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); 274 if ( zSig == 0 ) zExp = 0; ··· 287 ------------------------------------------------------------------------------- 288 */ 289 static float32 290 + normalizeRoundAndPackFloat32( struct roundingData *roundData, flag zSign, int16 zExp, bits32 zSig ) 291 { 292 int8 shiftCount; 293 294 shiftCount = countLeadingZeros32( zSig ) - 1; 295 + return roundAndPackFloat32( roundData, zSign, zExp - shiftCount, zSig<<shiftCount ); 296 297 } 298 ··· 395 Binary Floating-point Arithmetic. 396 ------------------------------------------------------------------------------- 397 */ 398 + static float64 roundAndPackFloat64( struct roundingData *roundData, flag zSign, int16 zExp, bits64 zSig ) 399 { 400 int8 roundingMode; 401 flag roundNearestEven; 402 int16 roundIncrement, roundBits; 403 flag isTiny; 404 405 + roundingMode = roundData->mode; 406 roundNearestEven = ( roundingMode == float_round_nearest_even ); 407 roundIncrement = 0x200; 408 if ( ! roundNearestEven ) { ··· 427 ) { 428 //register int lr = __builtin_return_address(0); 429 //printk("roundAndPackFloat64 called from 0x%08x\n",lr); 430 + roundData->exception |= float_flag_overflow | float_flag_inexact; 431 return packFloat64( zSign, 0x7FF, 0 ) - ( roundIncrement == 0 ); 432 } 433 if ( zExp < 0 ) { ··· 438 shift64RightJamming( zSig, - zExp, &zSig ); 439 zExp = 0; 440 roundBits = zSig & 0x3FF; 441 + if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow; 442 } 443 } 444 + if ( roundBits ) roundData->exception |= float_flag_inexact; 445 zSig = ( zSig + roundIncrement )>>10; 446 zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven ); 447 if ( zSig == 0 ) zExp = 0; ··· 460 ------------------------------------------------------------------------------- 461 */ 462 static float64 463 + normalizeRoundAndPackFloat64( struct roundingData *roundData, flag zSign, int16 zExp, bits64 zSig ) 464 { 465 int8 shiftCount; 466 467 shiftCount = countLeadingZeros64( zSig ) - 1; 468 + return roundAndPackFloat64( roundData, zSign, zExp - shiftCount, zSig<<shiftCount ); 469 470 } 471 ··· 572 */ 573 static floatx80 574 roundAndPackFloatx80( 575 + struct roundingData *roundData, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 576 ) 577 { 578 + int8 roundingMode, roundingPrecision; 579 flag roundNearestEven, increment, isTiny; 580 int64 roundIncrement, roundMask, roundBits; 581 582 + roundingMode = roundData->mode; 583 + roundingPrecision = roundData->precision; 584 roundNearestEven = ( roundingMode == float_round_nearest_even ); 585 if ( roundingPrecision == 80 ) goto precision80; 586 if ( roundingPrecision == 64 ) { ··· 623 shift64RightJamming( zSig0, 1 - zExp, &zSig0 ); 624 zExp = 0; 625 roundBits = zSig0 & roundMask; 626 + if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow; 627 + if ( roundBits ) roundData->exception |= float_flag_inexact; 628 zSig0 += roundIncrement; 629 if ( (sbits64) zSig0 < 0 ) zExp = 1; 630 roundIncrement = roundMask + 1; ··· 635 return packFloatx80( zSign, zExp, zSig0 ); 636 } 637 } 638 + if ( roundBits ) roundData->exception |= float_flag_inexact; 639 zSig0 += roundIncrement; 640 if ( zSig0 < roundIncrement ) { 641 ++zExp; ··· 672 ) { 673 roundMask = 0; 674 overflow: 675 + roundData->exception |= float_flag_overflow | float_flag_inexact; 676 if ( ( roundingMode == float_round_to_zero ) 677 || ( zSign && ( roundingMode == float_round_up ) ) 678 || ( ! zSign && ( roundingMode == float_round_down ) ) ··· 689 || ( zSig0 < LIT64( 0xFFFFFFFFFFFFFFFF ) ); 690 shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 ); 691 zExp = 0; 692 + if ( isTiny && zSig1 ) roundData->exception |= float_flag_underflow; 693 + if ( zSig1 ) roundData->exception |= float_flag_inexact; 694 if ( roundNearestEven ) { 695 increment = ( (sbits64) zSig1 < 0 ); 696 } ··· 710 return packFloatx80( zSign, zExp, zSig0 ); 711 } 712 } 713 + if ( zSig1 ) roundData->exception |= float_flag_inexact; 714 if ( increment ) { 715 ++zSig0; 716 if ( zSig0 == 0 ) { ··· 740 */ 741 static floatx80 742 normalizeRoundAndPackFloatx80( 743 + struct roundingData *roundData, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 744 ) 745 { 746 int8 shiftCount; ··· 754 shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 ); 755 zExp -= shiftCount; 756 return 757 + roundAndPackFloatx80( roundData, zSign, zExp, zSig0, zSig1 ); 758 759 } 760 ··· 767 according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 768 ------------------------------------------------------------------------------- 769 */ 770 + float32 int32_to_float32(struct roundingData *roundData, int32 a) 771 { 772 flag zSign; 773 774 if ( a == 0 ) return 0; 775 if ( a == 0x80000000 ) return packFloat32( 1, 0x9E, 0 ); 776 zSign = ( a < 0 ); 777 + return normalizeRoundAndPackFloat32( roundData, zSign, 0x9C, zSign ? - a : a ); 778 779 } 780 ··· 840 largest integer with the same sign as `a' is returned. 841 ------------------------------------------------------------------------------- 842 */ 843 + int32 float32_to_int32( struct roundingData *roundData, float32 a ) 844 { 845 flag aSign; 846 int16 aExp, shiftCount; ··· 856 zSig = aSig; 857 zSig <<= 32; 858 if ( 0 < shiftCount ) shift64RightJamming( zSig, shiftCount, &zSig ); 859 + return roundAndPackInt32( roundData, aSign, zSig ); 860 861 } 862 ··· 889 return 0x80000000; 890 } 891 else if ( aExp <= 0x7E ) { 892 + if ( aExp | aSig ) float_raise( float_flag_inexact ); 893 return 0; 894 } 895 aSig = ( aSig | 0x00800000 )<<8; 896 z = aSig>>( - shiftCount ); 897 if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) { 898 + float_raise( float_flag_inexact ); 899 } 900 return aSign ? - z : z; 901 ··· 973 Floating-point Arithmetic. 974 ------------------------------------------------------------------------------- 975 */ 976 + float32 float32_round_to_int( struct roundingData *roundData, float32 a ) 977 { 978 flag aSign; 979 int16 aExp; ··· 988 } 989 return a; 990 } 991 + roundingMode = roundData->mode; 992 if ( aExp <= 0x7E ) { 993 if ( (bits32) ( a<<1 ) == 0 ) return a; 994 + roundData->exception |= float_flag_inexact; 995 aSign = extractFloat32Sign( a ); 996 + switch ( roundingMode ) { 997 case float_round_nearest_even: 998 if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) { 999 return packFloat32( aSign, 0x7F, 0 ); ··· 1009 lastBitMask <<= 0x96 - aExp; 1010 roundBitsMask = lastBitMask - 1; 1011 z = a; 1012 if ( roundingMode == float_round_nearest_even ) { 1013 z += lastBitMask>>1; 1014 if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; ··· 1020 } 1021 } 1022 z &= ~ roundBitsMask; 1023 + if ( z != a ) roundData->exception |= float_flag_inexact; 1024 return z; 1025 1026 } ··· 1034 Floating-point Arithmetic. 1035 ------------------------------------------------------------------------------- 1036 */ 1037 + static float32 addFloat32Sigs( struct roundingData *roundData, float32 a, float32 b, flag zSign ) 1038 { 1039 int16 aExp, bExp, zExp; 1040 bits32 aSig, bSig, zSig; ··· 1093 ++zExp; 1094 } 1095 roundAndPack: 1096 + return roundAndPackFloat32( roundData, zSign, zExp, zSig ); 1097 1098 } 1099 ··· 1106 Standard for Binary Floating-point Arithmetic. 1107 ------------------------------------------------------------------------------- 1108 */ 1109 + static float32 subFloat32Sigs( struct roundingData *roundData, float32 a, float32 b, flag zSign ) 1110 { 1111 int16 aExp, bExp, zExp; 1112 bits32 aSig, bSig, zSig; ··· 1123 if ( expDiff < 0 ) goto bExpBigger; 1124 if ( aExp == 0xFF ) { 1125 if ( aSig | bSig ) return propagateFloat32NaN( a, b ); 1126 + roundData->exception |= float_flag_invalid; 1127 return float32_default_nan; 1128 } 1129 if ( aExp == 0 ) { ··· 1132 } 1133 if ( bSig < aSig ) goto aBigger; 1134 if ( aSig < bSig ) goto bBigger; 1135 + return packFloat32( roundData->mode == float_round_down, 0, 0 ); 1136 bExpBigger: 1137 if ( bExp == 0xFF ) { 1138 if ( bSig ) return propagateFloat32NaN( a, b ); ··· 1169 zExp = aExp; 1170 normalizeRoundAndPack: 1171 --zExp; 1172 + return normalizeRoundAndPackFloat32( roundData, zSign, zExp, zSig ); 1173 1174 } 1175 ··· 1180 Binary Floating-point Arithmetic. 1181 ------------------------------------------------------------------------------- 1182 */ 1183 + float32 float32_add( struct roundingData *roundData, float32 a, float32 b ) 1184 { 1185 flag aSign, bSign; 1186 1187 aSign = extractFloat32Sign( a ); 1188 bSign = extractFloat32Sign( b ); 1189 if ( aSign == bSign ) { 1190 + return addFloat32Sigs( roundData, a, b, aSign ); 1191 } 1192 else { 1193 + return subFloat32Sigs( roundData, a, b, aSign ); 1194 } 1195 1196 } ··· 1202 for Binary Floating-point Arithmetic. 1203 ------------------------------------------------------------------------------- 1204 */ 1205 + float32 float32_sub( struct roundingData *roundData, float32 a, float32 b ) 1206 { 1207 flag aSign, bSign; 1208 1209 aSign = extractFloat32Sign( a ); 1210 bSign = extractFloat32Sign( b ); 1211 if ( aSign == bSign ) { 1212 + return subFloat32Sigs( roundData, a, b, aSign ); 1213 } 1214 else { 1215 + return addFloat32Sigs( roundData, a, b, aSign ); 1216 } 1217 1218 } ··· 1224 for Binary Floating-point Arithmetic. 1225 ------------------------------------------------------------------------------- 1226 */ 1227 + float32 float32_mul( struct roundingData *roundData, float32 a, float32 b ) 1228 { 1229 flag aSign, bSign, zSign; 1230 int16 aExp, bExp, zExp; ··· 1244 return propagateFloat32NaN( a, b ); 1245 } 1246 if ( ( bExp | bSig ) == 0 ) { 1247 + roundData->exception |= float_flag_invalid; 1248 return float32_default_nan; 1249 } 1250 return packFloat32( zSign, 0xFF, 0 ); ··· 1252 if ( bExp == 0xFF ) { 1253 if ( bSig ) return propagateFloat32NaN( a, b ); 1254 if ( ( aExp | aSig ) == 0 ) { 1255 + roundData->exception |= float_flag_invalid; 1256 return float32_default_nan; 1257 } 1258 return packFloat32( zSign, 0xFF, 0 ); ··· 1274 zSig <<= 1; 1275 --zExp; 1276 } 1277 + return roundAndPackFloat32( roundData, zSign, zExp, zSig ); 1278 1279 } 1280 ··· 1285 IEC/IEEE Standard for Binary Floating-point Arithmetic. 1286 ------------------------------------------------------------------------------- 1287 */ 1288 + float32 float32_div( struct roundingData *roundData, float32 a, float32 b ) 1289 { 1290 flag aSign, bSign, zSign; 1291 int16 aExp, bExp, zExp; ··· 1302 if ( aSig ) return propagateFloat32NaN( a, b ); 1303 if ( bExp == 0xFF ) { 1304 if ( bSig ) return propagateFloat32NaN( a, b ); 1305 + roundData->exception |= float_flag_invalid; 1306 return float32_default_nan; 1307 } 1308 return packFloat32( zSign, 0xFF, 0 ); ··· 1314 if ( bExp == 0 ) { 1315 if ( bSig == 0 ) { 1316 if ( ( aExp | aSig ) == 0 ) { 1317 + roundData->exception |= float_flag_invalid; 1318 return float32_default_nan; 1319 } 1320 + roundData->exception |= float_flag_divbyzero; 1321 return packFloat32( zSign, 0xFF, 0 ); 1322 } 1323 normalizeFloat32Subnormal( bSig, &bExp, &bSig ); ··· 1341 if ( ( zSig & 0x3F ) == 0 ) { 1342 zSig |= ( ( (bits64) bSig ) * zSig != ( (bits64) aSig )<<32 ); 1343 } 1344 + return roundAndPackFloat32( roundData, zSign, zExp, zSig ); 1345 1346 } 1347 ··· 1352 according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 1353 ------------------------------------------------------------------------------- 1354 */ 1355 + float32 float32_rem( struct roundingData *roundData, float32 a, float32 b ) 1356 { 1357 flag aSign, bSign, zSign; 1358 int16 aExp, bExp, expDiff; ··· 1372 if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { 1373 return propagateFloat32NaN( a, b ); 1374 } 1375 + roundData->exception |= float_flag_invalid; 1376 return float32_default_nan; 1377 } 1378 if ( bExp == 0xFF ) { ··· 1381 } 1382 if ( bExp == 0 ) { 1383 if ( bSig == 0 ) { 1384 + roundData->exception |= float_flag_invalid; 1385 return float32_default_nan; 1386 } 1387 normalizeFloat32Subnormal( bSig, &bExp, &bSig ); ··· 1444 } 1445 zSign = ( (sbits32) aSig < 0 ); 1446 if ( zSign ) aSig = - aSig; 1447 + return normalizeRoundAndPackFloat32( roundData, aSign ^ zSign, bExp, aSig ); 1448 1449 } 1450 ··· 1455 Floating-point Arithmetic. 1456 ------------------------------------------------------------------------------- 1457 */ 1458 + float32 float32_sqrt( struct roundingData *roundData, float32 a ) 1459 { 1460 flag aSign; 1461 int16 aExp, zExp; ··· 1468 if ( aExp == 0xFF ) { 1469 if ( aSig ) return propagateFloat32NaN( a, 0 ); 1470 if ( ! aSign ) return a; 1471 + roundData->exception |= float_flag_invalid; 1472 return float32_default_nan; 1473 } 1474 if ( aSign ) { 1475 if ( ( aExp | aSig ) == 0 ) return a; 1476 + roundData->exception |= float_flag_invalid; 1477 return float32_default_nan; 1478 } 1479 if ( aExp == 0 ) { ··· 1499 } 1500 } 1501 shift32RightJamming( zSig, 1, &zSig ); 1502 + return roundAndPackFloat32( roundData, 0, zExp, zSig ); 1503 1504 } 1505 ··· 1661 largest integer with the same sign as `a' is returned. 1662 ------------------------------------------------------------------------------- 1663 */ 1664 + int32 float64_to_int32( struct roundingData *roundData, float64 a ) 1665 { 1666 flag aSign; 1667 int16 aExp, shiftCount; ··· 1674 if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); 1675 shiftCount = 0x42C - aExp; 1676 if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); 1677 + return roundAndPackInt32( roundData, aSign, aSig ); 1678 1679 } 1680 ··· 1705 goto invalid; 1706 } 1707 else if ( 52 < shiftCount ) { 1708 + if ( aExp || aSig ) float_raise( float_flag_inexact ); 1709 return 0; 1710 } 1711 aSig |= LIT64( 0x0010000000000000 ); ··· 1715 if ( aSign ) z = - z; 1716 if ( ( z < 0 ) ^ aSign ) { 1717 invalid: 1718 + float_raise( float_flag_invalid ); 1719 return aSign ? 0x80000000 : 0x7FFFFFFF; 1720 } 1721 if ( ( aSig<<shiftCount ) != savedASig ) { 1722 + float_raise( float_flag_inexact ); 1723 } 1724 return z; 1725 ··· 1736 largest positive integer is returned. 1737 ------------------------------------------------------------------------------- 1738 */ 1739 + int32 float64_to_uint32( struct roundingData *roundData, float64 a ) 1740 { 1741 flag aSign; 1742 int16 aExp, shiftCount; ··· 1749 if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); 1750 shiftCount = 0x42C - aExp; 1751 if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); 1752 + return roundAndPackInt32( roundData, aSign, aSig ); 1753 } 1754 1755 /* ··· 1778 goto invalid; 1779 } 1780 else if ( 52 < shiftCount ) { 1781 + if ( aExp || aSig ) float_raise( float_flag_inexact ); 1782 return 0; 1783 } 1784 aSig |= LIT64( 0x0010000000000000 ); ··· 1788 if ( aSign ) z = - z; 1789 if ( ( z < 0 ) ^ aSign ) { 1790 invalid: 1791 + float_raise( float_flag_invalid ); 1792 return aSign ? 0x80000000 : 0x7FFFFFFF; 1793 } 1794 if ( ( aSig<<shiftCount ) != savedASig ) { 1795 + float_raise( float_flag_inexact ); 1796 } 1797 return z; 1798 } ··· 1805 Arithmetic. 1806 ------------------------------------------------------------------------------- 1807 */ 1808 + float32 float64_to_float32( struct roundingData *roundData, float64 a ) 1809 { 1810 flag aSign; 1811 int16 aExp; ··· 1825 zSig |= 0x40000000; 1826 aExp -= 0x381; 1827 } 1828 + return roundAndPackFloat32( roundData, aSign, aExp, zSig ); 1829 1830 } 1831 ··· 1872 Floating-point Arithmetic. 1873 ------------------------------------------------------------------------------- 1874 */ 1875 + float64 float64_round_to_int( struct roundingData *roundData, float64 a ) 1876 { 1877 flag aSign; 1878 int16 aExp; ··· 1889 } 1890 if ( aExp <= 0x3FE ) { 1891 if ( (bits64) ( a<<1 ) == 0 ) return a; 1892 + roundData->exception |= float_flag_inexact; 1893 aSign = extractFloat64Sign( a ); 1894 + switch ( roundData->mode ) { 1895 case float_round_nearest_even: 1896 if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) { 1897 return packFloat64( aSign, 0x3FF, 0 ); ··· 1909 lastBitMask <<= 0x433 - aExp; 1910 roundBitsMask = lastBitMask - 1; 1911 z = a; 1912 + roundingMode = roundData->mode; 1913 if ( roundingMode == float_round_nearest_even ) { 1914 z += lastBitMask>>1; 1915 if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; ··· 1920 } 1921 } 1922 z &= ~ roundBitsMask; 1923 + if ( z != a ) roundData->exception |= float_flag_inexact; 1924 return z; 1925 1926 } ··· 1934 Floating-point Arithmetic. 1935 ------------------------------------------------------------------------------- 1936 */ 1937 + static float64 addFloat64Sigs( struct roundingData *roundData, float64 a, float64 b, flag zSign ) 1938 { 1939 int16 aExp, bExp, zExp; 1940 bits64 aSig, bSig, zSig; ··· 1993 ++zExp; 1994 } 1995 roundAndPack: 1996 + return roundAndPackFloat64( roundData, zSign, zExp, zSig ); 1997 1998 } 1999 ··· 2006 Standard for Binary Floating-point Arithmetic. 2007 ------------------------------------------------------------------------------- 2008 */ 2009 + static float64 subFloat64Sigs( struct roundingData *roundData, float64 a, float64 b, flag zSign ) 2010 { 2011 int16 aExp, bExp, zExp; 2012 bits64 aSig, bSig, zSig; ··· 2023 if ( expDiff < 0 ) goto bExpBigger; 2024 if ( aExp == 0x7FF ) { 2025 if ( aSig | bSig ) return propagateFloat64NaN( a, b ); 2026 + roundData->exception |= float_flag_invalid; 2027 return float64_default_nan; 2028 } 2029 if ( aExp == 0 ) { ··· 2032 } 2033 if ( bSig < aSig ) goto aBigger; 2034 if ( aSig < bSig ) goto bBigger; 2035 + return packFloat64( roundData->mode == float_round_down, 0, 0 ); 2036 bExpBigger: 2037 if ( bExp == 0x7FF ) { 2038 if ( bSig ) return propagateFloat64NaN( a, b ); ··· 2069 zExp = aExp; 2070 normalizeRoundAndPack: 2071 --zExp; 2072 + return normalizeRoundAndPackFloat64( roundData, zSign, zExp, zSig ); 2073 2074 } 2075 ··· 2080 Binary Floating-point Arithmetic. 2081 ------------------------------------------------------------------------------- 2082 */ 2083 + float64 float64_add( struct roundingData *roundData, float64 a, float64 b ) 2084 { 2085 flag aSign, bSign; 2086 2087 aSign = extractFloat64Sign( a ); 2088 bSign = extractFloat64Sign( b ); 2089 if ( aSign == bSign ) { 2090 + return addFloat64Sigs( roundData, a, b, aSign ); 2091 } 2092 else { 2093 + return subFloat64Sigs( roundData, a, b, aSign ); 2094 } 2095 2096 } ··· 2102 for Binary Floating-point Arithmetic. 2103 ------------------------------------------------------------------------------- 2104 */ 2105 + float64 float64_sub( struct roundingData *roundData, float64 a, float64 b ) 2106 { 2107 flag aSign, bSign; 2108 2109 aSign = extractFloat64Sign( a ); 2110 bSign = extractFloat64Sign( b ); 2111 if ( aSign == bSign ) { 2112 + return subFloat64Sigs( roundData, a, b, aSign ); 2113 } 2114 else { 2115 + return addFloat64Sigs( roundData, a, b, aSign ); 2116 } 2117 2118 } ··· 2124 for Binary Floating-point Arithmetic. 2125 ------------------------------------------------------------------------------- 2126 */ 2127 + float64 float64_mul( struct roundingData *roundData, float64 a, float64 b ) 2128 { 2129 flag aSign, bSign, zSign; 2130 int16 aExp, bExp, zExp; ··· 2142 return propagateFloat64NaN( a, b ); 2143 } 2144 if ( ( bExp | bSig ) == 0 ) { 2145 + roundData->exception |= float_flag_invalid; 2146 return float64_default_nan; 2147 } 2148 return packFloat64( zSign, 0x7FF, 0 ); ··· 2150 if ( bExp == 0x7FF ) { 2151 if ( bSig ) return propagateFloat64NaN( a, b ); 2152 if ( ( aExp | aSig ) == 0 ) { 2153 + roundData->exception |= float_flag_invalid; 2154 return float64_default_nan; 2155 } 2156 return packFloat64( zSign, 0x7FF, 0 ); ··· 2172 zSig0 <<= 1; 2173 --zExp; 2174 } 2175 + return roundAndPackFloat64( roundData, zSign, zExp, zSig0 ); 2176 2177 } 2178 ··· 2183 the IEC/IEEE Standard for Binary Floating-point Arithmetic. 2184 ------------------------------------------------------------------------------- 2185 */ 2186 + float64 float64_div( struct roundingData *roundData, float64 a, float64 b ) 2187 { 2188 flag aSign, bSign, zSign; 2189 int16 aExp, bExp, zExp; ··· 2202 if ( aSig ) return propagateFloat64NaN( a, b ); 2203 if ( bExp == 0x7FF ) { 2204 if ( bSig ) return propagateFloat64NaN( a, b ); 2205 + roundData->exception |= float_flag_invalid; 2206 return float64_default_nan; 2207 } 2208 return packFloat64( zSign, 0x7FF, 0 ); ··· 2214 if ( bExp == 0 ) { 2215 if ( bSig == 0 ) { 2216 if ( ( aExp | aSig ) == 0 ) { 2217 + roundData->exception |= float_flag_invalid; 2218 return float64_default_nan; 2219 } 2220 + roundData->exception |= float_flag_divbyzero; 2221 return packFloat64( zSign, 0x7FF, 0 ); 2222 } 2223 normalizeFloat64Subnormal( bSig, &bExp, &bSig ); ··· 2243 } 2244 zSig |= ( rem1 != 0 ); 2245 } 2246 + return roundAndPackFloat64( roundData, zSign, zExp, zSig ); 2247 2248 } 2249 ··· 2254 according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 2255 ------------------------------------------------------------------------------- 2256 */ 2257 + float64 float64_rem( struct roundingData *roundData, float64 a, float64 b ) 2258 { 2259 flag aSign, bSign, zSign; 2260 int16 aExp, bExp, expDiff; ··· 2272 if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { 2273 return propagateFloat64NaN( a, b ); 2274 } 2275 + roundData->exception |= float_flag_invalid; 2276 return float64_default_nan; 2277 } 2278 if ( bExp == 0x7FF ) { ··· 2281 } 2282 if ( bExp == 0 ) { 2283 if ( bSig == 0 ) { 2284 + roundData->exception |= float_flag_invalid; 2285 return float64_default_nan; 2286 } 2287 normalizeFloat64Subnormal( bSig, &bExp, &bSig ); ··· 2329 } 2330 zSign = ( (sbits64) aSig < 0 ); 2331 if ( zSign ) aSig = - aSig; 2332 + return normalizeRoundAndPackFloat64( roundData, aSign ^ zSign, bExp, aSig ); 2333 2334 } 2335 ··· 2340 Floating-point Arithmetic. 2341 ------------------------------------------------------------------------------- 2342 */ 2343 + float64 float64_sqrt( struct roundingData *roundData, float64 a ) 2344 { 2345 flag aSign; 2346 int16 aExp, zExp; ··· 2354 if ( aExp == 0x7FF ) { 2355 if ( aSig ) return propagateFloat64NaN( a, a ); 2356 if ( ! aSign ) return a; 2357 + roundData->exception |= float_flag_invalid; 2358 return float64_default_nan; 2359 } 2360 if ( aSign ) { 2361 if ( ( aExp | aSig ) == 0 ) return a; 2362 + roundData->exception |= float_flag_invalid; 2363 return float64_default_nan; 2364 } 2365 if ( aExp == 0 ) { ··· 2390 } 2391 } 2392 shift64RightJamming( zSig, 1, &zSig ); 2393 + return roundAndPackFloat64( roundData, 0, zExp, zSig ); 2394 2395 } 2396 ··· 2554 overflows, the largest integer with the same sign as `a' is returned. 2555 ------------------------------------------------------------------------------- 2556 */ 2557 + int32 floatx80_to_int32( struct roundingData *roundData, floatx80 a ) 2558 { 2559 flag aSign; 2560 int32 aExp, shiftCount; ··· 2567 shiftCount = 0x4037 - aExp; 2568 if ( shiftCount <= 0 ) shiftCount = 1; 2569 shift64RightJamming( aSig, shiftCount, &aSig ); 2570 + return roundAndPackInt32( roundData, aSign, aSig ); 2571 2572 } 2573 ··· 2598 goto invalid; 2599 } 2600 else if ( 63 < shiftCount ) { 2601 + if ( aExp || aSig ) float_raise( float_flag_inexact ); 2602 return 0; 2603 } 2604 savedASig = aSig; ··· 2607 if ( aSign ) z = - z; 2608 if ( ( z < 0 ) ^ aSign ) { 2609 invalid: 2610 + float_raise( float_flag_invalid ); 2611 return aSign ? 0x80000000 : 0x7FFFFFFF; 2612 } 2613 if ( ( aSig<<shiftCount ) != savedASig ) { 2614 + float_raise( float_flag_inexact ); 2615 } 2616 return z; 2617 ··· 2625 Floating-point Arithmetic. 2626 ------------------------------------------------------------------------------- 2627 */ 2628 + float32 floatx80_to_float32( struct roundingData *roundData, floatx80 a ) 2629 { 2630 flag aSign; 2631 int32 aExp; ··· 2642 } 2643 shift64RightJamming( aSig, 33, &aSig ); 2644 if ( aExp || aSig ) aExp -= 0x3F81; 2645 + return roundAndPackFloat32( roundData, aSign, aExp, aSig ); 2646 2647 } 2648 ··· 2654 Floating-point Arithmetic. 2655 ------------------------------------------------------------------------------- 2656 */ 2657 + float64 floatx80_to_float64( struct roundingData *roundData, floatx80 a ) 2658 { 2659 flag aSign; 2660 int32 aExp; ··· 2671 } 2672 shift64RightJamming( aSig, 1, &zSig ); 2673 if ( aExp || aSig ) aExp -= 0x3C01; 2674 + return roundAndPackFloat64( roundData, aSign, aExp, zSig ); 2675 2676 } 2677 ··· 2683 Binary Floating-point Arithmetic. 2684 ------------------------------------------------------------------------------- 2685 */ 2686 + floatx80 floatx80_round_to_int( struct roundingData *roundData, floatx80 a ) 2687 { 2688 flag aSign; 2689 int32 aExp; ··· 2703 && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) { 2704 return a; 2705 } 2706 + roundData->exception |= float_flag_inexact; 2707 aSign = extractFloatx80Sign( a ); 2708 + switch ( roundData->mode ) { 2709 case float_round_nearest_even: 2710 if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 ) 2711 ) { ··· 2729 lastBitMask <<= 0x403E - aExp; 2730 roundBitsMask = lastBitMask - 1; 2731 z = a; 2732 + roundingMode = roundData->mode; 2733 if ( roundingMode == float_round_nearest_even ) { 2734 z.low += lastBitMask>>1; 2735 if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; ··· 2744 ++z.high; 2745 z.low = LIT64( 0x8000000000000000 ); 2746 } 2747 + if ( z.low != a.low ) roundData->exception |= float_flag_inexact; 2748 return z; 2749 2750 } ··· 2758 Floating-point Arithmetic. 2759 ------------------------------------------------------------------------------- 2760 */ 2761 + static floatx80 addFloatx80Sigs( struct roundingData *roundData, floatx80 a, floatx80 b, flag zSign ) 2762 { 2763 int32 aExp, bExp, zExp; 2764 bits64 aSig, bSig, zSig0, zSig1; ··· 2814 roundAndPack: 2815 return 2816 roundAndPackFloatx80( 2817 + roundData, zSign, zExp, zSig0, zSig1 ); 2818 2819 } 2820 ··· 2827 Standard for Binary Floating-point Arithmetic. 2828 ------------------------------------------------------------------------------- 2829 */ 2830 + static floatx80 subFloatx80Sigs( struct roundingData *roundData, floatx80 a, floatx80 b, flag zSign ) 2831 { 2832 int32 aExp, bExp, zExp; 2833 bits64 aSig, bSig, zSig0, zSig1; ··· 2845 if ( (bits64) ( ( aSig | bSig )<<1 ) ) { 2846 return propagateFloatx80NaN( a, b ); 2847 } 2848 + roundData->exception |= float_flag_invalid; 2849 z.low = floatx80_default_nan_low; 2850 z.high = floatx80_default_nan_high; 2851 return z; ··· 2857 zSig1 = 0; 2858 if ( bSig < aSig ) goto aBigger; 2859 if ( aSig < bSig ) goto bBigger; 2860 + return packFloatx80( roundData->mode == float_round_down, 0, 0 ); 2861 bExpBigger: 2862 if ( bExp == 0x7FFF ) { 2863 if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); ··· 2883 normalizeRoundAndPack: 2884 return 2885 normalizeRoundAndPackFloatx80( 2886 + roundData, zSign, zExp, zSig0, zSig1 ); 2887 2888 } 2889 ··· 2894 Standard for Binary Floating-point Arithmetic. 2895 ------------------------------------------------------------------------------- 2896 */ 2897 + floatx80 floatx80_add( struct roundingData *roundData, floatx80 a, floatx80 b ) 2898 { 2899 flag aSign, bSign; 2900 2901 aSign = extractFloatx80Sign( a ); 2902 bSign = extractFloatx80Sign( b ); 2903 if ( aSign == bSign ) { 2904 + return addFloatx80Sigs( roundData, a, b, aSign ); 2905 } 2906 else { 2907 + return subFloatx80Sigs( roundData, a, b, aSign ); 2908 } 2909 2910 } ··· 2916 IEC/IEEE Standard for Binary Floating-point Arithmetic. 2917 ------------------------------------------------------------------------------- 2918 */ 2919 + floatx80 floatx80_sub( struct roundingData *roundData, floatx80 a, floatx80 b ) 2920 { 2921 flag aSign, bSign; 2922 2923 aSign = extractFloatx80Sign( a ); 2924 bSign = extractFloatx80Sign( b ); 2925 if ( aSign == bSign ) { 2926 + return subFloatx80Sigs( roundData, a, b, aSign ); 2927 } 2928 else { 2929 + return addFloatx80Sigs( roundData, a, b, aSign ); 2930 } 2931 2932 } ··· 2938 IEC/IEEE Standard for Binary Floating-point Arithmetic. 2939 ------------------------------------------------------------------------------- 2940 */ 2941 + floatx80 floatx80_mul( struct roundingData *roundData, floatx80 a, floatx80 b ) 2942 { 2943 flag aSign, bSign, zSign; 2944 int32 aExp, bExp, zExp; ··· 2964 if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); 2965 if ( ( aExp | aSig ) == 0 ) { 2966 invalid: 2967 + roundData->exception |= float_flag_invalid; 2968 z.low = floatx80_default_nan_low; 2969 z.high = floatx80_default_nan_high; 2970 return z; ··· 2987 } 2988 return 2989 roundAndPackFloatx80( 2990 + roundData, zSign, zExp, zSig0, zSig1 ); 2991 2992 } 2993 ··· 2998 according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 2999 ------------------------------------------------------------------------------- 3000 */ 3001 + floatx80 floatx80_div( struct roundingData *roundData, floatx80 a, floatx80 b ) 3002 { 3003 flag aSign, bSign, zSign; 3004 int32 aExp, bExp, zExp; ··· 3029 if ( bSig == 0 ) { 3030 if ( ( aExp | aSig ) == 0 ) { 3031 invalid: 3032 + roundData->exception |= float_flag_invalid; 3033 z.low = floatx80_default_nan_low; 3034 z.high = floatx80_default_nan_high; 3035 return z; 3036 } 3037 + roundData->exception |= float_flag_divbyzero; 3038 return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); 3039 } 3040 normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); ··· 3068 } 3069 return 3070 roundAndPackFloatx80( 3071 + roundData, zSign, zExp, zSig0, zSig1 ); 3072 3073 } 3074 ··· 3079 according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 3080 ------------------------------------------------------------------------------- 3081 */ 3082 + floatx80 floatx80_rem( struct roundingData *roundData, floatx80 a, floatx80 b ) 3083 { 3084 flag aSign, bSign, zSign; 3085 int32 aExp, bExp, expDiff; ··· 3107 if ( bExp == 0 ) { 3108 if ( bSig == 0 ) { 3109 invalid: 3110 + roundData->exception |= float_flag_invalid; 3111 z.low = floatx80_default_nan_low; 3112 z.high = floatx80_default_nan_high; 3113 return z; ··· 3164 aSig1 = alternateASig1; 3165 zSign = ! zSign; 3166 } 3167 + 3168 return 3169 normalizeRoundAndPackFloatx80( 3170 + roundData, zSign, bExp + expDiff, aSig0, aSig1 ); 3171 3172 } 3173 ··· 3177 for Binary Floating-point Arithmetic. 3178 ------------------------------------------------------------------------------- 3179 */ 3180 + floatx80 floatx80_sqrt( struct roundingData *roundData, floatx80 a ) 3181 { 3182 flag aSign; 3183 int32 aExp, zExp; ··· 3197 if ( aSign ) { 3198 if ( ( aExp | aSig0 ) == 0 ) return a; 3199 invalid: 3200 + roundData->exception |= float_flag_invalid; 3201 z.low = floatx80_default_nan_low; 3202 z.high = floatx80_default_nan_high; 3203 return z; ··· 3242 } 3243 return 3244 roundAndPackFloatx80( 3245 + roundData, 0, zExp, zSig0, zSig1 ); 3246 3247 } 3248 ··· 3264 ) { 3265 if ( floatx80_is_signaling_nan( a ) 3266 || floatx80_is_signaling_nan( b ) ) { 3267 + roundData->exception |= float_flag_invalid; 3268 } 3269 return 0; 3270 } ··· 3294 || ( ( extractFloatx80Exp( b ) == 0x7FFF ) 3295 && (bits64) ( extractFloatx80Frac( b )<<1 ) ) 3296 ) { 3297 + roundData->exception |= float_flag_invalid; 3298 return 0; 3299 } 3300 aSign = extractFloatx80Sign( a ); ··· 3328 || ( ( extractFloatx80Exp( b ) == 0x7FFF ) 3329 && (bits64) ( extractFloatx80Frac( b )<<1 ) ) 3330 ) { 3331 + roundData->exception |= float_flag_invalid; 3332 return 0; 3333 } 3334 aSign = extractFloatx80Sign( a ); ··· 3361 || ( ( extractFloatx80Exp( b ) == 0x7FFF ) 3362 && (bits64) ( extractFloatx80Frac( b )<<1 ) ) 3363 ) { 3364 + roundData->exception |= float_flag_invalid; 3365 return 0; 3366 } 3367 return ··· 3392 ) { 3393 if ( floatx80_is_signaling_nan( a ) 3394 || floatx80_is_signaling_nan( b ) ) { 3395 + roundData->exception |= float_flag_invalid; 3396 } 3397 return 0; 3398 } ··· 3429 ) { 3430 if ( floatx80_is_signaling_nan( a ) 3431 || floatx80_is_signaling_nan( b ) ) { 3432 + roundData->exception |= float_flag_invalid; 3433 } 3434 return 0; 3435 }
+29 -39
arch/arm/nwfpe/softfloat.h
··· 74 Software IEC/IEEE floating-point rounding mode. 75 ------------------------------------------------------------------------------- 76 */ 77 - extern signed char float_rounding_mode; 78 enum { 79 float_round_nearest_even = 0, 80 float_round_to_zero = 1, ··· 86 ------------------------------------------------------------------------------- 87 Software IEC/IEEE floating-point exception flags. 88 ------------------------------------------------------------------------------- 89 - extern signed char float_exception_flags; 90 enum { 91 float_flag_inexact = 1, 92 float_flag_underflow = 2, ··· 98 Changed the enumeration to match the bit order in the FPA11. 99 */ 100 101 - extern signed char float_exception_flags; 102 enum { 103 float_flag_invalid = 1, 104 float_flag_divbyzero = 2, ··· 119 Software IEC/IEEE integer-to-floating-point conversion routines. 120 ------------------------------------------------------------------------------- 121 */ 122 - float32 int32_to_float32( signed int ); 123 float64 int32_to_float64( signed int ); 124 #ifdef FLOATX80 125 floatx80 int32_to_floatx80( signed int ); ··· 130 Software IEC/IEEE single-precision conversion routines. 131 ------------------------------------------------------------------------------- 132 */ 133 - signed int float32_to_int32( float32 ); 134 signed int float32_to_int32_round_to_zero( float32 ); 135 float64 float32_to_float64( float32 ); 136 #ifdef FLOATX80 ··· 142 Software IEC/IEEE single-precision operations. 143 ------------------------------------------------------------------------------- 144 */ 145 - float32 float32_round_to_int( float32 ); 146 - float32 float32_add( float32, float32 ); 147 - float32 float32_sub( float32, float32 ); 148 - float32 float32_mul( float32, float32 ); 149 - float32 float32_div( float32, float32 ); 150 - float32 float32_rem( float32, float32 ); 151 - float32 float32_sqrt( float32 ); 152 char float32_eq( float32, float32 ); 153 char float32_le( float32, float32 ); 154 char float32_lt( float32, float32 ); ··· 162 Software IEC/IEEE double-precision conversion routines. 163 ------------------------------------------------------------------------------- 164 */ 165 - signed int float64_to_int32( float64 ); 166 signed int float64_to_int32_round_to_zero( float64 ); 167 - float32 float64_to_float32( float64 ); 168 #ifdef FLOATX80 169 floatx80 float64_to_floatx80( float64 ); 170 #endif ··· 174 Software IEC/IEEE double-precision operations. 175 ------------------------------------------------------------------------------- 176 */ 177 - float64 float64_round_to_int( float64 ); 178 - float64 float64_add( float64, float64 ); 179 - float64 float64_sub( float64, float64 ); 180 - float64 float64_mul( float64, float64 ); 181 - float64 float64_div( float64, float64 ); 182 - float64 float64_rem( float64, float64 ); 183 - float64 float64_sqrt( float64 ); 184 char float64_eq( float64, float64 ); 185 char float64_le( float64, float64 ); 186 char float64_lt( float64, float64 ); ··· 196 Software IEC/IEEE extended double-precision conversion routines. 197 ------------------------------------------------------------------------------- 198 */ 199 - signed int floatx80_to_int32( floatx80 ); 200 signed int floatx80_to_int32_round_to_zero( floatx80 ); 201 - float32 floatx80_to_float32( floatx80 ); 202 - float64 floatx80_to_float64( floatx80 ); 203 - 204 - /* 205 - ------------------------------------------------------------------------------- 206 - Software IEC/IEEE extended double-precision rounding precision. Valid 207 - values are 32, 64, and 80. 208 - ------------------------------------------------------------------------------- 209 - */ 210 - extern signed char floatx80_rounding_precision; 211 212 /* 213 ------------------------------------------------------------------------------- 214 Software IEC/IEEE extended double-precision operations. 215 ------------------------------------------------------------------------------- 216 */ 217 - floatx80 floatx80_round_to_int( floatx80 ); 218 - floatx80 floatx80_add( floatx80, floatx80 ); 219 - floatx80 floatx80_sub( floatx80, floatx80 ); 220 - floatx80 floatx80_mul( floatx80, floatx80 ); 221 - floatx80 floatx80_div( floatx80, floatx80 ); 222 - floatx80 floatx80_rem( floatx80, floatx80 ); 223 - floatx80 floatx80_sqrt( floatx80 ); 224 char floatx80_eq( floatx80, floatx80 ); 225 char floatx80_le( floatx80, floatx80 ); 226 char floatx80_lt( floatx80, floatx80 );
··· 74 Software IEC/IEEE floating-point rounding mode. 75 ------------------------------------------------------------------------------- 76 */ 77 + //extern int8 float_rounding_mode; 78 enum { 79 float_round_nearest_even = 0, 80 float_round_to_zero = 1, ··· 86 ------------------------------------------------------------------------------- 87 Software IEC/IEEE floating-point exception flags. 88 ------------------------------------------------------------------------------- 89 enum { 90 float_flag_inexact = 1, 91 float_flag_underflow = 2, ··· 99 Changed the enumeration to match the bit order in the FPA11. 100 */ 101 102 enum { 103 float_flag_invalid = 1, 104 float_flag_divbyzero = 2, ··· 121 Software IEC/IEEE integer-to-floating-point conversion routines. 122 ------------------------------------------------------------------------------- 123 */ 124 + float32 int32_to_float32( struct roundingData *, signed int ); 125 float64 int32_to_float64( signed int ); 126 #ifdef FLOATX80 127 floatx80 int32_to_floatx80( signed int ); ··· 132 Software IEC/IEEE single-precision conversion routines. 133 ------------------------------------------------------------------------------- 134 */ 135 + signed int float32_to_int32( struct roundingData *, float32 ); 136 signed int float32_to_int32_round_to_zero( float32 ); 137 float64 float32_to_float64( float32 ); 138 #ifdef FLOATX80 ··· 144 Software IEC/IEEE single-precision operations. 145 ------------------------------------------------------------------------------- 146 */ 147 + float32 float32_round_to_int( struct roundingData*, float32 ); 148 + float32 float32_add( struct roundingData *, float32, float32 ); 149 + float32 float32_sub( struct roundingData *, float32, float32 ); 150 + float32 float32_mul( struct roundingData *, float32, float32 ); 151 + float32 float32_div( struct roundingData *, float32, float32 ); 152 + float32 float32_rem( struct roundingData *, float32, float32 ); 153 + float32 float32_sqrt( struct roundingData*, float32 ); 154 char float32_eq( float32, float32 ); 155 char float32_le( float32, float32 ); 156 char float32_lt( float32, float32 ); ··· 164 Software IEC/IEEE double-precision conversion routines. 165 ------------------------------------------------------------------------------- 166 */ 167 + signed int float64_to_int32( struct roundingData *, float64 ); 168 signed int float64_to_int32_round_to_zero( float64 ); 169 + float32 float64_to_float32( struct roundingData *, float64 ); 170 #ifdef FLOATX80 171 floatx80 float64_to_floatx80( float64 ); 172 #endif ··· 176 Software IEC/IEEE double-precision operations. 177 ------------------------------------------------------------------------------- 178 */ 179 + float64 float64_round_to_int( struct roundingData *, float64 ); 180 + float64 float64_add( struct roundingData *, float64, float64 ); 181 + float64 float64_sub( struct roundingData *, float64, float64 ); 182 + float64 float64_mul( struct roundingData *, float64, float64 ); 183 + float64 float64_div( struct roundingData *, float64, float64 ); 184 + float64 float64_rem( struct roundingData *, float64, float64 ); 185 + float64 float64_sqrt( struct roundingData *, float64 ); 186 char float64_eq( float64, float64 ); 187 char float64_le( float64, float64 ); 188 char float64_lt( float64, float64 ); ··· 198 Software IEC/IEEE extended double-precision conversion routines. 199 ------------------------------------------------------------------------------- 200 */ 201 + signed int floatx80_to_int32( struct roundingData *, floatx80 ); 202 signed int floatx80_to_int32_round_to_zero( floatx80 ); 203 + float32 floatx80_to_float32( struct roundingData *, floatx80 ); 204 + float64 floatx80_to_float64( struct roundingData *, floatx80 ); 205 206 /* 207 ------------------------------------------------------------------------------- 208 Software IEC/IEEE extended double-precision operations. 209 ------------------------------------------------------------------------------- 210 */ 211 + floatx80 floatx80_round_to_int( struct roundingData *, floatx80 ); 212 + floatx80 floatx80_add( struct roundingData *, floatx80, floatx80 ); 213 + floatx80 floatx80_sub( struct roundingData *, floatx80, floatx80 ); 214 + floatx80 floatx80_mul( struct roundingData *, floatx80, floatx80 ); 215 + floatx80 floatx80_div( struct roundingData *, floatx80, floatx80 ); 216 + floatx80 floatx80_rem( struct roundingData *, floatx80, floatx80 ); 217 + floatx80 floatx80_sqrt( struct roundingData *, floatx80 ); 218 char floatx80_eq( floatx80, floatx80 ); 219 char floatx80_le( floatx80, floatx80 ); 220 char floatx80_lt( floatx80, floatx80 );