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 |