vfp.cc (7434:dd5a09b86b14) | vfp.cc (7639:8c09b7ff5b57) |
---|---|
1/* 2 * Copyright (c) 2010 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software --- 77 unchanged lines hidden (view full) --- 86 printReg(ss, dest + FP_Base_DepTag); 87 ss << ", "; 88 printReg(ss, op1 + FP_Base_DepTag); 89 ss << ", "; 90 printReg(ss, op2 + FP_Base_DepTag); 91 return ss.str(); 92} 93 | 1/* 2 * Copyright (c) 2010 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software --- 77 unchanged lines hidden (view full) --- 86 printReg(ss, dest + FP_Base_DepTag); 87 ss << ", "; 88 printReg(ss, op1 + FP_Base_DepTag); 89 ss << ", "; 90 printReg(ss, op2 + FP_Base_DepTag); 91 return ss.str(); 92} 93 |
94std::string 95FpRegRegRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 96{ 97 std::stringstream ss; 98 printMnemonic(ss); 99 printReg(ss, dest + FP_Base_DepTag); 100 ss << ", "; 101 printReg(ss, op1 + FP_Base_DepTag); 102 ss << ", "; 103 printReg(ss, op2 + FP_Base_DepTag); 104 ccprintf(ss, ", #%d", imm); 105 return ss.str(); 106} 107 |
|
94namespace ArmISA 95{ 96 97VfpSavedState 98prepFpState(uint32_t rMode) 99{ 100 int roundingMode = fegetround(); 101 feclearexcept(FeAllExceptions); --- 10 unchanged lines hidden (view full) --- 112 case VfpRoundZero: 113 fesetround(FeRoundZero); 114 break; 115 } 116 return roundingMode; 117} 118 119void | 108namespace ArmISA 109{ 110 111VfpSavedState 112prepFpState(uint32_t rMode) 113{ 114 int roundingMode = fegetround(); 115 feclearexcept(FeAllExceptions); --- 10 unchanged lines hidden (view full) --- 126 case VfpRoundZero: 127 fesetround(FeRoundZero); 128 break; 129 } 130 return roundingMode; 131} 132 133void |
120finishVfp(FPSCR &fpscr, VfpSavedState state) | 134finishVfp(FPSCR &fpscr, VfpSavedState state, bool flush) |
121{ 122 int exceptions = fetestexcept(FeAllExceptions); 123 bool underflow = false; 124 if (exceptions & FeInvalid) { 125 fpscr.ioc = 1; 126 } 127 if (exceptions & FeDivByZero) { 128 fpscr.dzc = 1; 129 } 130 if (exceptions & FeOverflow) { 131 fpscr.ofc = 1; 132 } 133 if (exceptions & FeUnderflow) { 134 underflow = true; 135 fpscr.ufc = 1; 136 } | 135{ 136 int exceptions = fetestexcept(FeAllExceptions); 137 bool underflow = false; 138 if (exceptions & FeInvalid) { 139 fpscr.ioc = 1; 140 } 141 if (exceptions & FeDivByZero) { 142 fpscr.dzc = 1; 143 } 144 if (exceptions & FeOverflow) { 145 fpscr.ofc = 1; 146 } 147 if (exceptions & FeUnderflow) { 148 underflow = true; 149 fpscr.ufc = 1; 150 } |
137 if ((exceptions & FeInexact) && !(underflow && fpscr.fz)) { | 151 if ((exceptions & FeInexact) && !(underflow && flush)) { |
138 fpscr.ixc = 1; 139 } 140 fesetround(state); 141} 142 143template <class fpType> 144fpType | 152 fpscr.ixc = 1; 153 } 154 fesetround(state); 155} 156 157template <class fpType> 158fpType |
145fixDest(FPSCR fpscr, fpType val, fpType op1) | 159fixDest(bool flush, bool defaultNan, fpType val, fpType op1) |
146{ 147 int fpClass = std::fpclassify(val); 148 fpType junk = 0.0; 149 if (fpClass == FP_NAN) { 150 const bool single = (sizeof(val) == sizeof(float)); 151 const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); 152 const bool nan = std::isnan(op1); | 160{ 161 int fpClass = std::fpclassify(val); 162 fpType junk = 0.0; 163 if (fpClass == FP_NAN) { 164 const bool single = (sizeof(val) == sizeof(float)); 165 const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); 166 const bool nan = std::isnan(op1); |
153 if (!nan || (fpscr.dn == 1)) { | 167 if (!nan || defaultNan) { |
154 val = bitsToFp(qnan, junk); 155 } else if (nan) { 156 val = bitsToFp(fpToBits(op1) | qnan, junk); 157 } | 168 val = bitsToFp(qnan, junk); 169 } else if (nan) { 170 val = bitsToFp(fpToBits(op1) | qnan, junk); 171 } |
158 } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) { | 172 } else if (fpClass == FP_SUBNORMAL && flush == 1) { |
159 // Turn val into a zero with the correct sign; 160 uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 161 val = bitsToFp(fpToBits(val) & bitMask, junk); 162 feclearexcept(FeInexact); 163 feraiseexcept(FeUnderflow); 164 } 165 return val; 166} 167 168template | 173 // Turn val into a zero with the correct sign; 174 uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 175 val = bitsToFp(fpToBits(val) & bitMask, junk); 176 feclearexcept(FeInexact); 177 feraiseexcept(FeUnderflow); 178 } 179 return val; 180} 181 182template |
169float fixDest<float>(FPSCR fpscr, float val, float op1); | 183float fixDest<float>(bool flush, bool defaultNan, float val, float op1); |
170template | 184template |
171double fixDest<double>(FPSCR fpscr, double val, double op1); | 185double fixDest<double>(bool flush, bool defaultNan, double val, double op1); |
172 173template <class fpType> 174fpType | 186 187template <class fpType> 188fpType |
175fixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2) | 189fixDest(bool flush, bool defaultNan, fpType val, fpType op1, fpType op2) |
176{ 177 int fpClass = std::fpclassify(val); 178 fpType junk = 0.0; 179 if (fpClass == FP_NAN) { 180 const bool single = (sizeof(val) == sizeof(float)); 181 const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); 182 const bool nan1 = std::isnan(op1); 183 const bool nan2 = std::isnan(op2); 184 const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); 185 const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan); | 190{ 191 int fpClass = std::fpclassify(val); 192 fpType junk = 0.0; 193 if (fpClass == FP_NAN) { 194 const bool single = (sizeof(val) == sizeof(float)); 195 const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); 196 const bool nan1 = std::isnan(op1); 197 const bool nan2 = std::isnan(op2); 198 const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); 199 const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan); |
186 if ((!nan1 && !nan2) || (fpscr.dn == 1)) { | 200 if ((!nan1 && !nan2) || defaultNan) { |
187 val = bitsToFp(qnan, junk); 188 } else if (signal1) { 189 val = bitsToFp(fpToBits(op1) | qnan, junk); 190 } else if (signal2) { 191 val = bitsToFp(fpToBits(op2) | qnan, junk); 192 } else if (nan1) { 193 val = op1; 194 } else if (nan2) { 195 val = op2; 196 } | 201 val = bitsToFp(qnan, junk); 202 } else if (signal1) { 203 val = bitsToFp(fpToBits(op1) | qnan, junk); 204 } else if (signal2) { 205 val = bitsToFp(fpToBits(op2) | qnan, junk); 206 } else if (nan1) { 207 val = op1; 208 } else if (nan2) { 209 val = op2; 210 } |
197 } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) { | 211 } else if (fpClass == FP_SUBNORMAL && flush) { |
198 // Turn val into a zero with the correct sign; 199 uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 200 val = bitsToFp(fpToBits(val) & bitMask, junk); 201 feclearexcept(FeInexact); 202 feraiseexcept(FeUnderflow); 203 } 204 return val; 205} 206 207template | 212 // Turn val into a zero with the correct sign; 213 uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 214 val = bitsToFp(fpToBits(val) & bitMask, junk); 215 feclearexcept(FeInexact); 216 feraiseexcept(FeUnderflow); 217 } 218 return val; 219} 220 221template |
208float fixDest<float>(FPSCR fpscr, float val, float op1, float op2); | 222float fixDest<float>(bool flush, bool defaultNan, 223 float val, float op1, float op2); |
209template | 224template |
210double fixDest<double>(FPSCR fpscr, double val, double op1, double op2); | 225double fixDest<double>(bool flush, bool defaultNan, 226 double val, double op1, double op2); |
211 212template <class fpType> 213fpType | 227 228template <class fpType> 229fpType |
214fixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2) | 230fixDivDest(bool flush, bool defaultNan, fpType val, fpType op1, fpType op2) |
215{ | 231{ |
216 fpType mid = fixDest(fpscr, val, op1, op2); | 232 fpType mid = fixDest(flush, defaultNan, val, op1, op2); |
217 const bool single = (sizeof(fpType) == sizeof(float)); 218 const fpType junk = 0.0; 219 if ((single && (val == bitsToFp(0x00800000, junk) || 220 val == bitsToFp(0x80800000, junk))) || 221 (!single && (val == bitsToFp(ULL(0x0010000000000000), junk) || 222 val == bitsToFp(ULL(0x8010000000000000), junk))) 223 ) { 224 __asm__ __volatile__("" : "=m" (op1) : "m" (op1)); 225 fesetround(FeRoundZero); 226 fpType temp = 0.0; 227 __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 228 temp = op1 / op2; 229 if (flushToZero(temp)) { 230 feraiseexcept(FeUnderflow); | 233 const bool single = (sizeof(fpType) == sizeof(float)); 234 const fpType junk = 0.0; 235 if ((single && (val == bitsToFp(0x00800000, junk) || 236 val == bitsToFp(0x80800000, junk))) || 237 (!single && (val == bitsToFp(ULL(0x0010000000000000), junk) || 238 val == bitsToFp(ULL(0x8010000000000000), junk))) 239 ) { 240 __asm__ __volatile__("" : "=m" (op1) : "m" (op1)); 241 fesetround(FeRoundZero); 242 fpType temp = 0.0; 243 __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 244 temp = op1 / op2; 245 if (flushToZero(temp)) { 246 feraiseexcept(FeUnderflow); |
231 if (fpscr.fz) { | 247 if (flush) { |
232 feclearexcept(FeInexact); 233 mid = temp; 234 } 235 } 236 __asm__ __volatile__("" :: "m" (temp)); 237 } 238 return mid; 239} 240 241template | 248 feclearexcept(FeInexact); 249 mid = temp; 250 } 251 } 252 __asm__ __volatile__("" :: "m" (temp)); 253 } 254 return mid; 255} 256 257template |
242float fixDivDest<float>(FPSCR fpscr, float val, float op1, float op2); | 258float fixDivDest<float>(bool flush, bool defaultNan, 259 float val, float op1, float op2); |
243template | 260template |
244double fixDivDest<double>(FPSCR fpscr, double val, double op1, double op2); | 261double fixDivDest<double>(bool flush, bool defaultNan, 262 double val, double op1, double op2); |
245 246float 247fixFpDFpSDest(FPSCR fpscr, double val) 248{ 249 const float junk = 0.0; 250 float op1 = 0.0; 251 if (std::isnan(val)) { 252 uint64_t valBits = fpToBits(val); 253 uint32_t op1Bits = bits(valBits, 50, 29) | 254 (mask(9) << 22) | 255 (bits(valBits, 63) << 31); 256 op1 = bitsToFp(op1Bits, junk); 257 } | 263 264float 265fixFpDFpSDest(FPSCR fpscr, double val) 266{ 267 const float junk = 0.0; 268 float op1 = 0.0; 269 if (std::isnan(val)) { 270 uint64_t valBits = fpToBits(val); 271 uint32_t op1Bits = bits(valBits, 50, 29) | 272 (mask(9) << 22) | 273 (bits(valBits, 63) << 31); 274 op1 = bitsToFp(op1Bits, junk); 275 } |
258 float mid = fixDest(fpscr, (float)val, op1); | 276 float mid = fixDest(fpscr.fz, fpscr.dn, (float)val, op1); |
259 if (fpscr.fz && fetestexcept(FeUnderflow | FeInexact) == 260 (FeUnderflow | FeInexact)) { 261 feclearexcept(FeInexact); 262 } 263 if (mid == bitsToFp(0x00800000, junk) || 264 mid == bitsToFp(0x80800000, junk)) { 265 __asm__ __volatile__("" : "=m" (val) : "m" (val)); 266 fesetround(FeRoundZero); --- 19 unchanged lines hidden (view full) --- 286 double op1 = 0.0; 287 if (std::isnan(val)) { 288 uint32_t valBits = fpToBits(val); 289 uint64_t op1Bits = ((uint64_t)bits(valBits, 21, 0) << 29) | 290 (mask(12) << 51) | 291 ((uint64_t)bits(valBits, 31) << 63); 292 op1 = bitsToFp(op1Bits, junk); 293 } | 277 if (fpscr.fz && fetestexcept(FeUnderflow | FeInexact) == 278 (FeUnderflow | FeInexact)) { 279 feclearexcept(FeInexact); 280 } 281 if (mid == bitsToFp(0x00800000, junk) || 282 mid == bitsToFp(0x80800000, junk)) { 283 __asm__ __volatile__("" : "=m" (val) : "m" (val)); 284 fesetround(FeRoundZero); --- 19 unchanged lines hidden (view full) --- 304 double op1 = 0.0; 305 if (std::isnan(val)) { 306 uint32_t valBits = fpToBits(val); 307 uint64_t op1Bits = ((uint64_t)bits(valBits, 21, 0) << 29) | 308 (mask(12) << 51) | 309 ((uint64_t)bits(valBits, 31) << 63); 310 op1 = bitsToFp(op1Bits, junk); 311 } |
294 double mid = fixDest(fpscr, (double)val, op1); | 312 double mid = fixDest(fpscr.fz, fpscr.dn, (double)val, op1); |
295 if (mid == bitsToFp(ULL(0x0010000000000000), junk) || 296 mid == bitsToFp(ULL(0x8010000000000000), junk)) { 297 __asm__ __volatile__("" : "=m" (val) : "m" (val)); 298 fesetround(FeRoundZero); 299 double temp = 0.0; 300 __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 301 temp = val; 302 if (flushToZero(temp)) { 303 feraiseexcept(FeUnderflow); 304 if (fpscr.fz) { 305 feclearexcept(FeInexact); 306 mid = temp; 307 } 308 } 309 __asm__ __volatile__("" :: "m" (temp)); 310 } 311 return mid; 312} 313 | 313 if (mid == bitsToFp(ULL(0x0010000000000000), junk) || 314 mid == bitsToFp(ULL(0x8010000000000000), junk)) { 315 __asm__ __volatile__("" : "=m" (val) : "m" (val)); 316 fesetround(FeRoundZero); 317 double temp = 0.0; 318 __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 319 temp = val; 320 if (flushToZero(temp)) { 321 feraiseexcept(FeUnderflow); 322 if (fpscr.fz) { 323 feclearexcept(FeInexact); 324 mid = temp; 325 } 326 } 327 __asm__ __volatile__("" :: "m" (temp)); 328 } 329 return mid; 330} 331 |
314float 315vcvtFpSFpH(FPSCR &fpscr, float op, float dest, bool top) | 332uint16_t 333vcvtFpSFpH(FPSCR &fpscr, bool flush, bool defaultNan, 334 uint32_t rMode, bool ahp, float op) |
316{ | 335{ |
317 float junk = 0.0; 318 uint32_t destBits = fpToBits(dest); | |
319 uint32_t opBits = fpToBits(op); 320 // Extract the operand. 321 bool neg = bits(opBits, 31); 322 uint32_t exponent = bits(opBits, 30, 23); 323 uint32_t oldMantissa = bits(opBits, 22, 0); 324 uint32_t mantissa = oldMantissa >> (23 - 10); 325 // Do the conversion. 326 uint32_t extra = oldMantissa & mask(23 - 10); 327 if (exponent == 0xff) { 328 if (oldMantissa != 0) { 329 // Nans. 330 if (bits(mantissa, 9) == 0) { 331 // Signalling nan. 332 fpscr.ioc = 1; 333 } | 336 uint32_t opBits = fpToBits(op); 337 // Extract the operand. 338 bool neg = bits(opBits, 31); 339 uint32_t exponent = bits(opBits, 30, 23); 340 uint32_t oldMantissa = bits(opBits, 22, 0); 341 uint32_t mantissa = oldMantissa >> (23 - 10); 342 // Do the conversion. 343 uint32_t extra = oldMantissa & mask(23 - 10); 344 if (exponent == 0xff) { 345 if (oldMantissa != 0) { 346 // Nans. 347 if (bits(mantissa, 9) == 0) { 348 // Signalling nan. 349 fpscr.ioc = 1; 350 } |
334 if (fpscr.ahp) { | 351 if (ahp) { |
335 mantissa = 0; 336 exponent = 0; 337 fpscr.ioc = 1; | 352 mantissa = 0; 353 exponent = 0; 354 fpscr.ioc = 1; |
338 } else if (fpscr.dn) { | 355 } else if (defaultNan) { |
339 mantissa = (1 << 9); 340 exponent = 0x1f; 341 neg = false; 342 } else { 343 exponent = 0x1f; 344 mantissa |= (1 << 9); 345 } 346 } else { 347 // Infinities. 348 exponent = 0x1F; | 356 mantissa = (1 << 9); 357 exponent = 0x1f; 358 neg = false; 359 } else { 360 exponent = 0x1f; 361 mantissa |= (1 << 9); 362 } 363 } else { 364 // Infinities. 365 exponent = 0x1F; |
349 if (fpscr.ahp) { | 366 if (ahp) { |
350 fpscr.ioc = 1; 351 mantissa = 0x3ff; 352 } else { 353 mantissa = 0; 354 } 355 } 356 } else if (exponent == 0 && oldMantissa == 0) { 357 // Zero, don't need to do anything. 358 } else { 359 // Normalized or denormalized numbers. 360 361 bool inexact = (extra != 0); 362 363 if (exponent == 0) { 364 // Denormalized. 365 366 // If flush to zero is on, this shouldn't happen. | 367 fpscr.ioc = 1; 368 mantissa = 0x3ff; 369 } else { 370 mantissa = 0; 371 } 372 } 373 } else if (exponent == 0 && oldMantissa == 0) { 374 // Zero, don't need to do anything. 375 } else { 376 // Normalized or denormalized numbers. 377 378 bool inexact = (extra != 0); 379 380 if (exponent == 0) { 381 // Denormalized. 382 383 // If flush to zero is on, this shouldn't happen. |
367 assert(fpscr.fz == 0); | 384 assert(!flush); |
368 369 // Check for underflow 370 if (inexact || fpscr.ufe) 371 fpscr.ufc = 1; 372 373 // Handle rounding. | 385 386 // Check for underflow 387 if (inexact || fpscr.ufe) 388 fpscr.ufc = 1; 389 390 // Handle rounding. |
374 unsigned mode = fpscr.rMode; | 391 unsigned mode = rMode; |
375 if ((mode == VfpRoundUpward && !neg && extra) || 376 (mode == VfpRoundDown && neg && extra) || 377 (mode == VfpRoundNearest && 378 (extra > (1 << 9) || 379 (extra == (1 << 9) && bits(mantissa, 0))))) { 380 mantissa++; 381 } 382 --- 28 unchanged lines hidden (view full) --- 411 } 412 413 if (exponent == 0 && (inexact || fpscr.ufe)) { 414 // Underflow 415 fpscr.ufc = 1; 416 } 417 418 // Handle rounding. | 392 if ((mode == VfpRoundUpward && !neg && extra) || 393 (mode == VfpRoundDown && neg && extra) || 394 (mode == VfpRoundNearest && 395 (extra > (1 << 9) || 396 (extra == (1 << 9) && bits(mantissa, 0))))) { 397 mantissa++; 398 } 399 --- 28 unchanged lines hidden (view full) --- 428 } 429 430 if (exponent == 0 && (inexact || fpscr.ufe)) { 431 // Underflow 432 fpscr.ufc = 1; 433 } 434 435 // Handle rounding. |
419 unsigned mode = fpscr.rMode; | 436 unsigned mode = rMode; |
420 bool nonZero = topOne || !restZeros; 421 if ((mode == VfpRoundUpward && !neg && nonZero) || 422 (mode == VfpRoundDown && neg && nonZero) || 423 (mode == VfpRoundNearest && topOne && 424 (!restZeros || bits(mantissa, 0)))) { 425 mantissa++; 426 } 427 428 // See if we rounded up and need to bump the exponent. 429 if (mantissa == (1 << 10)) { 430 mantissa = 0; 431 exponent++; 432 } 433 434 // Deal with overflow | 437 bool nonZero = topOne || !restZeros; 438 if ((mode == VfpRoundUpward && !neg && nonZero) || 439 (mode == VfpRoundDown && neg && nonZero) || 440 (mode == VfpRoundNearest && topOne && 441 (!restZeros || bits(mantissa, 0)))) { 442 mantissa++; 443 } 444 445 // See if we rounded up and need to bump the exponent. 446 if (mantissa == (1 << 10)) { 447 mantissa = 0; 448 exponent++; 449 } 450 451 // Deal with overflow |
435 if (fpscr.ahp) { | 452 if (ahp) { |
436 if (exponent >= 0x20) { 437 exponent = 0x1f; 438 mantissa = 0x3ff; 439 fpscr.ioc = 1; 440 // Supress inexact exception. 441 inexact = false; 442 } 443 } else { --- 19 unchanged lines hidden (view full) --- 463 fpscr.ixc = 1; 464 } 465 } 466 // Reassemble and install the result. 467 uint32_t result = bits(mantissa, 9, 0); 468 replaceBits(result, 14, 10, exponent); 469 if (neg) 470 result |= (1 << 15); | 453 if (exponent >= 0x20) { 454 exponent = 0x1f; 455 mantissa = 0x3ff; 456 fpscr.ioc = 1; 457 // Supress inexact exception. 458 inexact = false; 459 } 460 } else { --- 19 unchanged lines hidden (view full) --- 480 fpscr.ixc = 1; 481 } 482 } 483 // Reassemble and install the result. 484 uint32_t result = bits(mantissa, 9, 0); 485 replaceBits(result, 14, 10, exponent); 486 if (neg) 487 result |= (1 << 15); |
471 if (top) 472 replaceBits(destBits, 31, 16, result); 473 else 474 replaceBits(destBits, 15, 0, result); 475 return bitsToFp(destBits, junk); | 488 return result; |
476} 477 478float | 489} 490 491float |
479vcvtFpHFpS(FPSCR &fpscr, float op, bool top) | 492vcvtFpHFpS(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op) |
480{ 481 float junk = 0.0; | 493{ 494 float junk = 0.0; |
482 uint32_t opBits = fpToBits(op); 483 // Extract the operand. 484 if (top) 485 opBits = bits(opBits, 31, 16); 486 else 487 opBits = bits(opBits, 15, 0); | |
488 // Extract the bitfields. | 495 // Extract the bitfields. |
489 bool neg = bits(opBits, 15); 490 uint32_t exponent = bits(opBits, 14, 10); 491 uint32_t mantissa = bits(opBits, 9, 0); | 496 bool neg = bits(op, 15); 497 uint32_t exponent = bits(op, 14, 10); 498 uint32_t mantissa = bits(op, 9, 0); |
492 // Do the conversion. 493 if (exponent == 0) { 494 if (mantissa != 0) { 495 // Normalize the value. 496 exponent = exponent + (127 - 15) + 1; 497 while (mantissa < (1 << 10)) { 498 mantissa = mantissa << 1; 499 exponent--; 500 } 501 } 502 mantissa = mantissa << (23 - 10); | 499 // Do the conversion. 500 if (exponent == 0) { 501 if (mantissa != 0) { 502 // Normalize the value. 503 exponent = exponent + (127 - 15) + 1; 504 while (mantissa < (1 << 10)) { 505 mantissa = mantissa << 1; 506 exponent--; 507 } 508 } 509 mantissa = mantissa << (23 - 10); |
503 } else if (exponent == 0x1f && !fpscr.ahp) { | 510 } else if (exponent == 0x1f && !ahp) { |
504 // Infinities and nans. 505 exponent = 0xff; 506 if (mantissa != 0) { 507 // Nans. 508 mantissa = mantissa << (23 - 10); 509 if (bits(mantissa, 22) == 0) { 510 // Signalling nan. 511 fpscr.ioc = 1; 512 mantissa |= (1 << 22); 513 } | 511 // Infinities and nans. 512 exponent = 0xff; 513 if (mantissa != 0) { 514 // Nans. 515 mantissa = mantissa << (23 - 10); 516 if (bits(mantissa, 22) == 0) { 517 // Signalling nan. 518 fpscr.ioc = 1; 519 mantissa |= (1 << 22); 520 } |
514 if (fpscr.dn) { | 521 if (defaultNan) { |
515 mantissa &= ~mask(22); 516 neg = false; 517 } 518 } 519 } else { 520 exponent = exponent + (127 - 15); 521 mantissa = mantissa << (23 - 10); 522 } --- 96 unchanged lines hidden (view full) --- 619 return mask(32); 620 } 621 return (uint32_t)val; 622 } 623 } 624} 625 626float | 522 mantissa &= ~mask(22); 523 neg = false; 524 } 525 } 526 } else { 527 exponent = exponent + (127 - 15); 528 mantissa = mantissa << (23 - 10); 529 } --- 96 unchanged lines hidden (view full) --- 626 return mask(32); 627 } 628 return (uint32_t)val; 629 } 630 } 631} 632 633float |
627vfpUFixedToFpS(FPSCR fpscr, uint32_t val, bool half, uint8_t imm) | 634vfpUFixedToFpS(bool flush, bool defaultNan, 635 uint32_t val, bool half, uint8_t imm) |
628{ 629 fesetround(FeRoundNearest); 630 if (half) 631 val = (uint16_t)val; 632 float scale = powf(2.0, imm); 633 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 634 feclearexcept(FeAllExceptions); 635 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); | 636{ 637 fesetround(FeRoundNearest); 638 if (half) 639 val = (uint16_t)val; 640 float scale = powf(2.0, imm); 641 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 642 feclearexcept(FeAllExceptions); 643 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); |
636 return fixDivDest(fpscr, val / scale, (float)val, scale); | 644 return fixDivDest(flush, defaultNan, val / scale, (float)val, scale); |
637} 638 639float | 645} 646 647float |
640vfpSFixedToFpS(FPSCR fpscr, int32_t val, bool half, uint8_t imm) | 648vfpSFixedToFpS(bool flush, bool defaultNan, 649 int32_t val, bool half, uint8_t imm) |
641{ 642 fesetround(FeRoundNearest); 643 if (half) 644 val = sext<16>(val & mask(16)); 645 float scale = powf(2.0, imm); 646 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 647 feclearexcept(FeAllExceptions); 648 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); | 650{ 651 fesetround(FeRoundNearest); 652 if (half) 653 val = sext<16>(val & mask(16)); 654 float scale = powf(2.0, imm); 655 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 656 feclearexcept(FeAllExceptions); 657 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); |
649 return fixDivDest(fpscr, val / scale, (float)val, scale); | 658 return fixDivDest(flush, defaultNan, val / scale, (float)val, scale); |
650} 651 652uint64_t 653vfpFpDToFixed(double val, bool isSigned, bool half, 654 uint8_t imm, bool rzero) 655{ 656 int rmode = rzero ? FeRoundZero : fegetround(); 657 fesetround(FeRoundNearest); --- 80 unchanged lines hidden (view full) --- 738 return mask(32); 739 } 740 return (uint32_t)val; 741 } 742 } 743} 744 745double | 659} 660 661uint64_t 662vfpFpDToFixed(double val, bool isSigned, bool half, 663 uint8_t imm, bool rzero) 664{ 665 int rmode = rzero ? FeRoundZero : fegetround(); 666 fesetround(FeRoundNearest); --- 80 unchanged lines hidden (view full) --- 747 return mask(32); 748 } 749 return (uint32_t)val; 750 } 751 } 752} 753 754double |
746vfpUFixedToFpD(FPSCR fpscr, uint32_t val, bool half, uint8_t imm) | 755vfpUFixedToFpD(bool flush, bool defaultNan, 756 uint32_t val, bool half, uint8_t imm) |
747{ 748 fesetround(FeRoundNearest); 749 if (half) 750 val = (uint16_t)val; 751 double scale = pow(2.0, imm); 752 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 753 feclearexcept(FeAllExceptions); 754 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); | 757{ 758 fesetround(FeRoundNearest); 759 if (half) 760 val = (uint16_t)val; 761 double scale = pow(2.0, imm); 762 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 763 feclearexcept(FeAllExceptions); 764 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); |
755 return fixDivDest(fpscr, val / scale, (double)val, scale); | 765 return fixDivDest(flush, defaultNan, val / scale, (double)val, scale); |
756} 757 758double | 766} 767 768double |
759vfpSFixedToFpD(FPSCR fpscr, int32_t val, bool half, uint8_t imm) | 769vfpSFixedToFpD(bool flush, bool defaultNan, 770 int32_t val, bool half, uint8_t imm) |
760{ 761 fesetround(FeRoundNearest); 762 if (half) 763 val = sext<16>(val & mask(16)); 764 double scale = pow(2.0, imm); 765 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 766 feclearexcept(FeAllExceptions); 767 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); | 771{ 772 fesetround(FeRoundNearest); 773 if (half) 774 val = sext<16>(val & mask(16)); 775 double scale = pow(2.0, imm); 776 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 777 feclearexcept(FeAllExceptions); 778 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); |
768 return fixDivDest(fpscr, val / scale, (double)val, scale); | 779 return fixDivDest(flush, defaultNan, val / scale, (double)val, scale); |
769} 770 | 780} 781 |
782// This function implements a magic formula taken from the architecture 783// reference manual. It was originally called recip_sqrt_estimate. 784static double 785recipSqrtEstimate(double a) 786{ 787 int64_t q0, q1, s; 788 double r; 789 if (a < 0.5) { 790 q0 = (int64_t)(a * 512.0); 791 r = 1.0 / sqrt(((double)q0 + 0.5) / 512.0); 792 } else { 793 q1 = (int64_t)(a * 256.0); 794 r = 1.0 / sqrt(((double)q1 + 0.5) / 256.0); 795 } 796 s = (int64_t)(256.0 * r + 0.5); 797 return (double)s / 256.0; 798} 799 800// This function is only intended for use in Neon instructions because 801// it ignores certain bits in the FPSCR. 802float 803fprSqrtEstimate(FPSCR &fpscr, float op) 804{ 805 const uint32_t qnan = 0x7fc00000; 806 float junk = 0.0; 807 int fpClass = std::fpclassify(op); 808 if (fpClass == FP_NAN) { 809 if ((fpToBits(op) & qnan) != qnan) 810 fpscr.ioc = 1; 811 return bitsToFp(qnan, junk); 812 } else if (fpClass == FP_ZERO) { 813 fpscr.dzc = 1; 814 // Return infinity with the same sign as the operand. 815 return bitsToFp((std::signbit(op) << 31) | 816 (0xFF << 23) | (0 << 0), junk); 817 } else if (std::signbit(op)) { 818 // Set invalid op bit. 819 fpscr.ioc = 1; 820 return bitsToFp(qnan, junk); 821 } else if (fpClass == FP_INFINITE) { 822 return 0.0; 823 } else { 824 uint64_t opBits = fpToBits(op); 825 double scaled; 826 if (bits(opBits, 23)) { 827 scaled = bitsToFp((0 << 0) | (bits(opBits, 22, 0) << 29) | 828 (ULL(0x3fd) << 52) | (bits(opBits, 31) << 63), 829 (double)0.0); 830 } else { 831 scaled = bitsToFp((0 << 0) | (bits(opBits, 22, 0) << 29) | 832 (ULL(0x3fe) << 52) | (bits(opBits, 31) << 63), 833 (double)0.0); 834 } 835 uint64_t resultExp = (380 - bits(opBits, 30, 23)) / 2; 836 837 uint64_t estimate = fpToBits(recipSqrtEstimate(scaled)); 838 839 return bitsToFp((bits(estimate, 63) << 31) | 840 (bits(resultExp, 7, 0) << 23) | 841 (bits(estimate, 51, 29) << 0), junk); 842 } 843} 844 845uint32_t 846unsignedRSqrtEstimate(uint32_t op) 847{ 848 if (bits(op, 31, 30) == 0) { 849 return -1; 850 } else { 851 double dpOp; 852 if (bits(op, 31)) { 853 dpOp = bitsToFp((ULL(0) << 63) | 854 (ULL(0x3fe) << 52) | 855 (bits((uint64_t)op, 30, 0) << 21) | 856 (0 << 0), (double)0.0); 857 } else { 858 dpOp = bitsToFp((ULL(0) << 63) | 859 (ULL(0x3fd) << 52) | 860 (bits((uint64_t)op, 29, 0) << 22) | 861 (0 << 0), (double)0.0); 862 } 863 uint64_t estimate = fpToBits(recipSqrtEstimate(dpOp)); 864 return (1 << 31) | bits(estimate, 51, 21); 865 } 866} 867 868// This function implements a magic formula taken from the architecture 869// reference manual. It was originally called recip_estimate. 870 871static double 872recipEstimate(double a) 873{ 874 int64_t q, s; 875 double r; 876 q = (int64_t)(a * 512.0); 877 r = 1.0 / (((double)q + 0.5) / 512.0); 878 s = (int64_t)(256.0 * r + 0.5); 879 return (double)s / 256.0; 880} 881 882// This function is only intended for use in Neon instructions because 883// it ignores certain bits in the FPSCR. 884float 885fpRecipEstimate(FPSCR &fpscr, float op) 886{ 887 const uint32_t qnan = 0x7fc00000; 888 float junk = 0.0; 889 int fpClass = std::fpclassify(op); 890 if (fpClass == FP_NAN) { 891 if ((fpToBits(op) & qnan) != qnan) 892 fpscr.ioc = 1; 893 return bitsToFp(qnan, junk); 894 } else if (fpClass == FP_INFINITE) { 895 return bitsToFp(std::signbit(op) << 31, junk); 896 } else if (fpClass == FP_ZERO) { 897 fpscr.dzc = 1; 898 // Return infinity with the same sign as the operand. 899 return bitsToFp((std::signbit(op) << 31) | 900 (0xFF << 23) | (0 << 0), junk); 901 } else if (fabs(op) >= pow(2.0, 126)) { 902 fpscr.ufc = 1; 903 return bitsToFp(std::signbit(op) << 31, junk); 904 } else { 905 uint64_t opBits = fpToBits(op); 906 double scaled; 907 scaled = bitsToFp((0 << 0) | (bits(opBits, 22, 0) << 29) | 908 (ULL(0x3fe) << 52) | (ULL(0) << 63), 909 (double)0.0); 910 uint64_t resultExp = 253 - bits(opBits, 30, 23); 911 912 uint64_t estimate = fpToBits(recipEstimate(scaled)); 913 914 return bitsToFp((bits(opBits, 31) << 31) | 915 (bits(resultExp, 7, 0) << 23) | 916 (bits(estimate, 51, 29) << 0), junk); 917 } 918} 919 920uint32_t 921unsignedRecipEstimate(uint32_t op) 922{ 923 if (bits(op, 31) == 0) { 924 return -1; 925 } else { 926 double dpOp; 927 dpOp = bitsToFp((ULL(0) << 63) | 928 (ULL(0x3fe) << 52) | 929 (bits((uint64_t)op, 30, 0) << 21) | 930 (0 << 0), (double)0.0); 931 uint64_t estimate = fpToBits(recipEstimate(dpOp)); 932 return (1 << 31) | bits(estimate, 51, 21); 933 } 934} 935 |
|
771template <class fpType> 772fpType | 936template <class fpType> 937fpType |
938FpOp::processNans(FPSCR &fpscr, bool &done, bool defaultNan, 939 fpType op1, fpType op2) const 940{ 941 done = true; 942 fpType junk = 0.0; 943 fpType dest = 0.0; 944 const bool single = (sizeof(fpType) == sizeof(float)); 945 const uint64_t qnan = 946 single ? 0x7fc00000 : ULL(0x7ff8000000000000); 947 const bool nan1 = std::isnan(op1); 948 const bool nan2 = std::isnan(op2); 949 const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); 950 const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan); 951 if (nan1 || nan2) { 952 if (defaultNan) { 953 dest = bitsToFp(qnan, junk); 954 } else if (signal1) { 955 dest = bitsToFp(fpToBits(op1) | qnan, junk); 956 } else if (signal2) { 957 dest = bitsToFp(fpToBits(op2) | qnan, junk); 958 } else if (nan1) { 959 dest = op1; 960 } else if (nan2) { 961 dest = op2; 962 } 963 if (signal1 || signal2) { 964 fpscr.ioc = 1; 965 } 966 } else { 967 done = false; 968 } 969 return dest; 970} 971 972template 973float FpOp::processNans(FPSCR &fpscr, bool &done, bool defaultNan, 974 float op1, float op2) const; 975template 976double FpOp::processNans(FPSCR &fpscr, bool &done, bool defaultNan, 977 double op1, double op2) const; 978 979template <class fpType> 980fpType |
|
773FpOp::binaryOp(FPSCR &fpscr, fpType op1, fpType op2, 774 fpType (*func)(fpType, fpType), | 981FpOp::binaryOp(FPSCR &fpscr, fpType op1, fpType op2, 982 fpType (*func)(fpType, fpType), |
775 bool flush, uint32_t rMode) const | 983 bool flush, bool defaultNan, uint32_t rMode) const |
776{ 777 const bool single = (sizeof(fpType) == sizeof(float)); 778 fpType junk = 0.0; 779 780 if (flush && flushToZero(op1, op2)) 781 fpscr.idc = 1; 782 VfpSavedState state = prepFpState(rMode); 783 __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2), "=m" (state) --- 6 unchanged lines hidden (view full) --- 790 if (fpClass == FP_NAN) { 791 const bool single = (sizeof(fpType) == sizeof(float)); 792 const uint64_t qnan = 793 single ? 0x7fc00000 : ULL(0x7ff8000000000000); 794 const bool nan1 = std::isnan(op1); 795 const bool nan2 = std::isnan(op2); 796 const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); 797 const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan); | 984{ 985 const bool single = (sizeof(fpType) == sizeof(float)); 986 fpType junk = 0.0; 987 988 if (flush && flushToZero(op1, op2)) 989 fpscr.idc = 1; 990 VfpSavedState state = prepFpState(rMode); 991 __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2), "=m" (state) --- 6 unchanged lines hidden (view full) --- 998 if (fpClass == FP_NAN) { 999 const bool single = (sizeof(fpType) == sizeof(float)); 1000 const uint64_t qnan = 1001 single ? 0x7fc00000 : ULL(0x7ff8000000000000); 1002 const bool nan1 = std::isnan(op1); 1003 const bool nan2 = std::isnan(op2); 1004 const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); 1005 const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan); |
798 if ((!nan1 && !nan2) || (fpscr.dn == 1)) { | 1006 if ((!nan1 && !nan2) || (defaultNan == 1)) { |
799 dest = bitsToFp(qnan, junk); 800 } else if (signal1) { 801 dest = bitsToFp(fpToBits(op1) | qnan, junk); 802 } else if (signal2) { 803 dest = bitsToFp(fpToBits(op2) | qnan, junk); 804 } else if (nan1) { 805 dest = op1; 806 } else if (nan2) { --- 16 unchanged lines hidden (view full) --- 823 __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2) 824 : "m" (op1), "m" (op2)); 825 fpType temp = func(op1, op2); 826 __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp)); 827 if (flush && flushToZero(temp)) { 828 dest = temp; 829 } 830 } | 1007 dest = bitsToFp(qnan, junk); 1008 } else if (signal1) { 1009 dest = bitsToFp(fpToBits(op1) | qnan, junk); 1010 } else if (signal2) { 1011 dest = bitsToFp(fpToBits(op2) | qnan, junk); 1012 } else if (nan1) { 1013 dest = op1; 1014 } else if (nan2) { --- 16 unchanged lines hidden (view full) --- 1031 __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2) 1032 : "m" (op1), "m" (op2)); 1033 fpType temp = func(op1, op2); 1034 __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp)); 1035 if (flush && flushToZero(temp)) { 1036 dest = temp; 1037 } 1038 } |
831 finishVfp(fpscr, state); | 1039 finishVfp(fpscr, state, flush); |
832 return dest; 833} 834 835template 836float FpOp::binaryOp(FPSCR &fpscr, float op1, float op2, 837 float (*func)(float, float), | 1040 return dest; 1041} 1042 1043template 1044float FpOp::binaryOp(FPSCR &fpscr, float op1, float op2, 1045 float (*func)(float, float), |
838 bool flush, uint32_t rMode) const; | 1046 bool flush, bool defaultNan, uint32_t rMode) const; |
839template 840double FpOp::binaryOp(FPSCR &fpscr, double op1, double op2, 841 double (*func)(double, double), | 1047template 1048double FpOp::binaryOp(FPSCR &fpscr, double op1, double op2, 1049 double (*func)(double, double), |
842 bool flush, uint32_t rMode) const; | 1050 bool flush, bool defaultNan, uint32_t rMode) const; |
843 844template <class fpType> 845fpType 846FpOp::unaryOp(FPSCR &fpscr, fpType op1, fpType (*func)(fpType), 847 bool flush, uint32_t rMode) const 848{ 849 const bool single = (sizeof(fpType) == sizeof(float)); 850 fpType junk = 0.0; --- 34 unchanged lines hidden (view full) --- 885 fesetround(FeRoundZero); 886 __asm__ __volatile__ ("" : "=m" (op1) : "m" (op1)); 887 fpType temp = func(op1); 888 __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp)); 889 if (flush && flushToZero(temp)) { 890 dest = temp; 891 } 892 } | 1051 1052template <class fpType> 1053fpType 1054FpOp::unaryOp(FPSCR &fpscr, fpType op1, fpType (*func)(fpType), 1055 bool flush, uint32_t rMode) const 1056{ 1057 const bool single = (sizeof(fpType) == sizeof(float)); 1058 fpType junk = 0.0; --- 34 unchanged lines hidden (view full) --- 1093 fesetround(FeRoundZero); 1094 __asm__ __volatile__ ("" : "=m" (op1) : "m" (op1)); 1095 fpType temp = func(op1); 1096 __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp)); 1097 if (flush && flushToZero(temp)) { 1098 dest = temp; 1099 } 1100 } |
893 finishVfp(fpscr, state); | 1101 finishVfp(fpscr, state, flush); |
894 return dest; 895} 896 897template 898float FpOp::unaryOp(FPSCR &fpscr, float op1, float (*func)(float), 899 bool flush, uint32_t rMode) const; 900template 901double FpOp::unaryOp(FPSCR &fpscr, double op1, double (*func)(double), --- 47 unchanged lines hidden --- | 1102 return dest; 1103} 1104 1105template 1106float FpOp::unaryOp(FPSCR &fpscr, float op1, float (*func)(float), 1107 bool flush, uint32_t rMode) const; 1108template 1109double FpOp::unaryOp(FPSCR &fpscr, double op1, double (*func)(double), --- 47 unchanged lines hidden --- |