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

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

Issue 1147493002: Reland "MIPS: Add float instructions and test coverage, part one" (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Bug fixed Created 5 years, 7 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 | « src/mips64/simulator-mips64.h ('k') | test/cctest/test-assembler-mips.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 #include "src/v8.h" 10 #include "src/v8.h"
(...skipping 1170 matching lines...) Expand 10 before | Expand all | Expand 10 after
1181 FCSR_ &= ~(1 << cc); 1181 FCSR_ &= ~(1 << cc);
1182 } 1182 }
1183 } 1183 }
1184 1184
1185 1185
1186 bool Simulator::test_fcsr_bit(uint32_t cc) { 1186 bool Simulator::test_fcsr_bit(uint32_t cc) {
1187 return FCSR_ & (1 << cc); 1187 return FCSR_ & (1 << cc);
1188 } 1188 }
1189 1189
1190 1190
1191 void Simulator::set_fcsr_rounding_mode(FPURoundingMode mode) {
1192 FCSR_ |= mode & kFPURoundingModeMask;
1193 }
1194
1195
1196 unsigned int Simulator::get_fcsr_rounding_mode() {
1197 return FCSR_ & kFPURoundingModeMask;
1198 }
1199
1200
1191 // Sets the rounding error codes in FCSR based on the result of the rounding. 1201 // Sets the rounding error codes in FCSR based on the result of the rounding.
1192 // Returns true if the operation was invalid. 1202 // Returns true if the operation was invalid.
1193 bool Simulator::set_fcsr_round_error(double original, double rounded) { 1203 bool Simulator::set_fcsr_round_error(double original, double rounded) {
1194 bool ret = false; 1204 bool ret = false;
1195 double max_int32 = std::numeric_limits<int32_t>::max(); 1205 double max_int32 = std::numeric_limits<int32_t>::max();
1196 double min_int32 = std::numeric_limits<int32_t>::min(); 1206 double min_int32 = std::numeric_limits<int32_t>::min();
1197 1207
1198 if (!std::isfinite(original) || !std::isfinite(rounded)) { 1208 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1199 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1209 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1200 ret = true; 1210 ret = true;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1245 set_fcsr_bit(kFCSROverflowFlagBit, true); 1255 set_fcsr_bit(kFCSROverflowFlagBit, true);
1246 // The reference is not really clear but it seems this is required: 1256 // The reference is not really clear but it seems this is required:
1247 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1257 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1248 ret = true; 1258 ret = true;
1249 } 1259 }
1250 1260
1251 return ret; 1261 return ret;
1252 } 1262 }
1253 1263
1254 1264
1265 bool Simulator::set_fcsr_round_error(float original, float rounded) {
1266 bool ret = false;
1267 double max_int32 = std::numeric_limits<int32_t>::max();
1268 double min_int32 = std::numeric_limits<int32_t>::min();
1269
1270 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1271 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1272 ret = true;
1273 }
1274
1275 if (original != rounded) {
1276 set_fcsr_bit(kFCSRInexactFlagBit, true);
1277 }
1278
1279 if (rounded < FLT_MIN && rounded > -FLT_MIN && rounded != 0) {
1280 set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1281 ret = true;
1282 }
1283
1284 if (rounded > max_int32 || rounded < min_int32) {
1285 set_fcsr_bit(kFCSROverflowFlagBit, true);
1286 // The reference is not really clear but it seems this is required:
1287 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1288 ret = true;
1289 }
1290
1291 return ret;
1292 }
1293
1294
1295 // Sets the rounding error codes in FCSR based on the result of the rounding.
1296 // Returns true if the operation was invalid.
1297 bool Simulator::set_fcsr_round64_error(float original, float rounded) {
1298 bool ret = false;
1299 double max_int64 = std::numeric_limits<int64_t>::max();
1300 double min_int64 = std::numeric_limits<int64_t>::min();
1301
1302 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1303 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1304 ret = true;
1305 }
1306
1307 if (original != rounded) {
1308 set_fcsr_bit(kFCSRInexactFlagBit, true);
1309 }
1310
1311 if (rounded < FLT_MIN && rounded > -FLT_MIN && rounded != 0) {
1312 set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1313 ret = true;
1314 }
1315
1316 if (rounded > max_int64 || rounded < min_int64) {
1317 set_fcsr_bit(kFCSROverflowFlagBit, true);
1318 // The reference is not really clear but it seems this is required:
1319 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1320 ret = true;
1321 }
1322
1323 return ret;
1324 }
1325
1326
1255 // for cvt instructions only 1327 // for cvt instructions only
1256 void Simulator::round_according_to_fcsr(double toRound, double& rounded, 1328 void Simulator::round_according_to_fcsr(double toRound, double& rounded,
1257 int32_t& rounded_int, double fs) { 1329 int32_t& rounded_int, double fs) {
1258 // 0 RN (round to nearest): Round a result to the nearest 1330 // 0 RN (round to nearest): Round a result to the nearest
1259 // representable value; if the result is exactly halfway between 1331 // representable value; if the result is exactly halfway between
1260 // two representable values, round to zero. Behave like round_w_d. 1332 // two representable values, round to zero. Behave like round_w_d.
1261 1333
1262 // 1 RZ (round toward zero): Round a result to the closest 1334 // 1 RZ (round toward zero): Round a result to the closest
1263 // representable value whose absolute value is less than or 1335 // representable value whose absolute value is less than or
1264 // equal to the infinitely accurate result. Behave like trunc_w_d. 1336 // equal to the infinitely accurate result. Behave like trunc_w_d.
(...skipping 1084 matching lines...) Expand 10 before | Expand all | Expand 10 after
2349 default: 2421 default:
2350 UNREACHABLE(); 2422 UNREACHABLE();
2351 } 2423 }
2352 } 2424 }
2353 2425
2354 2426
2355 void Simulator::DecodeTypeRegisterSRsType(Instruction* instr, 2427 void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
2356 const int32_t& fs_reg, 2428 const int32_t& fs_reg,
2357 const int32_t& ft_reg, 2429 const int32_t& ft_reg,
2358 const int32_t& fd_reg) { 2430 const int32_t& fd_reg) {
2359 float fs, ft; 2431 float fs, ft, fd;
2360 fs = get_fpu_register_float(fs_reg); 2432 fs = get_fpu_register_float(fs_reg);
2361 ft = get_fpu_register_float(ft_reg); 2433 ft = get_fpu_register_float(ft_reg);
2434 fd = get_fpu_register_float(fd_reg);
2435 int32_t ft_int = bit_cast<int32_t>(ft);
2436 int32_t fd_int = bit_cast<int32_t>(fd);
2362 uint32_t cc, fcsr_cc; 2437 uint32_t cc, fcsr_cc;
2363 cc = instr->FCccValue(); 2438 cc = instr->FCccValue();
2364 fcsr_cc = get_fcsr_condition_bit(cc); 2439 fcsr_cc = get_fcsr_condition_bit(cc);
2365 switch (instr->FunctionFieldRaw()) { 2440 switch (instr->FunctionFieldRaw()) {
2366 case ADD_D: 2441 case RINT: {
2442 DCHECK(kArchVariant == kMips64r6);
2443 float result, temp_result;
2444 double temp;
2445 float upper = std::ceil(fs);
2446 float lower = std::floor(fs);
2447 switch (get_fcsr_rounding_mode()) {
2448 case kRoundToNearest:
2449 if (upper - fs < fs - lower) {
2450 result = upper;
2451 } else if (upper - fs > fs - lower) {
2452 result = lower;
2453 } else {
2454 temp_result = upper / 2;
2455 float reminder = modf(temp_result, &temp);
2456 if (reminder == 0) {
2457 result = upper;
2458 } else {
2459 result = lower;
2460 }
2461 }
2462 break;
2463 case kRoundToZero:
2464 result = (fs > 0 ? lower : upper);
2465 break;
2466 case kRoundToPlusInf:
2467 result = upper;
2468 break;
2469 case kRoundToMinusInf:
2470 result = lower;
2471 break;
2472 }
2473 set_fpu_register_float(fd_reg, result);
2474 if (result != fs) {
2475 set_fcsr_bit(kFCSRInexactFlagBit, true);
2476 }
2477 break;
2478 }
2479 case ADD_S:
2367 set_fpu_register_float(fd_reg, fs + ft); 2480 set_fpu_register_float(fd_reg, fs + ft);
2368 break; 2481 break;
2369 case SUB_D: 2482 case SUB_S:
2370 set_fpu_register_float(fd_reg, fs - ft); 2483 set_fpu_register_float(fd_reg, fs - ft);
2371 break; 2484 break;
2372 case MUL_D: 2485 case MUL_S:
2373 set_fpu_register_float(fd_reg, fs * ft); 2486 set_fpu_register_float(fd_reg, fs * ft);
2374 break; 2487 break;
2375 case DIV_D: 2488 case DIV_S:
2376 set_fpu_register_float(fd_reg, fs / ft); 2489 set_fpu_register_float(fd_reg, fs / ft);
2377 break; 2490 break;
2378 case ABS_D: 2491 case ABS_S:
2379 set_fpu_register_float(fd_reg, fabs(fs)); 2492 set_fpu_register_float(fd_reg, fabs(fs));
2380 break; 2493 break;
2381 case MOV_D: 2494 case MOV_S:
2382 set_fpu_register_float(fd_reg, fs); 2495 set_fpu_register_float(fd_reg, fs);
2383 break; 2496 break;
2384 case NEG_D: 2497 case NEG_S:
2385 set_fpu_register_float(fd_reg, -fs); 2498 set_fpu_register_float(fd_reg, -fs);
2386 break; 2499 break;
2387 case SQRT_D: 2500 case SQRT_S:
2388 set_fpu_register_float(fd_reg, fast_sqrt(fs)); 2501 set_fpu_register_float(fd_reg, fast_sqrt(fs));
2389 break; 2502 break;
2503 case RSQRT_S: {
2504 float result = 1.0 / fast_sqrt(fs);
2505 set_fpu_register_float(fd_reg, result);
2506 break;
2507 }
2508 case RECIP_S: {
2509 float result = 1.0 / fs;
2510 set_fpu_register_float(fd_reg, result);
2511 break;
2512 }
2390 case C_UN_D: 2513 case C_UN_D:
2391 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); 2514 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2392 break; 2515 break;
2393 case C_EQ_D: 2516 case C_EQ_D:
2394 set_fcsr_bit(fcsr_cc, (fs == ft)); 2517 set_fcsr_bit(fcsr_cc, (fs == ft));
2395 break; 2518 break;
2396 case C_UEQ_D: 2519 case C_UEQ_D:
2397 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); 2520 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2398 break; 2521 break;
2399 case C_OLT_D: 2522 case C_OLT_D:
2400 set_fcsr_bit(fcsr_cc, (fs < ft)); 2523 set_fcsr_bit(fcsr_cc, (fs < ft));
2401 break; 2524 break;
2402 case C_ULT_D: 2525 case C_ULT_D:
2403 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); 2526 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
2404 break; 2527 break;
2405 case C_OLE_D: 2528 case C_OLE_D:
2406 set_fcsr_bit(fcsr_cc, (fs <= ft)); 2529 set_fcsr_bit(fcsr_cc, (fs <= ft));
2407 break; 2530 break;
2408 case C_ULE_D: 2531 case C_ULE_D:
2409 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); 2532 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
2410 break; 2533 break;
2411 case CVT_D_S: 2534 case CVT_D_S:
2412 set_fpu_register_double(fd_reg, static_cast<double>(fs)); 2535 set_fpu_register_double(fd_reg, static_cast<double>(fs));
2413 break; 2536 break;
2537 case TRUNC_W_S: { // Truncate single to word (round towards 0).
2538 float rounded = trunc(fs);
2539 int32_t result = static_cast<int32_t>(rounded);
2540 set_fpu_register_word(fd_reg, result);
2541 if (set_fcsr_round_error(fs, rounded)) {
2542 set_fpu_register_word(fd_reg, kFPUInvalidResult);
2543 }
2544 } break;
2545 case TRUNC_L_S: { // Mips64r2 instruction.
2546 float rounded = trunc(fs);
2547 int64_t result = static_cast<int64_t>(rounded);
2548 set_fpu_register(fd_reg, result);
2549 if (set_fcsr_round64_error(fs, rounded)) {
2550 set_fpu_register(fd_reg, kFPU64InvalidResult);
2551 }
2552 break;
2553 }
2554 case ROUND_W_S: {
2555 float rounded = std::floor(fs + 0.5);
2556 int32_t result = static_cast<int32_t>(rounded);
2557 if ((result & 1) != 0 && result - fs == 0.5) {
2558 // If the number is halfway between two integers,
2559 // round to the even one.
2560 result--;
2561 }
2562 set_fpu_register_word(fd_reg, result);
2563 if (set_fcsr_round_error(fs, rounded)) {
2564 set_fpu_register_word(fd_reg, kFPUInvalidResult);
2565 }
2566 break;
2567 }
2568 case ROUND_L_S: { // Mips64r2 instruction.
2569 float rounded = std::floor(fs + 0.5);
2570 int64_t result = static_cast<int64_t>(rounded);
2571 if ((result & 1) != 0 && result - fs == 0.5) {
2572 // If the number is halfway between two integers,
2573 // round to the even one.
2574 result--;
2575 }
2576 int64_t i64 = static_cast<int64_t>(result);
2577 set_fpu_register(fd_reg, i64);
2578 if (set_fcsr_round64_error(fs, rounded)) {
2579 set_fpu_register(fd_reg, kFPU64InvalidResult);
2580 }
2581 break;
2582 }
2583 case FLOOR_L_S: { // Mips64r2 instruction.
2584 float rounded = floor(fs);
2585 int64_t result = static_cast<int64_t>(rounded);
2586 set_fpu_register(fd_reg, result);
2587 if (set_fcsr_round64_error(fs, rounded)) {
2588 set_fpu_register(fd_reg, kFPU64InvalidResult);
2589 }
2590 break;
2591 }
2592 case FLOOR_W_S: // Round double to word towards negative infinity.
2593 {
2594 float rounded = std::floor(fs);
2595 int32_t result = static_cast<int32_t>(rounded);
2596 set_fpu_register_word(fd_reg, result);
2597 if (set_fcsr_round_error(fs, rounded)) {
2598 set_fpu_register_word(fd_reg, kFPUInvalidResult);
2599 }
2600 } break;
2601 case CEIL_W_S: // Round double to word towards positive infinity.
2602 {
2603 float rounded = std::ceil(fs);
2604 int32_t result = static_cast<int32_t>(rounded);
2605 set_fpu_register_word(fd_reg, result);
2606 if (set_fcsr_round_error(fs, rounded)) {
2607 set_fpu_register(fd_reg, kFPUInvalidResult);
2608 }
2609 } break;
2610 case CEIL_L_S: { // Mips64r2 instruction.
2611 float rounded = ceil(fs);
2612 int64_t result = static_cast<int64_t>(rounded);
2613 set_fpu_register(fd_reg, result);
2614 if (set_fcsr_round64_error(fs, rounded)) {
2615 set_fpu_register(fd_reg, kFPU64InvalidResult);
2616 }
2617 break;
2618 }
2619 case MINA:
2620 DCHECK(kArchVariant == kMips64r6);
2621 fs = get_fpu_register_float(fs_reg);
2622 if (std::isnan(fs) && std::isnan(ft)) {
2623 set_fpu_register_float(fd_reg, fs);
2624 } else if (std::isnan(fs) && !std::isnan(ft)) {
2625 set_fpu_register_float(fd_reg, ft);
2626 } else if (!std::isnan(fs) && std::isnan(ft)) {
2627 set_fpu_register_float(fd_reg, fs);
2628 } else {
2629 float result;
2630 if (fabs(fs) > fabs(ft)) {
2631 result = ft;
2632 } else if (fabs(fs) < fabs(ft)) {
2633 result = fs;
2634 } else {
2635 result = (fs > ft ? fs : ft);
2636 }
2637 set_fpu_register_float(fd_reg, result);
2638 }
2639 break;
2640 case MAXA:
2641 DCHECK(kArchVariant == kMips64r6);
2642 fs = get_fpu_register_float(fs_reg);
2643 if (std::isnan(fs) && std::isnan(ft)) {
2644 set_fpu_register_float(fd_reg, fs);
2645 } else if (std::isnan(fs) && !std::isnan(ft)) {
2646 set_fpu_register_float(fd_reg, ft);
2647 } else if (!std::isnan(fs) && std::isnan(ft)) {
2648 set_fpu_register_float(fd_reg, fs);
2649 } else {
2650 float result;
2651 if (fabs(fs) < fabs(ft)) {
2652 result = ft;
2653 } else if (fabs(fs) > fabs(ft)) {
2654 result = fs;
2655 } else {
2656 result = (fs > ft ? fs : ft);
2657 }
2658 set_fpu_register_float(fd_reg, result);
2659 }
2660 break;
2661 case MIN:
2662 DCHECK(kArchVariant == kMips64r6);
2663 fs = get_fpu_register_float(fs_reg);
2664 if (std::isnan(fs) && std::isnan(ft)) {
2665 set_fpu_register_float(fd_reg, fs);
2666 } else if (std::isnan(fs) && !std::isnan(ft)) {
2667 set_fpu_register_float(fd_reg, ft);
2668 } else if (!std::isnan(fs) && std::isnan(ft)) {
2669 set_fpu_register_float(fd_reg, fs);
2670 } else {
2671 set_fpu_register_float(fd_reg, (fs >= ft) ? ft : fs);
2672 }
2673 break;
2674 case MAX:
2675 DCHECK(kArchVariant == kMips64r6);
2676 fs = get_fpu_register_float(fs_reg);
2677 if (std::isnan(fs) && std::isnan(ft)) {
2678 set_fpu_register_float(fd_reg, fs);
2679 } else if (std::isnan(fs) && !std::isnan(ft)) {
2680 set_fpu_register_float(fd_reg, ft);
2681 } else if (!std::isnan(fs) && std::isnan(ft)) {
2682 set_fpu_register_float(fd_reg, fs);
2683 } else {
2684 set_fpu_register_float(fd_reg, (fs <= ft) ? ft : fs);
2685 }
2686 break;
2687 case SEL:
2688 DCHECK(kArchVariant == kMips64r6);
2689 set_fpu_register_float(fd_reg, (fd_int & 0x1) == 0 ? fs : ft);
2690 break;
2691 case SELEQZ_C:
2692 DCHECK(kArchVariant == kMips64r6);
2693 set_fpu_register_float(
2694 fd_reg, (ft_int & 0x1) == 0 ? get_fpu_register_float(fs_reg) : 0.0);
2695 break;
2696 case SELNEZ_C:
2697 DCHECK(kArchVariant == kMips64r6);
2698 set_fpu_register_float(
2699 fd_reg, (ft_int & 0x1) != 0 ? get_fpu_register_float(fs_reg) : 0.0);
2700 break;
2701 case MOVZ_C: {
2702 DCHECK(kArchVariant == kMips64r2);
2703 int32_t rt_reg = instr->RtValue();
2704 int64_t rt = get_register(rt_reg);
2705 if (rt == 0) {
2706 set_fpu_register_float(fd_reg, fs);
2707 }
2708 break;
2709 }
2710 case MOVN_C: {
2711 DCHECK(kArchVariant == kMips64r2);
2712 int32_t rt_reg = instr->RtValue();
2713 int64_t rt = get_register(rt_reg);
2714 if (rt != 0) {
2715 set_fpu_register_float(fd_reg, fs);
2716 }
2717 break;
2718 }
2719 case MOVF: {
2720 // Same function field for MOVT.D and MOVF.D
2721 uint32_t ft_cc = (ft_reg >> 2) & 0x7;
2722 ft_cc = get_fcsr_condition_bit(ft_cc);
2723
2724 if (instr->Bit(16)) { // Read Tf bit.
2725 // MOVT.D
2726 if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg, fs);
2727 } else {
2728 // MOVF.D
2729 if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg, fs);
2730 }
2731 break;
2732 }
2414 default: 2733 default:
2415 // CVT_W_S CVT_L_S TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S 2734 // CVT_W_S CVT_L_S TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S
2416 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. 2735 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented.
2417 UNREACHABLE(); 2736 UNREACHABLE();
2418 } 2737 }
2419 } 2738 }
2420 2739
2421 2740
2422 void Simulator::DecodeTypeRegisterDRsType(Instruction* instr, 2741 void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
2423 const int32_t& fs_reg, 2742 const int32_t& fs_reg,
2424 const int32_t& ft_reg, 2743 const int32_t& ft_reg,
2425 const int32_t& fd_reg) { 2744 const int32_t& fd_reg) {
2426 double ft, fs, fd; 2745 double ft, fs, fd;
2427 uint32_t cc, fcsr_cc; 2746 uint32_t cc, fcsr_cc;
2428 fs = get_fpu_register_double(fs_reg); 2747 fs = get_fpu_register_double(fs_reg);
2429 ft = get_fpu_register_double(ft_reg); 2748 if (instr->FunctionFieldRaw() != MOVF) {
2749 ft = get_fpu_register_double(ft_reg);
2750 }
2430 fd = get_fpu_register_double(fd_reg); 2751 fd = get_fpu_register_double(fd_reg);
2431 cc = instr->FCccValue(); 2752 cc = instr->FCccValue();
2432 fcsr_cc = get_fcsr_condition_bit(cc); 2753 fcsr_cc = get_fcsr_condition_bit(cc);
2433 int64_t ft_int = bit_cast<int64_t>(ft); 2754 int64_t ft_int = bit_cast<int64_t>(ft);
2434 int64_t fd_int = bit_cast<int64_t>(fd); 2755 int64_t fd_int = bit_cast<int64_t>(fd);
2435 switch (instr->FunctionFieldRaw()) { 2756 switch (instr->FunctionFieldRaw()) {
2436 case RINT: { 2757 case RINT: {
2437 DCHECK(kArchVariant == kMips64r6); 2758 DCHECK(kArchVariant == kMips64r6);
2438 double result, temp, temp_result; 2759 double result, temp, temp_result;
2439 double upper = std::ceil(fs); 2760 double upper = std::ceil(fs);
2440 double lower = std::floor(fs); 2761 double lower = std::floor(fs);
2441 switch (FCSR_ & 0x3) { 2762 switch (get_fcsr_rounding_mode()) {
2442 case kRoundToNearest: 2763 case kRoundToNearest:
2443 if (upper - fs < fs - lower) { 2764 if (upper - fs < fs - lower) {
2444 result = upper; 2765 result = upper;
2445 } else if (upper - fs > fs - lower) { 2766 } else if (upper - fs > fs - lower) {
2446 result = lower; 2767 result = lower;
2447 } else { 2768 } else {
2448 temp_result = upper / 2; 2769 temp_result = upper / 2;
2449 double reminder = modf(temp_result, &temp); 2770 double reminder = modf(temp_result, &temp);
2450 if (reminder == 0) { 2771 if (reminder == 0) {
2451 result = upper; 2772 result = upper;
(...skipping 23 matching lines...) Expand all
2475 set_fpu_register_double(fd_reg, (fd_int & 0x1) == 0 ? fs : ft); 2796 set_fpu_register_double(fd_reg, (fd_int & 0x1) == 0 ? fs : ft);
2476 break; 2797 break;
2477 case SELEQZ_C: 2798 case SELEQZ_C:
2478 DCHECK(kArchVariant == kMips64r6); 2799 DCHECK(kArchVariant == kMips64r6);
2479 set_fpu_register_double(fd_reg, (ft_int & 0x1) == 0 ? fs : 0.0); 2800 set_fpu_register_double(fd_reg, (ft_int & 0x1) == 0 ? fs : 0.0);
2480 break; 2801 break;
2481 case SELNEZ_C: 2802 case SELNEZ_C:
2482 DCHECK(kArchVariant == kMips64r6); 2803 DCHECK(kArchVariant == kMips64r6);
2483 set_fpu_register_double(fd_reg, (ft_int & 0x1) != 0 ? fs : 0.0); 2804 set_fpu_register_double(fd_reg, (ft_int & 0x1) != 0 ? fs : 0.0);
2484 break; 2805 break;
2806 case MOVZ_C: {
2807 DCHECK(kArchVariant == kMips64r2);
2808 int32_t rt_reg = instr->RtValue();
2809 int64_t rt = get_register(rt_reg);
2810 if (rt == 0) {
2811 set_fpu_register_double(fd_reg, fs);
2812 }
2813 break;
2814 }
2815 case MOVN_C: {
2816 DCHECK(kArchVariant == kMips64r2);
2817 int32_t rt_reg = instr->RtValue();
2818 int64_t rt = get_register(rt_reg);
2819 if (rt != 0) {
2820 set_fpu_register_double(fd_reg, fs);
2821 }
2822 break;
2823 }
2824 case MOVF: {
2825 // Same function field for MOVT.D and MOVF.D
2826 uint32_t ft_cc = (ft_reg >> 2) & 0x7;
2827 ft_cc = get_fcsr_condition_bit(ft_cc);
2828 if (instr->Bit(16)) { // Read Tf bit.
2829 // MOVT.D
2830 if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg, fs);
2831 } else {
2832 // MOVF.D
2833 if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg, fs);
2834 }
2835 break;
2836 }
2837 case MINA:
2838 DCHECK(kArchVariant == kMips64r6);
2839 fs = get_fpu_register_double(fs_reg);
2840 if (std::isnan(fs) && std::isnan(ft)) {
2841 set_fpu_register_double(fd_reg, fs);
2842 } else if (std::isnan(fs) && !std::isnan(ft)) {
2843 set_fpu_register_double(fd_reg, ft);
2844 } else if (!std::isnan(fs) && std::isnan(ft)) {
2845 set_fpu_register_double(fd_reg, fs);
2846 } else {
2847 double result;
2848 if (fabs(fs) > fabs(ft)) {
2849 result = ft;
2850 } else if (fabs(fs) < fabs(ft)) {
2851 result = fs;
2852 } else {
2853 result = (fs > ft ? fs : ft);
2854 }
2855 set_fpu_register_double(fd_reg, result);
2856 }
2857 break;
2858 case MAXA:
2859 DCHECK(kArchVariant == kMips64r6);
2860 fs = get_fpu_register_double(fs_reg);
2861 if (std::isnan(fs) && std::isnan(ft)) {
2862 set_fpu_register_double(fd_reg, fs);
2863 } else if (std::isnan(fs) && !std::isnan(ft)) {
2864 set_fpu_register_double(fd_reg, ft);
2865 } else if (!std::isnan(fs) && std::isnan(ft)) {
2866 set_fpu_register_double(fd_reg, fs);
2867 } else {
2868 double result;
2869 if (fabs(fs) < fabs(ft)) {
2870 result = ft;
2871 } else if (fabs(fs) > fabs(ft)) {
2872 result = fs;
2873 } else {
2874 result = (fs > ft ? fs : ft);
2875 }
2876 set_fpu_register_double(fd_reg, result);
2877 }
2878 break;
2485 case MIN: 2879 case MIN:
2486 DCHECK(kArchVariant == kMips64r6); 2880 DCHECK(kArchVariant == kMips64r6);
2487 fs = get_fpu_register_double(fs_reg); 2881 fs = get_fpu_register_double(fs_reg);
2488 if (std::isnan(fs) && std::isnan(ft)) { 2882 if (std::isnan(fs) && std::isnan(ft)) {
2489 set_fpu_register_double(fd_reg, fs); 2883 set_fpu_register_double(fd_reg, fs);
2490 } else if (std::isnan(fs) && !std::isnan(ft)) { 2884 } else if (std::isnan(fs) && !std::isnan(ft)) {
2491 set_fpu_register_double(fd_reg, ft); 2885 set_fpu_register_double(fd_reg, ft);
2492 } else if (!std::isnan(fs) && std::isnan(ft)) { 2886 } else if (!std::isnan(fs) && std::isnan(ft)) {
2493 set_fpu_register_double(fd_reg, fs); 2887 set_fpu_register_double(fd_reg, fs);
2494 } else { 2888 } else {
(...skipping 30 matching lines...) Expand all
2525 break; 2919 break;
2526 case MOV_D: 2920 case MOV_D:
2527 set_fpu_register_double(fd_reg, fs); 2921 set_fpu_register_double(fd_reg, fs);
2528 break; 2922 break;
2529 case NEG_D: 2923 case NEG_D:
2530 set_fpu_register_double(fd_reg, -fs); 2924 set_fpu_register_double(fd_reg, -fs);
2531 break; 2925 break;
2532 case SQRT_D: 2926 case SQRT_D:
2533 set_fpu_register_double(fd_reg, fast_sqrt(fs)); 2927 set_fpu_register_double(fd_reg, fast_sqrt(fs));
2534 break; 2928 break;
2929 case RSQRT_D: {
2930 double result = 1.0 / fast_sqrt(fs);
2931 set_fpu_register_double(fd_reg, result);
2932 break;
2933 }
2934 case RECIP_D: {
2935 double result = 1.0 / fs;
2936 set_fpu_register_double(fd_reg, result);
2937 break;
2938 }
2535 case C_UN_D: 2939 case C_UN_D:
2536 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); 2940 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2537 break; 2941 break;
2538 case C_EQ_D: 2942 case C_EQ_D:
2539 set_fcsr_bit(fcsr_cc, (fs == ft)); 2943 set_fcsr_bit(fcsr_cc, (fs == ft));
2540 break; 2944 break;
2541 case C_UEQ_D: 2945 case C_UEQ_D:
2542 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); 2946 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2543 break; 2947 break;
2544 case C_OLT_D: 2948 case C_OLT_D:
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
2611 double rounded; 3015 double rounded;
2612 int64_t result; 3016 int64_t result;
2613 round64_according_to_fcsr(fs, rounded, result, fs); 3017 round64_according_to_fcsr(fs, rounded, result, fs);
2614 set_fpu_register(fd_reg, result); 3018 set_fpu_register(fd_reg, result);
2615 if (set_fcsr_round64_error(fs, rounded)) { 3019 if (set_fcsr_round64_error(fs, rounded)) {
2616 set_fpu_register(fd_reg, kFPUInvalidResult); 3020 set_fpu_register(fd_reg, kFPUInvalidResult);
2617 } 3021 }
2618 break; 3022 break;
2619 } 3023 }
2620 case ROUND_L_D: { // Mips64r2 instruction. 3024 case ROUND_L_D: { // Mips64r2 instruction.
2621 // check error cases 3025 double rounded = std::floor(fs + 0.5);
2622 double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
2623 int64_t result = static_cast<int64_t>(rounded); 3026 int64_t result = static_cast<int64_t>(rounded);
2624 set_fpu_register(fd_reg, result); 3027 if ((result & 1) != 0 && result - fs == 0.5) {
3028 // If the number is halfway between two integers,
3029 // round to the even one.
3030 result--;
3031 }
3032 int64_t i64 = static_cast<int64_t>(result);
3033 set_fpu_register(fd_reg, i64);
2625 if (set_fcsr_round64_error(fs, rounded)) { 3034 if (set_fcsr_round64_error(fs, rounded)) {
2626 set_fpu_register(fd_reg, kFPU64InvalidResult); 3035 set_fpu_register(fd_reg, kFPU64InvalidResult);
2627 } 3036 }
2628 break; 3037 break;
2629 } 3038 }
2630 case TRUNC_L_D: { // Mips64r2 instruction. 3039 case TRUNC_L_D: { // Mips64r2 instruction.
2631 double rounded = trunc(fs); 3040 double rounded = trunc(fs);
2632 int64_t result = static_cast<int64_t>(rounded); 3041 int64_t result = static_cast<int64_t>(rounded);
2633 set_fpu_register(fd_reg, result); 3042 set_fpu_register(fd_reg, result);
2634 if (set_fcsr_round64_error(fs, rounded)) { 3043 if (set_fcsr_round64_error(fs, rounded)) {
(...skipping 1116 matching lines...) Expand 10 before | Expand all | Expand 10 after
3751 return address; 4160 return address;
3752 } 4161 }
3753 4162
3754 4163
3755 #undef UNSUPPORTED 4164 #undef UNSUPPORTED
3756 } } // namespace v8::internal 4165 } } // namespace v8::internal
3757 4166
3758 #endif // USE_SIMULATOR 4167 #endif // USE_SIMULATOR
3759 4168
3760 #endif // V8_TARGET_ARCH_MIPS64 4169 #endif // V8_TARGET_ARCH_MIPS64
OLDNEW
« no previous file with comments | « src/mips64/simulator-mips64.h ('k') | test/cctest/test-assembler-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698