| OLD | NEW |
| 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 2329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2340 } | 2340 } |
| 2341 } | 2341 } |
| 2342 } | 2342 } |
| 2343 | 2343 |
| 2344 | 2344 |
| 2345 void Simulator::SignalException(Exception e) { | 2345 void Simulator::SignalException(Exception e) { |
| 2346 V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", | 2346 V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", |
| 2347 static_cast<int>(e)); | 2347 static_cast<int>(e)); |
| 2348 } | 2348 } |
| 2349 | 2349 |
| 2350 template <typename T> |
| 2351 T FPAbs(T a); |
| 2352 |
| 2353 template <> |
| 2354 double FPAbs<double>(double a) { |
| 2355 return fabs(a); |
| 2356 } |
| 2357 |
| 2358 template <> |
| 2359 float FPAbs<float>(float a) { |
| 2360 return fabsf(a); |
| 2361 } |
| 2362 |
| 2363 template <typename T> |
| 2364 bool Simulator::FPUProcessNaNsAndZeros(T a, T b, IsMin min, T& result) { |
| 2365 if (std::isnan(a) && std::isnan(b)) { |
| 2366 result = a; |
| 2367 } else if (std::isnan(a)) { |
| 2368 result = b; |
| 2369 } else if (std::isnan(b)) { |
| 2370 result = a; |
| 2371 } else if (b == a) { |
| 2372 // Handle -0.0 == 0.0 case. |
| 2373 // std::signbit() returns int 0 or 1 so substracting IsMin::kMax negates the |
| 2374 // result. |
| 2375 result = std::signbit(b) - static_cast<int>(min) ? b : a; |
| 2376 } else { |
| 2377 return false; |
| 2378 } |
| 2379 return true; |
| 2380 } |
| 2381 |
| 2382 template <typename T> |
| 2383 T Simulator::FPUMin(T a, T b) { |
| 2384 T result; |
| 2385 if (FPUProcessNaNsAndZeros(a, b, IsMin::kMin, result)) { |
| 2386 return result; |
| 2387 } else { |
| 2388 return b < a ? b : a; |
| 2389 } |
| 2390 } |
| 2391 |
| 2392 template <typename T> |
| 2393 T Simulator::FPUMax(T a, T b) { |
| 2394 T result; |
| 2395 if (FPUProcessNaNsAndZeros(a, b, IsMin::kMax, result)) { |
| 2396 return result; |
| 2397 } else { |
| 2398 return b > a ? b : a; |
| 2399 } |
| 2400 } |
| 2401 |
| 2402 template <typename T> |
| 2403 T Simulator::FPUMinA(T a, T b) { |
| 2404 T result; |
| 2405 if (!FPUProcessNaNsAndZeros(a, b, IsMin::kMin, result)) { |
| 2406 if (FPAbs(a) < FPAbs(b)) { |
| 2407 result = a; |
| 2408 } else if (FPAbs(b) < FPAbs(a)) { |
| 2409 result = b; |
| 2410 } else { |
| 2411 result = a < b ? a : b; |
| 2412 } |
| 2413 } |
| 2414 return result; |
| 2415 } |
| 2416 |
| 2417 template <typename T> |
| 2418 T Simulator::FPUMaxA(T a, T b) { |
| 2419 T result; |
| 2420 if (!FPUProcessNaNsAndZeros(a, b, IsMin::kMin, result)) { |
| 2421 if (FPAbs(a) > FPAbs(b)) { |
| 2422 result = a; |
| 2423 } else if (FPAbs(b) > FPAbs(a)) { |
| 2424 result = b; |
| 2425 } else { |
| 2426 result = a > b ? a : b; |
| 2427 } |
| 2428 } |
| 2429 return result; |
| 2430 } |
| 2431 |
| 2432 // Handle execution based on instruction types. |
| 2350 | 2433 |
| 2351 void Simulator::DecodeTypeRegisterDRsType() { | 2434 void Simulator::DecodeTypeRegisterDRsType() { |
| 2352 double ft, fs, fd; | 2435 double ft, fs, fd; |
| 2353 uint32_t cc, fcsr_cc; | 2436 uint32_t cc, fcsr_cc; |
| 2354 int64_t i64; | 2437 int64_t i64; |
| 2355 fs = get_fpu_register_double(fs_reg()); | 2438 fs = get_fpu_register_double(fs_reg()); |
| 2356 ft = (get_instr()->FunctionFieldRaw() != MOVF) | 2439 ft = (get_instr()->FunctionFieldRaw() != MOVF) |
| 2357 ? get_fpu_register_double(ft_reg()) | 2440 ? get_fpu_register_double(ft_reg()) |
| 2358 : 0.0; | 2441 : 0.0; |
| 2359 fd = get_fpu_register_double(fd_reg()); | 2442 fd = get_fpu_register_double(fd_reg()); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2435 // MOVT.D | 2518 // MOVT.D |
| 2436 if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); | 2519 if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); |
| 2437 } else { | 2520 } else { |
| 2438 // MOVF.D | 2521 // MOVF.D |
| 2439 if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); | 2522 if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); |
| 2440 } | 2523 } |
| 2441 break; | 2524 break; |
| 2442 } | 2525 } |
| 2443 case MIN: | 2526 case MIN: |
| 2444 DCHECK(IsMipsArchVariant(kMips32r6)); | 2527 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2445 fs = get_fpu_register_double(fs_reg()); | 2528 set_fpu_register_double(fd_reg(), FPUMin(ft, fs)); |
| 2446 if (std::isnan(fs) && std::isnan(ft)) { | 2529 break; |
| 2447 set_fpu_register_double(fd_reg(), fs); | 2530 case MAX: |
| 2448 } else if (std::isnan(fs) && !std::isnan(ft)) { | 2531 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2449 set_fpu_register_double(fd_reg(), ft); | 2532 set_fpu_register_double(fd_reg(), FPUMax(ft, fs)); |
| 2450 } else if (!std::isnan(fs) && std::isnan(ft)) { | |
| 2451 set_fpu_register_double(fd_reg(), fs); | |
| 2452 } else { | |
| 2453 set_fpu_register_double(fd_reg(), (fs >= ft) ? ft : fs); | |
| 2454 } | |
| 2455 break; | 2533 break; |
| 2456 case MINA: | 2534 case MINA: |
| 2457 DCHECK(IsMipsArchVariant(kMips32r6)); | 2535 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2458 fs = get_fpu_register_double(fs_reg()); | 2536 set_fpu_register_double(fd_reg(), FPUMinA(ft, fs)); |
| 2459 if (std::isnan(fs) && std::isnan(ft)) { | |
| 2460 set_fpu_register_double(fd_reg(), fs); | |
| 2461 } else if (std::isnan(fs) && !std::isnan(ft)) { | |
| 2462 set_fpu_register_double(fd_reg(), ft); | |
| 2463 } else if (!std::isnan(fs) && std::isnan(ft)) { | |
| 2464 set_fpu_register_double(fd_reg(), fs); | |
| 2465 } else { | |
| 2466 double result; | |
| 2467 if (fabs(fs) > fabs(ft)) { | |
| 2468 result = ft; | |
| 2469 } else if (fabs(fs) < fabs(ft)) { | |
| 2470 result = fs; | |
| 2471 } else { | |
| 2472 result = (fs < ft ? fs : ft); | |
| 2473 } | |
| 2474 set_fpu_register_double(fd_reg(), result); | |
| 2475 } | |
| 2476 break; | 2537 break; |
| 2477 case MAXA: | 2538 case MAXA: |
| 2478 DCHECK(IsMipsArchVariant(kMips32r6)); | 2539 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2479 fs = get_fpu_register_double(fs_reg()); | 2540 set_fpu_register_double(fd_reg(), FPUMaxA(ft, fs)); |
| 2480 if (std::isnan(fs) && std::isnan(ft)) { | |
| 2481 set_fpu_register_double(fd_reg(), fs); | |
| 2482 } else if (std::isnan(fs) && !std::isnan(ft)) { | |
| 2483 set_fpu_register_double(fd_reg(), ft); | |
| 2484 } else if (!std::isnan(fs) && std::isnan(ft)) { | |
| 2485 set_fpu_register_double(fd_reg(), fs); | |
| 2486 } else { | |
| 2487 double result; | |
| 2488 if (fabs(fs) < fabs(ft)) { | |
| 2489 result = ft; | |
| 2490 } else if (fabs(fs) > fabs(ft)) { | |
| 2491 result = fs; | |
| 2492 } else { | |
| 2493 result = (fs > ft ? fs : ft); | |
| 2494 } | |
| 2495 set_fpu_register_double(fd_reg(), result); | |
| 2496 } | |
| 2497 break; | |
| 2498 case MAX: | |
| 2499 DCHECK(IsMipsArchVariant(kMips32r6)); | |
| 2500 fs = get_fpu_register_double(fs_reg()); | |
| 2501 if (std::isnan(fs) && std::isnan(ft)) { | |
| 2502 set_fpu_register_double(fd_reg(), fs); | |
| 2503 } else if (std::isnan(fs) && !std::isnan(ft)) { | |
| 2504 set_fpu_register_double(fd_reg(), ft); | |
| 2505 } else if (!std::isnan(fs) && std::isnan(ft)) { | |
| 2506 set_fpu_register_double(fd_reg(), fs); | |
| 2507 } else { | |
| 2508 set_fpu_register_double(fd_reg(), (fs <= ft) ? ft : fs); | |
| 2509 } | |
| 2510 break; | |
| 2511 break; | 2541 break; |
| 2512 case ADD_D: | 2542 case ADD_D: |
| 2513 set_fpu_register_double(fd_reg(), fs + ft); | 2543 set_fpu_register_double(fd_reg(), fs + ft); |
| 2514 break; | 2544 break; |
| 2515 case SUB_D: | 2545 case SUB_D: |
| 2516 set_fpu_register_double(fd_reg(), fs - ft); | 2546 set_fpu_register_double(fd_reg(), fs - ft); |
| 2517 break; | 2547 break; |
| 2518 case MUL_D: | 2548 case MUL_D: |
| 2519 set_fpu_register_double(fd_reg(), fs * ft); | 2549 set_fpu_register_double(fd_reg(), fs * ft); |
| 2520 break; | 2550 break; |
| (...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3186 if (set_fcsr_round64_error(fs, rounded)) { | 3216 if (set_fcsr_round64_error(fs, rounded)) { |
| 3187 set_fpu_register_invalid_result64(fs, rounded); | 3217 set_fpu_register_invalid_result64(fs, rounded); |
| 3188 } | 3218 } |
| 3189 } else { | 3219 } else { |
| 3190 UNSUPPORTED(); | 3220 UNSUPPORTED(); |
| 3191 } | 3221 } |
| 3192 break; | 3222 break; |
| 3193 } | 3223 } |
| 3194 case MIN: | 3224 case MIN: |
| 3195 DCHECK(IsMipsArchVariant(kMips32r6)); | 3225 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3196 fs = get_fpu_register_float(fs_reg()); | 3226 set_fpu_register_float(fd_reg(), FPUMin(ft, fs)); |
| 3197 if (std::isnan(fs) && std::isnan(ft)) { | |
| 3198 set_fpu_register_float(fd_reg(), fs); | |
| 3199 } else if (std::isnan(fs) && !std::isnan(ft)) { | |
| 3200 set_fpu_register_float(fd_reg(), ft); | |
| 3201 } else if (!std::isnan(fs) && std::isnan(ft)) { | |
| 3202 set_fpu_register_float(fd_reg(), fs); | |
| 3203 } else { | |
| 3204 set_fpu_register_float(fd_reg(), (fs >= ft) ? ft : fs); | |
| 3205 } | |
| 3206 break; | 3227 break; |
| 3207 case MAX: | 3228 case MAX: |
| 3208 DCHECK(IsMipsArchVariant(kMips32r6)); | 3229 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3209 fs = get_fpu_register_float(fs_reg()); | 3230 set_fpu_register_float(fd_reg(), FPUMax(ft, fs)); |
| 3210 if (std::isnan(fs) && std::isnan(ft)) { | |
| 3211 set_fpu_register_float(fd_reg(), fs); | |
| 3212 } else if (std::isnan(fs) && !std::isnan(ft)) { | |
| 3213 set_fpu_register_float(fd_reg(), ft); | |
| 3214 } else if (!std::isnan(fs) && std::isnan(ft)) { | |
| 3215 set_fpu_register_float(fd_reg(), fs); | |
| 3216 } else { | |
| 3217 set_fpu_register_float(fd_reg(), (fs <= ft) ? ft : fs); | |
| 3218 } | |
| 3219 break; | 3231 break; |
| 3220 case MINA: | 3232 case MINA: |
| 3221 DCHECK(IsMipsArchVariant(kMips32r6)); | 3233 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3222 fs = get_fpu_register_float(fs_reg()); | 3234 set_fpu_register_float(fd_reg(), FPUMinA(ft, fs)); |
| 3223 if (std::isnan(fs) && std::isnan(ft)) { | |
| 3224 set_fpu_register_float(fd_reg(), fs); | |
| 3225 } else if (std::isnan(fs) && !std::isnan(ft)) { | |
| 3226 set_fpu_register_float(fd_reg(), ft); | |
| 3227 } else if (!std::isnan(fs) && std::isnan(ft)) { | |
| 3228 set_fpu_register_float(fd_reg(), fs); | |
| 3229 } else { | |
| 3230 float result; | |
| 3231 if (fabs(fs) > fabs(ft)) { | |
| 3232 result = ft; | |
| 3233 } else if (fabs(fs) < fabs(ft)) { | |
| 3234 result = fs; | |
| 3235 } else { | |
| 3236 result = (fs < ft ? fs : ft); | |
| 3237 } | |
| 3238 set_fpu_register_float(fd_reg(), result); | |
| 3239 } | |
| 3240 break; | 3235 break; |
| 3241 case MAXA: | 3236 case MAXA: |
| 3242 DCHECK(IsMipsArchVariant(kMips32r6)); | 3237 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3243 fs = get_fpu_register_float(fs_reg()); | 3238 set_fpu_register_float(fd_reg(), FPUMaxA(ft, fs)); |
| 3244 if (std::isnan(fs) && std::isnan(ft)) { | |
| 3245 set_fpu_register_float(fd_reg(), fs); | |
| 3246 } else if (std::isnan(fs) && !std::isnan(ft)) { | |
| 3247 set_fpu_register_float(fd_reg(), ft); | |
| 3248 } else if (!std::isnan(fs) && std::isnan(ft)) { | |
| 3249 set_fpu_register_float(fd_reg(), fs); | |
| 3250 } else { | |
| 3251 float result; | |
| 3252 if (fabs(fs) < fabs(ft)) { | |
| 3253 result = ft; | |
| 3254 } else if (fabs(fs) > fabs(ft)) { | |
| 3255 result = fs; | |
| 3256 } else { | |
| 3257 result = (fs > ft ? fs : ft); | |
| 3258 } | |
| 3259 set_fpu_register_float(fd_reg(), result); | |
| 3260 } | |
| 3261 break; | 3239 break; |
| 3262 case CVT_L_S: { | 3240 case CVT_L_S: { |
| 3263 if (IsFp64Mode()) { | 3241 if (IsFp64Mode()) { |
| 3264 int64_t result; | 3242 int64_t result; |
| 3265 float rounded; | 3243 float rounded; |
| 3266 round64_according_to_fcsr(fs, rounded, result, fs); | 3244 round64_according_to_fcsr(fs, rounded, result, fs); |
| 3267 set_fpu_register(fd_reg(), result); | 3245 set_fpu_register(fd_reg(), result); |
| 3268 if (set_fcsr_round64_error(fs, rounded)) { | 3246 if (set_fcsr_round64_error(fs, rounded)) { |
| 3269 set_fpu_register_invalid_result64(fs, rounded); | 3247 set_fpu_register_invalid_result64(fs, rounded); |
| 3270 } | 3248 } |
| (...skipping 1344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4615 | 4593 |
| 4616 | 4594 |
| 4617 #undef UNSUPPORTED | 4595 #undef UNSUPPORTED |
| 4618 | 4596 |
| 4619 } // namespace internal | 4597 } // namespace internal |
| 4620 } // namespace v8 | 4598 } // namespace v8 |
| 4621 | 4599 |
| 4622 #endif // USE_SIMULATOR | 4600 #endif // USE_SIMULATOR |
| 4623 | 4601 |
| 4624 #endif // V8_TARGET_ARCH_MIPS | 4602 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |