Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(789)

Side by Side Diff: src/a64/simulator-a64.cc

Issue 199083005: A64: Fix a few simulation inaccuracies. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/a64/simulator-a64.h ('k') | src/a64/utils-a64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/a64/simulator-a64.h ('k') | src/a64/utils-a64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698