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 |
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 |
134finishVfp(FPSCR &fpscr, VfpSavedState state, bool flush) |
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 } |
151 if ((exceptions & FeInexact) && !(underflow && flush)) { |
152 fpscr.ixc = 1; 153 } 154 fesetround(state); 155} 156 157template <class fpType> 158fpType |
159fixDest(bool flush, bool defaultNan, fpType val, fpType 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); |
167 if (!nan || defaultNan) { |
168 val = bitsToFp(qnan, junk); 169 } else if (nan) { 170 val = bitsToFp(fpToBits(op1) | qnan, junk); 171 } |
172 } else if (fpClass == FP_SUBNORMAL && flush == 1) { |
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 |
183float fixDest<float>(bool flush, bool defaultNan, float val, float op1); |
184template |
185double fixDest<double>(bool flush, bool defaultNan, double val, double op1); |
186 187template <class fpType> 188fpType |
189fixDest(bool flush, bool defaultNan, fpType val, fpType op1, fpType op2) |
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); |
200 if ((!nan1 && !nan2) || defaultNan) { |
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 } |
211 } else if (fpClass == FP_SUBNORMAL && flush) { |
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 |
222float fixDest<float>(bool flush, bool defaultNan, 223 float val, float op1, float op2); |
224template |
225double fixDest<double>(bool flush, bool defaultNan, 226 double val, double op1, double op2); |
227 228template <class fpType> 229fpType |
230fixDivDest(bool flush, bool defaultNan, fpType val, fpType op1, fpType op2) |
231{ |
232 fpType mid = fixDest(flush, defaultNan, val, op1, op2); |
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); |
247 if (flush) { |
248 feclearexcept(FeInexact); 249 mid = temp; 250 } 251 } 252 __asm__ __volatile__("" :: "m" (temp)); 253 } 254 return mid; 255} 256 257template |
258float fixDivDest<float>(bool flush, bool defaultNan, 259 float val, float op1, float op2); |
260template |
261double fixDivDest<double>(bool flush, bool defaultNan, 262 double val, double op1, double op2); |
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 } |
276 float mid = fixDest(fpscr.fz, fpscr.dn, (float)val, op1); |
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 } |
312 double mid = fixDest(fpscr.fz, fpscr.dn, (double)val, op1); |
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 |
332uint16_t 333vcvtFpSFpH(FPSCR &fpscr, bool flush, bool defaultNan, 334 uint32_t rMode, bool ahp, float op) |
335{ |
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 } |
351 if (ahp) { |
352 mantissa = 0; 353 exponent = 0; 354 fpscr.ioc = 1; |
355 } else if (defaultNan) { |
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; |
366 if (ahp) { |
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. |
384 assert(!flush); |
385 386 // Check for underflow 387 if (inexact || fpscr.ufe) 388 fpscr.ufc = 1; 389 390 // Handle rounding. |
391 unsigned mode = rMode; |
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. |
436 unsigned mode = rMode; |
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 |
452 if (ahp) { |
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); |
488 return result; |
489} 490 491float |
492vcvtFpHFpS(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op) |
493{ 494 float junk = 0.0; |
495 // Extract the bitfields. |
496 bool neg = bits(op, 15); 497 uint32_t exponent = bits(op, 14, 10); 498 uint32_t mantissa = bits(op, 9, 0); |
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); |
510 } else if (exponent == 0x1f && !ahp) { |
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 } |
521 if (defaultNan) { |
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 |
634vfpUFixedToFpS(bool flush, bool defaultNan, 635 uint32_t val, bool half, uint8_t imm) |
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)); |
644 return fixDivDest(flush, defaultNan, val / scale, (float)val, scale); |
645} 646 647float |
648vfpSFixedToFpS(bool flush, bool defaultNan, 649 int32_t val, bool half, uint8_t imm) |
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)); |
658 return fixDivDest(flush, defaultNan, val / scale, (float)val, scale); |
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 |
755vfpUFixedToFpD(bool flush, bool defaultNan, 756 uint32_t val, bool half, uint8_t imm) |
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)); |
765 return fixDivDest(flush, defaultNan, val / scale, (double)val, scale); |
766} 767 768double |
769vfpSFixedToFpD(bool flush, bool defaultNan, 770 int32_t val, bool half, uint8_t imm) |
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)); |
779 return fixDivDest(flush, defaultNan, val / scale, (double)val, scale); |
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 |
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 |
981FpOp::binaryOp(FPSCR &fpscr, fpType op1, fpType op2, 982 fpType (*func)(fpType, fpType), |
983 bool flush, bool defaultNan, uint32_t rMode) const |
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); |
1006 if ((!nan1 && !nan2) || (defaultNan == 1)) { |
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 } |
1039 finishVfp(fpscr, state, flush); |
1040 return dest; 1041} 1042 1043template 1044float FpOp::binaryOp(FPSCR &fpscr, float op1, float op2, 1045 float (*func)(float, float), |
1046 bool flush, bool defaultNan, uint32_t rMode) const; |
1047template 1048double FpOp::binaryOp(FPSCR &fpscr, double op1, double op2, 1049 double (*func)(double, double), |
1050 bool flush, bool defaultNan, uint32_t rMode) const; |
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 } |
1101 finishVfp(fpscr, state, flush); |
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 --- |