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