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

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

Issue 2184843002: MIPS: Add NaN handling to floating point operators in simulators. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebased Created 4 years, 3 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
« no previous file with comments | « no previous file | src/mips64/simulator-mips64.cc » ('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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <limits.h> 5 #include <limits.h>
6 #include <stdarg.h> 6 #include <stdarg.h>
7 #include <stdlib.h> 7 #include <stdlib.h>
8 #include <cmath> 8 #include <cmath>
9 9
10 #if V8_TARGET_ARCH_MIPS 10 #if V8_TARGET_ARCH_MIPS
(...skipping 2348 matching lines...) Expand 10 before | Expand all | Expand 10 after
2359 result = a; 2359 result = a;
2360 } else if (FPAbs(b) > FPAbs(a)) { 2360 } else if (FPAbs(b) > FPAbs(a)) {
2361 result = b; 2361 result = b;
2362 } else { 2362 } else {
2363 result = a > b ? a : b; 2363 result = a > b ? a : b;
2364 } 2364 }
2365 } 2365 }
2366 return result; 2366 return result;
2367 } 2367 }
2368 2368
2369 enum class KeepSign : bool { no = false, yes };
2370
2371 template <typename T>
2372 T FPUCanonalizeNaNArg(T result, T arg, KeepSign keepSign = KeepSign::no);
2373
2374 template <>
2375 double FPUCanonalizeNaNArg(double result, double arg, KeepSign keepSign) {
2376 DCHECK(std::isnan(arg));
2377 double qNaN = std::numeric_limits<double>::quiet_NaN();
2378 if (keepSign == KeepSign::yes) {
2379 uint64_t resBits = bit_cast<uint64_t>(result);
2380 return resBits & Double::kSignMask ? -qNaN : qNaN;
ivica.bogosavljevic 2016/09/19 08:41:18 There is a more portable way of doing this: use s
balazs.kilvady 2016/09/20 08:28:39 Thanks for pointing it out. Done.
2381 }
2382 return qNaN;
2383 }
2384
2385 template <>
2386 float FPUCanonalizeNaNArg(float result, float arg, KeepSign keepSign) {
2387 DCHECK(std::isnan(arg));
2388 float qNaN = std::numeric_limits<float>::quiet_NaN();
2389 if (keepSign == KeepSign::yes) {
2390 uint32_t resBits = bit_cast<uint32_t>(result);
2391 return resBits & kBinary32SignMask ? -qNaN : qNaN;
2392 }
2393 return qNaN;
2394 }
2395
2396 template <typename T>
2397 T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first) {
2398 if (std::isnan(first)) {
2399 return FPUCanonalizeNaNArg(result, first, keepSign);
2400 }
2401 return result;
2402 }
2403
2404 template <typename T, typename... Args>
2405 T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first, Args... args) {
2406 if (std::isnan(first)) {
2407 return FPUCanonalizeNaNArg(result, first, keepSign);
2408 }
2409 return FPUCanonalizeNaNArgs(result, keepSign, args...);
2410 }
2411
2412 template <typename Func, typename T, typename... Args>
2413 T FPUCanonalizeOperation(Func f, T first, Args... args) {
2414 return FPUCanonalizeOperation(f, KeepSign::no, first, args...);
2415 }
2416
2417 template <typename Func, typename T, typename... Args>
2418 T FPUCanonalizeOperation(Func f, KeepSign keepSign, T first, Args... args) {
2419 T result = f(first, args...);
2420 if (std::isnan(result)) {
2421 result = FPUCanonalizeNaNArgs(result, keepSign, first, args...);
2422 }
2423 return result;
2424 }
2425
2369 // Handle execution based on instruction types. 2426 // Handle execution based on instruction types.
2370 2427
2371 void Simulator::DecodeTypeRegisterDRsType() { 2428 void Simulator::DecodeTypeRegisterDRsType() {
2372 double ft, fs, fd; 2429 double ft, fs, fd;
2373 uint32_t cc, fcsr_cc; 2430 uint32_t cc, fcsr_cc;
2374 int64_t i64; 2431 int64_t i64;
2375 fs = get_fpu_register_double(fs_reg()); 2432 fs = get_fpu_register_double(fs_reg());
2376 ft = (get_instr()->FunctionFieldRaw() != MOVF) 2433 ft = (get_instr()->FunctionFieldRaw() != MOVF)
2377 ? get_fpu_register_double(ft_reg()) 2434 ? get_fpu_register_double(ft_reg())
2378 : 0.0; 2435 : 0.0;
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
2470 break; 2527 break;
2471 case MINA: 2528 case MINA:
2472 DCHECK(IsMipsArchVariant(kMips32r6)); 2529 DCHECK(IsMipsArchVariant(kMips32r6));
2473 set_fpu_register_double(fd_reg(), FPUMinA(ft, fs)); 2530 set_fpu_register_double(fd_reg(), FPUMinA(ft, fs));
2474 break; 2531 break;
2475 case MAXA: 2532 case MAXA:
2476 DCHECK(IsMipsArchVariant(kMips32r6)); 2533 DCHECK(IsMipsArchVariant(kMips32r6));
2477 set_fpu_register_double(fd_reg(), FPUMaxA(ft, fs)); 2534 set_fpu_register_double(fd_reg(), FPUMaxA(ft, fs));
2478 break; 2535 break;
2479 case ADD_D: 2536 case ADD_D:
2480 set_fpu_register_double(fd_reg(), fs + ft); 2537 set_fpu_register_double(
2538 fd_reg(),
2539 FPUCanonalizeOperation(
2540 [](double lhs, double rhs) { return lhs + rhs; }, fs, ft));
2481 break; 2541 break;
2482 case SUB_D: 2542 case SUB_D:
2483 set_fpu_register_double(fd_reg(), fs - ft); 2543 set_fpu_register_double(
2544 fd_reg(),
2545 FPUCanonalizeOperation(
2546 [](double lhs, double rhs) { return lhs - rhs; }, fs, ft));
2484 break; 2547 break;
2485 case MADDF_D: 2548 case MADDF_D:
2486 DCHECK(IsMipsArchVariant(kMips32r6)); 2549 DCHECK(IsMipsArchVariant(kMips32r6));
2487 set_fpu_register_double(fd_reg(), fd + (fs * ft)); 2550 set_fpu_register_double(fd_reg(), fd + (fs * ft));
2488 break; 2551 break;
2489 case MSUBF_D: 2552 case MSUBF_D:
2490 DCHECK(IsMipsArchVariant(kMips32r6)); 2553 DCHECK(IsMipsArchVariant(kMips32r6));
2491 set_fpu_register_double(fd_reg(), fd - (fs * ft)); 2554 set_fpu_register_double(fd_reg(), fd - (fs * ft));
2492 break; 2555 break;
2493 case MUL_D: 2556 case MUL_D:
2494 set_fpu_register_double(fd_reg(), fs * ft); 2557 set_fpu_register_double(
2558 fd_reg(),
2559 FPUCanonalizeOperation(
2560 [](double lhs, double rhs) { return lhs * rhs; }, fs, ft));
2495 break; 2561 break;
2496 case DIV_D: 2562 case DIV_D:
2497 set_fpu_register_double(fd_reg(), fs / ft); 2563 set_fpu_register_double(
2564 fd_reg(),
2565 FPUCanonalizeOperation(
2566 [](double lhs, double rhs) { return lhs / rhs; }, fs, ft));
2498 break; 2567 break;
2499 case ABS_D: 2568 case ABS_D:
2500 set_fpu_register_double(fd_reg(), fabs(fs)); 2569 set_fpu_register_double(
2570 fd_reg(),
2571 FPUCanonalizeOperation([](double fs) { return FPAbs(fs); }, fs));
2501 break; 2572 break;
2502 case MOV_D: 2573 case MOV_D:
2503 set_fpu_register_double(fd_reg(), fs); 2574 set_fpu_register_double(fd_reg(), fs);
2504 break; 2575 break;
2505 case NEG_D: 2576 case NEG_D:
2506 set_fpu_register_double(fd_reg(), -fs); 2577 set_fpu_register_double(
2578 fd_reg(), FPUCanonalizeOperation([](double src) { return -src; },
2579 KeepSign::yes, fs));
2507 break; 2580 break;
2508 case SQRT_D: 2581 case SQRT_D:
2509 lazily_initialize_fast_sqrt(isolate_); 2582 set_fpu_register_double(
2510 set_fpu_register_double(fd_reg(), fast_sqrt(fs, isolate_)); 2583 fd_reg(),
2584 FPUCanonalizeOperation([](double fs) { return std::sqrt(fs); }, fs));
2511 break; 2585 break;
2512 case RSQRT_D: { 2586 case RSQRT_D:
2513 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); 2587 set_fpu_register_double(
2514 lazily_initialize_fast_sqrt(isolate_); 2588 fd_reg(), FPUCanonalizeOperation(
2515 double result = 1.0 / fast_sqrt(fs, isolate_); 2589 [](double fs) { return 1.0 / std::sqrt(fs); }, fs));
2516 set_fpu_register_double(fd_reg(), result);
2517 break; 2590 break;
2518 } 2591 case RECIP_D:
2519 case RECIP_D: { 2592 set_fpu_register_double(
2520 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); 2593 fd_reg(),
2521 double result = 1.0 / fs; 2594 FPUCanonalizeOperation([](double fs) { return 1.0 / fs; }, fs));
2522 set_fpu_register_double(fd_reg(), result);
2523 break; 2595 break;
2524 }
2525 case C_UN_D: 2596 case C_UN_D:
2526 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); 2597 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2527 break; 2598 break;
2528 case C_EQ_D: 2599 case C_EQ_D:
2529 set_fcsr_bit(fcsr_cc, (fs == ft)); 2600 set_fcsr_bit(fcsr_cc, (fs == ft));
2530 break; 2601 break;
2531 case C_UEQ_D: 2602 case C_UEQ_D:
2532 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); 2603 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2533 break; 2604 break;
2534 case C_OLT_D: 2605 case C_OLT_D:
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
2883 result = lower; 2954 result = lower;
2884 break; 2955 break;
2885 } 2956 }
2886 set_fpu_register_float(fd_reg(), result); 2957 set_fpu_register_float(fd_reg(), result);
2887 if (result != fs) { 2958 if (result != fs) {
2888 set_fcsr_bit(kFCSRInexactFlagBit, true); 2959 set_fcsr_bit(kFCSRInexactFlagBit, true);
2889 } 2960 }
2890 break; 2961 break;
2891 } 2962 }
2892 case ADD_S: 2963 case ADD_S:
2893 set_fpu_register_float(fd_reg(), fs + ft); 2964 set_fpu_register_float(
2965 fd_reg(),
2966 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs + rhs; },
2967 fs, ft));
2894 break; 2968 break;
2895 case SUB_S: 2969 case SUB_S:
2896 set_fpu_register_float(fd_reg(), fs - ft); 2970 set_fpu_register_float(
2971 fd_reg(),
2972 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs - rhs; },
2973 fs, ft));
2897 break; 2974 break;
2898 case MADDF_S: 2975 case MADDF_S:
2899 DCHECK(IsMipsArchVariant(kMips32r6)); 2976 DCHECK(IsMipsArchVariant(kMips32r6));
2900 set_fpu_register_float(fd_reg(), fd + (fs * ft)); 2977 set_fpu_register_float(fd_reg(), fd + (fs * ft));
2901 break; 2978 break;
2902 case MSUBF_S: 2979 case MSUBF_S:
2903 DCHECK(IsMipsArchVariant(kMips32r6)); 2980 DCHECK(IsMipsArchVariant(kMips32r6));
2904 set_fpu_register_float(fd_reg(), fd - (fs * ft)); 2981 set_fpu_register_float(fd_reg(), fd - (fs * ft));
2905 break; 2982 break;
2906 case MUL_S: 2983 case MUL_S:
2907 set_fpu_register_float(fd_reg(), fs * ft); 2984 set_fpu_register_float(
2985 fd_reg(),
2986 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs * rhs; },
2987 fs, ft));
2908 break; 2988 break;
2909 case DIV_S: 2989 case DIV_S:
2910 set_fpu_register_float(fd_reg(), fs / ft); 2990 set_fpu_register_float(
2991 fd_reg(),
2992 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs / rhs; },
2993 fs, ft));
2911 break; 2994 break;
2912 case ABS_S: 2995 case ABS_S:
2913 set_fpu_register_float(fd_reg(), fabs(fs)); 2996 set_fpu_register_float(
2997 fd_reg(),
2998 FPUCanonalizeOperation([](float fs) { return FPAbs(fs); }, fs));
2914 break; 2999 break;
2915 case MOV_S: 3000 case MOV_S:
2916 set_fpu_register_float(fd_reg(), fs); 3001 set_fpu_register_float(fd_reg(), fs);
2917 break; 3002 break;
2918 case NEG_S: 3003 case NEG_S:
2919 set_fpu_register_float(fd_reg(), -fs); 3004 set_fpu_register_float(
3005 fd_reg(), FPUCanonalizeOperation([](float src) { return -src; },
3006 KeepSign::yes, fs));
2920 break; 3007 break;
2921 case SQRT_S: 3008 case SQRT_S:
2922 lazily_initialize_fast_sqrt(isolate_); 3009 set_fpu_register_float(
2923 set_fpu_register_float(fd_reg(), fast_sqrt(fs, isolate_)); 3010 fd_reg(),
3011 FPUCanonalizeOperation([](float src) { return std::sqrt(src); }, fs));
2924 break; 3012 break;
2925 case RSQRT_S: { 3013 case RSQRT_S:
2926 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); 3014 set_fpu_register_float(
2927 lazily_initialize_fast_sqrt(isolate_); 3015 fd_reg(), FPUCanonalizeOperation(
2928 float result = 1.0 / fast_sqrt(fs, isolate_); 3016 [](float src) { return 1.0 / std::sqrt(src); }, fs));
2929 set_fpu_register_float(fd_reg(), result);
2930 break; 3017 break;
2931 } 3018 case RECIP_S:
2932 case RECIP_S: { 3019 set_fpu_register_float(
2933 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); 3020 fd_reg(),
2934 float result = 1.0 / fs; 3021 FPUCanonalizeOperation([](float src) { return 1.0 / src; }, fs));
2935 set_fpu_register_float(fd_reg(), result);
2936 break; 3022 break;
2937 }
2938 case C_F_D: 3023 case C_F_D:
2939 set_fcsr_bit(fcsr_cc, false); 3024 set_fcsr_bit(fcsr_cc, false);
2940 break; 3025 break;
2941 case C_UN_D: 3026 case C_UN_D:
2942 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); 3027 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2943 break; 3028 break;
2944 case C_EQ_D: 3029 case C_EQ_D:
2945 set_fcsr_bit(fcsr_cc, (fs == ft)); 3030 set_fcsr_bit(fcsr_cc, (fs == ft));
2946 break; 3031 break;
2947 case C_UEQ_D: 3032 case C_UEQ_D:
(...skipping 1678 matching lines...) Expand 10 before | Expand all | Expand 10 after
4626 4711
4627 4712
4628 #undef UNSUPPORTED 4713 #undef UNSUPPORTED
4629 4714
4630 } // namespace internal 4715 } // namespace internal
4631 } // namespace v8 4716 } // namespace v8
4632 4717
4633 #endif // USE_SIMULATOR 4718 #endif // USE_SIMULATOR
4634 4719
4635 #endif // V8_TARGET_ARCH_MIPS 4720 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « no previous file | src/mips64/simulator-mips64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698