OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 713 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
724 case SXTX: | 724 case SXTX: |
725 break; | 725 break; |
726 default: | 726 default: |
727 UNREACHABLE(); | 727 UNREACHABLE(); |
728 } | 728 } |
729 int64_t mask = (reg_size == kXRegSizeInBits) ? kXRegMask : kWRegMask; | 729 int64_t mask = (reg_size == kXRegSizeInBits) ? kXRegMask : kWRegMask; |
730 return (value << left_shift) & mask; | 730 return (value << left_shift) & mask; |
731 } | 731 } |
732 | 732 |
733 | 733 |
| 734 template<> double Simulator::FPDefaultNaN<double>() const { |
| 735 return kFP64DefaultNaN; |
| 736 } |
| 737 |
| 738 |
| 739 template<> float Simulator::FPDefaultNaN<float>() const { |
| 740 return kFP32DefaultNaN; |
| 741 } |
| 742 |
| 743 |
734 void Simulator::FPCompare(double val0, double val1) { | 744 void Simulator::FPCompare(double val0, double val1) { |
735 AssertSupportedFPCR(); | 745 AssertSupportedFPCR(); |
736 | 746 |
737 // TODO(jbramley): This assumes that the C++ implementation handles | 747 // TODO(jbramley): This assumes that the C++ implementation handles |
738 // comparisons in the way that we expect (as per AssertSupportedFPCR()). | 748 // comparisons in the way that we expect (as per AssertSupportedFPCR()). |
739 if ((std::isnan(val0) != 0) || (std::isnan(val1) != 0)) { | 749 if ((std::isnan(val0) != 0) || (std::isnan(val1) != 0)) { |
740 nzcv().SetRawValue(FPUnorderedFlag); | 750 nzcv().SetRawValue(FPUnorderedFlag); |
741 } else if (val0 < val1) { | 751 } else if (val0 < val1) { |
742 nzcv().SetRawValue(FPLessThanFlag); | 752 nzcv().SetRawValue(FPLessThanFlag); |
743 } else if (val0 > val1) { | 753 } else if (val0 > val1) { |
(...skipping 1349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2093 } else if (value < 0.0) { | 2103 } else if (value < 0.0) { |
2094 return 0; | 2104 return 0; |
2095 } | 2105 } |
2096 return std::isnan(value) ? 0 : static_cast<uint64_t>(value); | 2106 return std::isnan(value) ? 0 : static_cast<uint64_t>(value); |
2097 } | 2107 } |
2098 | 2108 |
2099 | 2109 |
2100 void Simulator::VisitFPCompare(Instruction* instr) { | 2110 void Simulator::VisitFPCompare(Instruction* instr) { |
2101 AssertSupportedFPCR(); | 2111 AssertSupportedFPCR(); |
2102 | 2112 |
2103 unsigned reg_size = instr->FPType() == FP32 ? kSRegSizeInBits | 2113 unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSizeInBits |
2104 : kDRegSizeInBits; | 2114 : kSRegSizeInBits; |
2105 double fn_val = fpreg(reg_size, instr->Rn()); | 2115 double fn_val = fpreg(reg_size, instr->Rn()); |
2106 | 2116 |
2107 switch (instr->Mask(FPCompareMask)) { | 2117 switch (instr->Mask(FPCompareMask)) { |
2108 case FCMP_s: | 2118 case FCMP_s: |
2109 case FCMP_d: FPCompare(fn_val, fpreg(reg_size, instr->Rm())); break; | 2119 case FCMP_d: FPCompare(fn_val, fpreg(reg_size, instr->Rm())); break; |
2110 case FCMP_s_zero: | 2120 case FCMP_s_zero: |
2111 case FCMP_d_zero: FPCompare(fn_val, 0.0); break; | 2121 case FCMP_d_zero: FPCompare(fn_val, 0.0); break; |
2112 default: UNIMPLEMENTED(); | 2122 default: UNIMPLEMENTED(); |
2113 } | 2123 } |
2114 } | 2124 } |
2115 | 2125 |
2116 | 2126 |
2117 void Simulator::VisitFPConditionalCompare(Instruction* instr) { | 2127 void Simulator::VisitFPConditionalCompare(Instruction* instr) { |
2118 AssertSupportedFPCR(); | 2128 AssertSupportedFPCR(); |
2119 | 2129 |
2120 switch (instr->Mask(FPConditionalCompareMask)) { | 2130 switch (instr->Mask(FPConditionalCompareMask)) { |
2121 case FCCMP_s: | 2131 case FCCMP_s: |
2122 case FCCMP_d: { | 2132 case FCCMP_d: { |
2123 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) { | 2133 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) { |
2124 // If the condition passes, set the status flags to the result of | 2134 // If the condition passes, set the status flags to the result of |
2125 // comparing the operands. | 2135 // comparing the operands. |
2126 unsigned reg_size = instr->FPType() == FP32 ? kSRegSizeInBits | 2136 unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSizeInBits |
2127 : kDRegSizeInBits; | 2137 : kSRegSizeInBits; |
2128 FPCompare(fpreg(reg_size, instr->Rn()), fpreg(reg_size, instr->Rm())); | 2138 FPCompare(fpreg(reg_size, instr->Rn()), fpreg(reg_size, instr->Rm())); |
2129 } else { | 2139 } else { |
2130 // If the condition fails, set the status flags to the nzcv immediate. | 2140 // If the condition fails, set the status flags to the nzcv immediate. |
2131 nzcv().SetFlags(instr->Nzcv()); | 2141 nzcv().SetFlags(instr->Nzcv()); |
2132 } | 2142 } |
2133 break; | 2143 break; |
2134 } | 2144 } |
2135 default: UNIMPLEMENTED(); | 2145 default: UNIMPLEMENTED(); |
2136 } | 2146 } |
2137 } | 2147 } |
(...skipping 23 matching lines...) Expand all Loading... |
2161 unsigned fd = instr->Rd(); | 2171 unsigned fd = instr->Rd(); |
2162 unsigned fn = instr->Rn(); | 2172 unsigned fn = instr->Rn(); |
2163 | 2173 |
2164 switch (instr->Mask(FPDataProcessing1SourceMask)) { | 2174 switch (instr->Mask(FPDataProcessing1SourceMask)) { |
2165 case FMOV_s: set_sreg(fd, sreg(fn)); break; | 2175 case FMOV_s: set_sreg(fd, sreg(fn)); break; |
2166 case FMOV_d: set_dreg(fd, dreg(fn)); break; | 2176 case FMOV_d: set_dreg(fd, dreg(fn)); break; |
2167 case FABS_s: set_sreg(fd, std::fabs(sreg(fn))); break; | 2177 case FABS_s: set_sreg(fd, std::fabs(sreg(fn))); break; |
2168 case FABS_d: set_dreg(fd, std::fabs(dreg(fn))); break; | 2178 case FABS_d: set_dreg(fd, std::fabs(dreg(fn))); break; |
2169 case FNEG_s: set_sreg(fd, -sreg(fn)); break; | 2179 case FNEG_s: set_sreg(fd, -sreg(fn)); break; |
2170 case FNEG_d: set_dreg(fd, -dreg(fn)); break; | 2180 case FNEG_d: set_dreg(fd, -dreg(fn)); break; |
2171 case FSQRT_s: set_sreg(fd, std::sqrt(sreg(fn))); break; | 2181 case FSQRT_s: set_sreg(fd, FPSqrt(sreg(fn))); break; |
2172 case FSQRT_d: set_dreg(fd, std::sqrt(dreg(fn))); break; | 2182 case FSQRT_d: set_dreg(fd, FPSqrt(dreg(fn))); break; |
2173 case FRINTA_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieAway)); break; | 2183 case FRINTA_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieAway)); break; |
2174 case FRINTA_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieAway)); break; | 2184 case FRINTA_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieAway)); break; |
2175 case FRINTN_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieEven)); break; | 2185 case FRINTN_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieEven)); break; |
2176 case FRINTN_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieEven)); break; | 2186 case FRINTN_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieEven)); break; |
2177 case FRINTZ_s: set_sreg(fd, FPRoundInt(sreg(fn), FPZero)); break; | 2187 case FRINTZ_s: set_sreg(fd, FPRoundInt(sreg(fn), FPZero)); break; |
2178 case FRINTZ_d: set_dreg(fd, FPRoundInt(dreg(fn), FPZero)); break; | 2188 case FRINTZ_d: set_dreg(fd, FPRoundInt(dreg(fn), FPZero)); break; |
2179 case FCVT_ds: set_dreg(fd, FPToDouble(sreg(fn))); break; | 2189 case FCVT_ds: set_dreg(fd, FPToDouble(sreg(fn))); break; |
2180 case FCVT_sd: set_sreg(fd, FPToFloat(dreg(fn), FPTieEven)); break; | 2190 case FCVT_sd: set_sreg(fd, FPToFloat(dreg(fn), FPTieEven)); break; |
2181 default: UNIMPLEMENTED(); | 2191 default: UNIMPLEMENTED(); |
2182 } | 2192 } |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2421 // 2^exponent. | 2431 // 2^exponent. |
2422 const int highest_significant_bit = 63 - CountLeadingZeros(src, 64); | 2432 const int highest_significant_bit = 63 - CountLeadingZeros(src, 64); |
2423 const int32_t exponent = highest_significant_bit - fbits; | 2433 const int32_t exponent = highest_significant_bit - fbits; |
2424 | 2434 |
2425 return FPRoundToFloat(0, exponent, src, round); | 2435 return FPRoundToFloat(0, exponent, src, round); |
2426 } | 2436 } |
2427 | 2437 |
2428 | 2438 |
2429 double Simulator::FPRoundInt(double value, FPRounding round_mode) { | 2439 double Simulator::FPRoundInt(double value, FPRounding round_mode) { |
2430 if ((value == 0.0) || (value == kFP64PositiveInfinity) || | 2440 if ((value == 0.0) || (value == kFP64PositiveInfinity) || |
2431 (value == kFP64NegativeInfinity) || std::isnan(value)) { | 2441 (value == kFP64NegativeInfinity)) { |
2432 return value; | 2442 return value; |
| 2443 } else if (std::isnan(value)) { |
| 2444 return FPProcessNaN(value); |
2433 } | 2445 } |
2434 | 2446 |
2435 double int_result = floor(value); | 2447 double int_result = floor(value); |
2436 double error = value - int_result; | 2448 double error = value - int_result; |
2437 switch (round_mode) { | 2449 switch (round_mode) { |
2438 case FPTieAway: { | 2450 case FPTieAway: { |
2439 // If the error is greater than 0.5, or is equal to 0.5 and the integer | 2451 // If the error is greater than 0.5, or is equal to 0.5 and the integer |
2440 // result is positive, round up. | 2452 // result is positive, round up. |
2441 if ((error > 0.5) || ((error == 0.5) && (int_result >= 0.0))) { | 2453 if ((error > 0.5) || ((error == 0.5) && (int_result >= 0.0))) { |
2442 int_result++; | 2454 int_result++; |
(...skipping 23 matching lines...) Expand all Loading... |
2466 } | 2478 } |
2467 default: UNIMPLEMENTED(); | 2479 default: UNIMPLEMENTED(); |
2468 } | 2480 } |
2469 return int_result; | 2481 return int_result; |
2470 } | 2482 } |
2471 | 2483 |
2472 | 2484 |
2473 double Simulator::FPToDouble(float value) { | 2485 double Simulator::FPToDouble(float value) { |
2474 switch (std::fpclassify(value)) { | 2486 switch (std::fpclassify(value)) { |
2475 case FP_NAN: { | 2487 case FP_NAN: { |
2476 // Convert NaNs as the processor would, assuming that FPCR.DN (default | 2488 if (DN()) return kFP64DefaultNaN; |
2477 // NaN) is not set: | 2489 |
| 2490 // Convert NaNs as the processor would: |
2478 // - The sign is propagated. | 2491 // - The sign is propagated. |
2479 // - The payload (mantissa) is transferred entirely, except that the top | 2492 // - The payload (mantissa) is transferred entirely, except that the top |
2480 // bit is forced to '1', making the result a quiet NaN. The unused | 2493 // bit is forced to '1', making the result a quiet NaN. The unused |
2481 // (low-order) payload bits are set to 0. | 2494 // (low-order) payload bits are set to 0. |
2482 uint32_t raw = float_to_rawbits(value); | 2495 uint32_t raw = float_to_rawbits(value); |
2483 | 2496 |
2484 uint64_t sign = raw >> 31; | 2497 uint64_t sign = raw >> 31; |
2485 uint64_t exponent = (1 << 11) - 1; | 2498 uint64_t exponent = (1 << 11) - 1; |
2486 uint64_t payload = unsigned_bitextract_64(21, 0, raw); | 2499 uint64_t payload = unsigned_bitextract_64(21, 0, raw); |
2487 payload <<= (52 - 23); // The unused low-order bits should be 0. | 2500 payload <<= (52 - 23); // The unused low-order bits should be 0. |
(...skipping 18 matching lines...) Expand all Loading... |
2506 } | 2519 } |
2507 | 2520 |
2508 | 2521 |
2509 float Simulator::FPToFloat(double value, FPRounding round_mode) { | 2522 float Simulator::FPToFloat(double value, FPRounding round_mode) { |
2510 // Only the FPTieEven rounding mode is implemented. | 2523 // Only the FPTieEven rounding mode is implemented. |
2511 ASSERT(round_mode == FPTieEven); | 2524 ASSERT(round_mode == FPTieEven); |
2512 USE(round_mode); | 2525 USE(round_mode); |
2513 | 2526 |
2514 switch (std::fpclassify(value)) { | 2527 switch (std::fpclassify(value)) { |
2515 case FP_NAN: { | 2528 case FP_NAN: { |
2516 // Convert NaNs as the processor would, assuming that FPCR.DN (default | 2529 if (DN()) return kFP32DefaultNaN; |
2517 // NaN) is not set: | 2530 |
| 2531 // Convert NaNs as the processor would: |
2518 // - The sign is propagated. | 2532 // - The sign is propagated. |
2519 // - The payload (mantissa) is transferred as much as possible, except | 2533 // - The payload (mantissa) is transferred as much as possible, except |
2520 // that the top bit is forced to '1', making the result a quiet NaN. | 2534 // that the top bit is forced to '1', making the result a quiet NaN. |
2521 uint64_t raw = double_to_rawbits(value); | 2535 uint64_t raw = double_to_rawbits(value); |
2522 | 2536 |
2523 uint32_t sign = raw >> 63; | 2537 uint32_t sign = raw >> 63; |
2524 uint32_t exponent = (1 << 8) - 1; | 2538 uint32_t exponent = (1 << 8) - 1; |
2525 uint32_t payload = unsigned_bitextract_64(50, 52 - 23, raw); | 2539 uint32_t payload = unsigned_bitextract_64(50, 52 - 23, raw); |
2526 payload |= (1 << 22); // Force a quiet NaN. | 2540 payload |= (1 << 22); // Force a quiet NaN. |
2527 | 2541 |
(...skipping 30 matching lines...) Expand all Loading... |
2558 } | 2572 } |
2559 | 2573 |
2560 | 2574 |
2561 void Simulator::VisitFPDataProcessing2Source(Instruction* instr) { | 2575 void Simulator::VisitFPDataProcessing2Source(Instruction* instr) { |
2562 AssertSupportedFPCR(); | 2576 AssertSupportedFPCR(); |
2563 | 2577 |
2564 unsigned fd = instr->Rd(); | 2578 unsigned fd = instr->Rd(); |
2565 unsigned fn = instr->Rn(); | 2579 unsigned fn = instr->Rn(); |
2566 unsigned fm = instr->Rm(); | 2580 unsigned fm = instr->Rm(); |
2567 | 2581 |
| 2582 // Fmaxnm and Fminnm have special NaN handling. |
2568 switch (instr->Mask(FPDataProcessing2SourceMask)) { | 2583 switch (instr->Mask(FPDataProcessing2SourceMask)) { |
2569 case FADD_s: set_sreg(fd, sreg(fn) + sreg(fm)); break; | 2584 case FMAXNM_s: set_sreg(fd, FPMaxNM(sreg(fn), sreg(fm))); return; |
2570 case FADD_d: set_dreg(fd, dreg(fn) + dreg(fm)); break; | 2585 case FMAXNM_d: set_dreg(fd, FPMaxNM(dreg(fn), dreg(fm))); return; |
2571 case FSUB_s: set_sreg(fd, sreg(fn) - sreg(fm)); break; | 2586 case FMINNM_s: set_sreg(fd, FPMinNM(sreg(fn), sreg(fm))); return; |
2572 case FSUB_d: set_dreg(fd, dreg(fn) - dreg(fm)); break; | 2587 case FMINNM_d: set_dreg(fd, FPMinNM(dreg(fn), dreg(fm))); return; |
2573 case FMUL_s: set_sreg(fd, sreg(fn) * sreg(fm)); break; | 2588 default: |
2574 case FMUL_d: set_dreg(fd, dreg(fn) * dreg(fm)); break; | 2589 break; // Fall through. |
2575 case FDIV_s: set_sreg(fd, sreg(fn) / sreg(fm)); break; | 2590 } |
2576 case FDIV_d: set_dreg(fd, dreg(fn) / dreg(fm)); break; | 2591 |
| 2592 if (FPProcessNaNs(instr)) return; |
| 2593 |
| 2594 switch (instr->Mask(FPDataProcessing2SourceMask)) { |
| 2595 case FADD_s: set_sreg(fd, FPAdd(sreg(fn), sreg(fm))); break; |
| 2596 case FADD_d: set_dreg(fd, FPAdd(dreg(fn), dreg(fm))); break; |
| 2597 case FSUB_s: set_sreg(fd, FPSub(sreg(fn), sreg(fm))); break; |
| 2598 case FSUB_d: set_dreg(fd, FPSub(dreg(fn), dreg(fm))); break; |
| 2599 case FMUL_s: set_sreg(fd, FPMul(sreg(fn), sreg(fm))); break; |
| 2600 case FMUL_d: set_dreg(fd, FPMul(dreg(fn), dreg(fm))); break; |
| 2601 case FDIV_s: set_sreg(fd, FPDiv(sreg(fn), sreg(fm))); break; |
| 2602 case FDIV_d: set_dreg(fd, FPDiv(dreg(fn), dreg(fm))); break; |
2577 case FMAX_s: set_sreg(fd, FPMax(sreg(fn), sreg(fm))); break; | 2603 case FMAX_s: set_sreg(fd, FPMax(sreg(fn), sreg(fm))); break; |
2578 case FMAX_d: set_dreg(fd, FPMax(dreg(fn), dreg(fm))); break; | 2604 case FMAX_d: set_dreg(fd, FPMax(dreg(fn), dreg(fm))); break; |
2579 case FMIN_s: set_sreg(fd, FPMin(sreg(fn), sreg(fm))); break; | 2605 case FMIN_s: set_sreg(fd, FPMin(sreg(fn), sreg(fm))); break; |
2580 case FMIN_d: set_dreg(fd, FPMin(dreg(fn), dreg(fm))); break; | 2606 case FMIN_d: set_dreg(fd, FPMin(dreg(fn), dreg(fm))); break; |
2581 case FMAXNM_s: set_sreg(fd, FPMaxNM(sreg(fn), sreg(fm))); break; | 2607 case FMAXNM_s: |
2582 case FMAXNM_d: set_dreg(fd, FPMaxNM(dreg(fn), dreg(fm))); break; | 2608 case FMAXNM_d: |
2583 case FMINNM_s: set_sreg(fd, FPMinNM(sreg(fn), sreg(fm))); break; | 2609 case FMINNM_s: |
2584 case FMINNM_d: set_dreg(fd, FPMinNM(dreg(fn), dreg(fm))); break; | 2610 case FMINNM_d: |
| 2611 // These were handled before the standard FPProcessNaNs() stage. |
| 2612 UNREACHABLE(); |
2585 default: UNIMPLEMENTED(); | 2613 default: UNIMPLEMENTED(); |
2586 } | 2614 } |
2587 } | 2615 } |
2588 | 2616 |
2589 | 2617 |
2590 void Simulator::VisitFPDataProcessing3Source(Instruction* instr) { | 2618 void Simulator::VisitFPDataProcessing3Source(Instruction* instr) { |
2591 AssertSupportedFPCR(); | 2619 AssertSupportedFPCR(); |
2592 | 2620 |
2593 unsigned fd = instr->Rd(); | 2621 unsigned fd = instr->Rd(); |
2594 unsigned fn = instr->Rn(); | 2622 unsigned fn = instr->Rn(); |
2595 unsigned fm = instr->Rm(); | 2623 unsigned fm = instr->Rm(); |
2596 unsigned fa = instr->Ra(); | 2624 unsigned fa = instr->Ra(); |
2597 | 2625 |
2598 // The C99 (and C++11) fma function performs a fused multiply-accumulate. | 2626 // The C99 (and C++11) fma function performs a fused multiply-accumulate. |
2599 switch (instr->Mask(FPDataProcessing3SourceMask)) { | 2627 switch (instr->Mask(FPDataProcessing3SourceMask)) { |
2600 // fd = fa +/- (fn * fm) | 2628 // fd = fa +/- (fn * fm) |
2601 case FMADD_s: set_sreg(fd, fmaf(sreg(fn), sreg(fm), sreg(fa))); break; | 2629 case FMADD_s: set_sreg(fd, FPMulAdd(sreg(fa), sreg(fn), sreg(fm))); break; |
2602 case FMSUB_s: set_sreg(fd, fmaf(-sreg(fn), sreg(fm), sreg(fa))); break; | 2630 case FMSUB_s: set_sreg(fd, FPMulAdd(sreg(fa), -sreg(fn), sreg(fm))); break; |
2603 case FMADD_d: set_dreg(fd, fma(dreg(fn), dreg(fm), dreg(fa))); break; | 2631 case FMADD_d: set_dreg(fd, FPMulAdd(dreg(fa), dreg(fn), dreg(fm))); break; |
2604 case FMSUB_d: set_dreg(fd, fma(-dreg(fn), dreg(fm), dreg(fa))); break; | 2632 case FMSUB_d: set_dreg(fd, FPMulAdd(dreg(fa), -dreg(fn), dreg(fm))); break; |
2605 // Variants of the above where the result is negated. | 2633 // Negated variants of the above. |
2606 case FNMADD_s: set_sreg(fd, -fmaf(sreg(fn), sreg(fm), sreg(fa))); break; | 2634 case FNMADD_s: |
2607 case FNMSUB_s: set_sreg(fd, -fmaf(-sreg(fn), sreg(fm), sreg(fa))); break; | 2635 set_sreg(fd, FPMulAdd(-sreg(fa), -sreg(fn), sreg(fm))); |
2608 case FNMADD_d: set_dreg(fd, -fma(dreg(fn), dreg(fm), dreg(fa))); break; | 2636 break; |
2609 case FNMSUB_d: set_dreg(fd, -fma(-dreg(fn), dreg(fm), dreg(fa))); break; | 2637 case FNMSUB_s: |
| 2638 set_sreg(fd, FPMulAdd(-sreg(fa), sreg(fn), sreg(fm))); |
| 2639 break; |
| 2640 case FNMADD_d: |
| 2641 set_dreg(fd, FPMulAdd(-dreg(fa), -dreg(fn), dreg(fm))); |
| 2642 break; |
| 2643 case FNMSUB_d: |
| 2644 set_dreg(fd, FPMulAdd(-dreg(fa), dreg(fn), dreg(fm))); |
| 2645 break; |
2610 default: UNIMPLEMENTED(); | 2646 default: UNIMPLEMENTED(); |
2611 } | 2647 } |
2612 } | 2648 } |
2613 | 2649 |
2614 | 2650 |
2615 template <typename T> | 2651 template <typename T> |
| 2652 T Simulator::FPAdd(T op1, T op2) { |
| 2653 // NaNs should be handled elsewhere. |
| 2654 ASSERT(!std::isnan(op1) && !std::isnan(op2)); |
| 2655 |
| 2656 if (isinf(op1) && isinf(op2) && (op1 != op2)) { |
| 2657 // inf + -inf returns the default NaN. |
| 2658 return FPDefaultNaN<T>(); |
| 2659 } else { |
| 2660 // Other cases should be handled by standard arithmetic. |
| 2661 return op1 + op2; |
| 2662 } |
| 2663 } |
| 2664 |
| 2665 |
| 2666 template <typename T> |
| 2667 T Simulator::FPDiv(T op1, T op2) { |
| 2668 // NaNs should be handled elsewhere. |
| 2669 ASSERT(!std::isnan(op1) && !std::isnan(op2)); |
| 2670 |
| 2671 if ((isinf(op1) && isinf(op2)) || ((op1 == 0.0) && (op2 == 0.0))) { |
| 2672 // inf / inf and 0.0 / 0.0 return the default NaN. |
| 2673 return FPDefaultNaN<T>(); |
| 2674 } else { |
| 2675 // Other cases should be handled by standard arithmetic. |
| 2676 return op1 / op2; |
| 2677 } |
| 2678 } |
| 2679 |
| 2680 |
| 2681 template <typename T> |
2616 T Simulator::FPMax(T a, T b) { | 2682 T Simulator::FPMax(T a, T b) { |
2617 if (IsSignallingNaN(a)) { | 2683 // NaNs should be handled elsewhere. |
2618 return a; | 2684 ASSERT(!std::isnan(a) && !std::isnan(b)); |
2619 } else if (IsSignallingNaN(b)) { | |
2620 return b; | |
2621 } else if (std::isnan(a)) { | |
2622 ASSERT(IsQuietNaN(a)); | |
2623 return a; | |
2624 } else if (std::isnan(b)) { | |
2625 ASSERT(IsQuietNaN(b)); | |
2626 return b; | |
2627 } | |
2628 | 2685 |
2629 if ((a == 0.0) && (b == 0.0) && | 2686 if ((a == 0.0) && (b == 0.0) && |
2630 (copysign(1.0, a) != copysign(1.0, b))) { | 2687 (copysign(1.0, a) != copysign(1.0, b))) { |
2631 // a and b are zero, and the sign differs: return +0.0. | 2688 // a and b are zero, and the sign differs: return +0.0. |
2632 return 0.0; | 2689 return 0.0; |
2633 } else { | 2690 } else { |
2634 return (a > b) ? a : b; | 2691 return (a > b) ? a : b; |
2635 } | 2692 } |
2636 } | 2693 } |
2637 | 2694 |
2638 | 2695 |
2639 template <typename T> | 2696 template <typename T> |
2640 T Simulator::FPMaxNM(T a, T b) { | 2697 T Simulator::FPMaxNM(T a, T b) { |
2641 if (IsQuietNaN(a) && !IsQuietNaN(b)) { | 2698 if (IsQuietNaN(a) && !IsQuietNaN(b)) { |
2642 a = kFP64NegativeInfinity; | 2699 a = kFP64NegativeInfinity; |
2643 } else if (!IsQuietNaN(a) && IsQuietNaN(b)) { | 2700 } else if (!IsQuietNaN(a) && IsQuietNaN(b)) { |
2644 b = kFP64NegativeInfinity; | 2701 b = kFP64NegativeInfinity; |
2645 } | 2702 } |
2646 return FPMax(a, b); | 2703 |
| 2704 T result = FPProcessNaNs(a, b); |
| 2705 return std::isnan(result) ? result : FPMax(a, b); |
2647 } | 2706 } |
2648 | 2707 |
2649 template <typename T> | 2708 template <typename T> |
2650 T Simulator::FPMin(T a, T b) { | 2709 T Simulator::FPMin(T a, T b) { |
2651 if (IsSignallingNaN(a)) { | 2710 // NaNs should be handled elsewhere. |
2652 return a; | 2711 ASSERT(!isnan(a) && !isnan(b)); |
2653 } else if (IsSignallingNaN(b)) { | |
2654 return b; | |
2655 } else if (std::isnan(a)) { | |
2656 ASSERT(IsQuietNaN(a)); | |
2657 return a; | |
2658 } else if (std::isnan(b)) { | |
2659 ASSERT(IsQuietNaN(b)); | |
2660 return b; | |
2661 } | |
2662 | 2712 |
2663 if ((a == 0.0) && (b == 0.0) && | 2713 if ((a == 0.0) && (b == 0.0) && |
2664 (copysign(1.0, a) != copysign(1.0, b))) { | 2714 (copysign(1.0, a) != copysign(1.0, b))) { |
2665 // a and b are zero, and the sign differs: return -0.0. | 2715 // a and b are zero, and the sign differs: return -0.0. |
2666 return -0.0; | 2716 return -0.0; |
2667 } else { | 2717 } else { |
2668 return (a < b) ? a : b; | 2718 return (a < b) ? a : b; |
2669 } | 2719 } |
2670 } | 2720 } |
2671 | 2721 |
2672 | 2722 |
2673 template <typename T> | 2723 template <typename T> |
2674 T Simulator::FPMinNM(T a, T b) { | 2724 T Simulator::FPMinNM(T a, T b) { |
2675 if (IsQuietNaN(a) && !IsQuietNaN(b)) { | 2725 if (IsQuietNaN(a) && !IsQuietNaN(b)) { |
2676 a = kFP64PositiveInfinity; | 2726 a = kFP64PositiveInfinity; |
2677 } else if (!IsQuietNaN(a) && IsQuietNaN(b)) { | 2727 } else if (!IsQuietNaN(a) && IsQuietNaN(b)) { |
2678 b = kFP64PositiveInfinity; | 2728 b = kFP64PositiveInfinity; |
2679 } | 2729 } |
2680 return FPMin(a, b); | 2730 |
| 2731 T result = FPProcessNaNs(a, b); |
| 2732 return isnan(result) ? result : FPMin(a, b); |
2681 } | 2733 } |
2682 | 2734 |
2683 | 2735 |
| 2736 template <typename T> |
| 2737 T Simulator::FPMul(T op1, T op2) { |
| 2738 // NaNs should be handled elsewhere. |
| 2739 ASSERT(!std::isnan(op1) && !std::isnan(op2)); |
| 2740 |
| 2741 if ((isinf(op1) && (op2 == 0.0)) || (isinf(op2) && (op1 == 0.0))) { |
| 2742 // inf * 0.0 returns the default NaN. |
| 2743 return FPDefaultNaN<T>(); |
| 2744 } else { |
| 2745 // Other cases should be handled by standard arithmetic. |
| 2746 return op1 * op2; |
| 2747 } |
| 2748 } |
| 2749 |
| 2750 |
| 2751 template<typename T> |
| 2752 T Simulator::FPMulAdd(T a, T op1, T op2) { |
| 2753 T result = FPProcessNaNs3(a, op1, op2); |
| 2754 |
| 2755 T sign_a = copysign(1.0, a); |
| 2756 T sign_prod = copysign(1.0, op1) * copysign(1.0, op2); |
| 2757 bool isinf_prod = std::isinf(op1) || std::isinf(op2); |
| 2758 bool operation_generates_nan = |
| 2759 (std::isinf(op1) && (op2 == 0.0)) || // inf * 0.0 |
| 2760 (std::isinf(op2) && (op1 == 0.0)) || // 0.0 * inf |
| 2761 (std::isinf(a) && isinf_prod && (sign_a != sign_prod)); // inf - inf |
| 2762 |
| 2763 if (std::isnan(result)) { |
| 2764 // Generated NaNs override quiet NaNs propagated from a. |
| 2765 if (operation_generates_nan && IsQuietNaN(a)) { |
| 2766 return FPDefaultNaN<T>(); |
| 2767 } else { |
| 2768 return result; |
| 2769 } |
| 2770 } |
| 2771 |
| 2772 // If the operation would produce a NaN, return the default NaN. |
| 2773 if (operation_generates_nan) { |
| 2774 return FPDefaultNaN<T>(); |
| 2775 } |
| 2776 |
| 2777 // Work around broken fma implementations for exact zero results: The sign of |
| 2778 // exact 0.0 results is positive unless both a and op1 * op2 are negative. |
| 2779 if (((op1 == 0.0) || (op2 == 0.0)) && (a == 0.0)) { |
| 2780 return ((sign_a < 0) && (sign_prod < 0)) ? -0.0 : 0.0; |
| 2781 } |
| 2782 |
| 2783 result = FusedMultiplyAdd(op1, op2, a); |
| 2784 ASSERT(!std::isnan(result)); |
| 2785 |
| 2786 // Work around broken fma implementations for rounded zero results: If a is |
| 2787 // 0.0, the sign of the result is the sign of op1 * op2 before rounding. |
| 2788 if ((a == 0.0) && (result == 0.0)) { |
| 2789 return copysign(0.0, sign_prod); |
| 2790 } |
| 2791 |
| 2792 return result; |
| 2793 } |
| 2794 |
| 2795 |
| 2796 template <typename T> |
| 2797 T Simulator::FPSqrt(T op) { |
| 2798 if (std::isnan(op)) { |
| 2799 return FPProcessNaN(op); |
| 2800 } else if (op < 0.0) { |
| 2801 return FPDefaultNaN<T>(); |
| 2802 } else { |
| 2803 return std::sqrt(op); |
| 2804 } |
| 2805 } |
| 2806 |
| 2807 |
| 2808 template <typename T> |
| 2809 T Simulator::FPSub(T op1, T op2) { |
| 2810 // NaNs should be handled elsewhere. |
| 2811 ASSERT(!std::isnan(op1) && !std::isnan(op2)); |
| 2812 |
| 2813 if (isinf(op1) && isinf(op2) && (op1 == op2)) { |
| 2814 // inf - inf returns the default NaN. |
| 2815 return FPDefaultNaN<T>(); |
| 2816 } else { |
| 2817 // Other cases should be handled by standard arithmetic. |
| 2818 return op1 - op2; |
| 2819 } |
| 2820 } |
| 2821 |
| 2822 |
| 2823 template <typename T> |
| 2824 T Simulator::FPProcessNaN(T op) { |
| 2825 ASSERT(std::isnan(op)); |
| 2826 return DN() ? FPDefaultNaN<T>() : ToQuietNaN(op); |
| 2827 } |
| 2828 |
| 2829 |
| 2830 template <typename T> |
| 2831 T Simulator::FPProcessNaNs(T op1, T op2) { |
| 2832 if (IsSignallingNaN(op1)) { |
| 2833 return FPProcessNaN(op1); |
| 2834 } else if (IsSignallingNaN(op2)) { |
| 2835 return FPProcessNaN(op2); |
| 2836 } else if (std::isnan(op1)) { |
| 2837 ASSERT(IsQuietNaN(op1)); |
| 2838 return FPProcessNaN(op1); |
| 2839 } else if (std::isnan(op2)) { |
| 2840 ASSERT(IsQuietNaN(op2)); |
| 2841 return FPProcessNaN(op2); |
| 2842 } else { |
| 2843 return 0.0; |
| 2844 } |
| 2845 } |
| 2846 |
| 2847 |
| 2848 template <typename T> |
| 2849 T Simulator::FPProcessNaNs3(T op1, T op2, T op3) { |
| 2850 if (IsSignallingNaN(op1)) { |
| 2851 return FPProcessNaN(op1); |
| 2852 } else if (IsSignallingNaN(op2)) { |
| 2853 return FPProcessNaN(op2); |
| 2854 } else if (IsSignallingNaN(op3)) { |
| 2855 return FPProcessNaN(op3); |
| 2856 } else if (std::isnan(op1)) { |
| 2857 ASSERT(IsQuietNaN(op1)); |
| 2858 return FPProcessNaN(op1); |
| 2859 } else if (std::isnan(op2)) { |
| 2860 ASSERT(IsQuietNaN(op2)); |
| 2861 return FPProcessNaN(op2); |
| 2862 } else if (std::isnan(op3)) { |
| 2863 ASSERT(IsQuietNaN(op3)); |
| 2864 return FPProcessNaN(op3); |
| 2865 } else { |
| 2866 return 0.0; |
| 2867 } |
| 2868 } |
| 2869 |
| 2870 |
| 2871 bool Simulator::FPProcessNaNs(Instruction* instr) { |
| 2872 unsigned fd = instr->Rd(); |
| 2873 unsigned fn = instr->Rn(); |
| 2874 unsigned fm = instr->Rm(); |
| 2875 bool done = false; |
| 2876 |
| 2877 if (instr->Mask(FP64) == FP64) { |
| 2878 double result = FPProcessNaNs(dreg(fn), dreg(fm)); |
| 2879 if (std::isnan(result)) { |
| 2880 set_dreg(fd, result); |
| 2881 done = true; |
| 2882 } |
| 2883 } else { |
| 2884 float result = FPProcessNaNs(sreg(fn), sreg(fm)); |
| 2885 if (std::isnan(result)) { |
| 2886 set_sreg(fd, result); |
| 2887 done = true; |
| 2888 } |
| 2889 } |
| 2890 |
| 2891 return done; |
| 2892 } |
| 2893 |
| 2894 |
2684 void Simulator::VisitSystem(Instruction* instr) { | 2895 void Simulator::VisitSystem(Instruction* instr) { |
2685 // Some system instructions hijack their Op and Cp fields to represent a | 2896 // Some system instructions hijack their Op and Cp fields to represent a |
2686 // range of immediates instead of indicating a different instruction. This | 2897 // range of immediates instead of indicating a different instruction. This |
2687 // makes the decoding tricky. | 2898 // makes the decoding tricky. |
2688 if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) { | 2899 if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) { |
2689 switch (instr->Mask(SystemSysRegMask)) { | 2900 switch (instr->Mask(SystemSysRegMask)) { |
2690 case MRS: { | 2901 case MRS: { |
2691 switch (instr->ImmSystemRegister()) { | 2902 switch (instr->ImmSystemRegister()) { |
2692 case NZCV: set_xreg(instr->Rt(), nzcv().RawValue()); break; | 2903 case NZCV: set_xreg(instr->Rt(), nzcv().RawValue()); break; |
2693 case FPCR: set_xreg(instr->Rt(), fpcr().RawValue()); break; | 2904 case FPCR: set_xreg(instr->Rt(), fpcr().RawValue()); break; |
(...skipping 756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3450 default: | 3661 default: |
3451 UNIMPLEMENTED(); | 3662 UNIMPLEMENTED(); |
3452 } | 3663 } |
3453 } | 3664 } |
3454 | 3665 |
3455 #endif // USE_SIMULATOR | 3666 #endif // USE_SIMULATOR |
3456 | 3667 |
3457 } } // namespace v8::internal | 3668 } } // namespace v8::internal |
3458 | 3669 |
3459 #endif // V8_TARGET_ARCH_A64 | 3670 #endif // V8_TARGET_ARCH_A64 |
OLD | NEW |