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 #include "src/v8.h" | 10 #include "src/v8.h" |
(...skipping 1264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1275 set_fcsr_bit(kFCSROverflowFlagBit, true); | 1275 set_fcsr_bit(kFCSROverflowFlagBit, true); |
1276 // The reference is not really clear but it seems this is required: | 1276 // The reference is not really clear but it seems this is required: |
1277 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); | 1277 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); |
1278 ret = true; | 1278 ret = true; |
1279 } | 1279 } |
1280 | 1280 |
1281 return ret; | 1281 return ret; |
1282 } | 1282 } |
1283 | 1283 |
1284 | 1284 |
| 1285 // Sets the rounding error codes in FCSR based on the result of the rounding. |
| 1286 // Returns true if the operation was invalid. |
1285 bool Simulator::set_fcsr_round_error(float original, float rounded) { | 1287 bool Simulator::set_fcsr_round_error(float original, float rounded) { |
1286 bool ret = false; | 1288 bool ret = false; |
1287 double max_int32 = std::numeric_limits<int32_t>::max(); | 1289 double max_int32 = std::numeric_limits<int32_t>::max(); |
1288 double min_int32 = std::numeric_limits<int32_t>::min(); | 1290 double min_int32 = std::numeric_limits<int32_t>::min(); |
1289 | 1291 |
1290 if (!std::isfinite(original) || !std::isfinite(rounded)) { | 1292 if (!std::isfinite(original) || !std::isfinite(rounded)) { |
1291 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); | 1293 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); |
1292 ret = true; | 1294 ret = true; |
1293 } | 1295 } |
1294 | 1296 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1337 set_fcsr_bit(kFCSROverflowFlagBit, true); | 1339 set_fcsr_bit(kFCSROverflowFlagBit, true); |
1338 // The reference is not really clear but it seems this is required: | 1340 // The reference is not really clear but it seems this is required: |
1339 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); | 1341 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); |
1340 ret = true; | 1342 ret = true; |
1341 } | 1343 } |
1342 | 1344 |
1343 return ret; | 1345 return ret; |
1344 } | 1346 } |
1345 | 1347 |
1346 | 1348 |
1347 // for cvt instructions only | 1349 // For cvt instructions only |
1348 void Simulator::round_according_to_fcsr(double toRound, double& rounded, | 1350 void Simulator::round_according_to_fcsr(double toRound, double& rounded, |
1349 int32_t& rounded_int, double fs) { | 1351 int32_t& rounded_int, double fs) { |
1350 // 0 RN (round to nearest): Round a result to the nearest | 1352 // 0 RN (round to nearest): Round a result to the nearest |
1351 // representable value; if the result is exactly halfway between | 1353 // representable value; if the result is exactly halfway between |
1352 // two representable values, round to zero. Behave like round_w_d. | 1354 // two representable values, round to zero. Behave like round_w_d. |
1353 | 1355 |
1354 // 1 RZ (round toward zero): Round a result to the closest | 1356 // 1 RZ (round toward zero): Round a result to the closest |
1355 // representable value whose absolute value is less than or | 1357 // representable value whose absolute value is less than or |
1356 // equal to the infinitely accurate result. Behave like trunc_w_d. | 1358 // equal to the infinitely accurate result. Behave like trunc_w_d. |
1357 | 1359 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1420 rounded_int = static_cast<int64_t>(rounded); | 1422 rounded_int = static_cast<int64_t>(rounded); |
1421 break; | 1423 break; |
1422 case kRoundToMinusInf: | 1424 case kRoundToMinusInf: |
1423 rounded = std::floor(fs); | 1425 rounded = std::floor(fs); |
1424 rounded_int = static_cast<int64_t>(rounded); | 1426 rounded_int = static_cast<int64_t>(rounded); |
1425 break; | 1427 break; |
1426 } | 1428 } |
1427 } | 1429 } |
1428 | 1430 |
1429 | 1431 |
| 1432 // for cvt instructions only |
| 1433 void Simulator::round_according_to_fcsr(float toRound, float& rounded, |
| 1434 int32_t& rounded_int, float fs) { |
| 1435 // 0 RN (round to nearest): Round a result to the nearest |
| 1436 // representable value; if the result is exactly halfway between |
| 1437 // two representable values, round to zero. Behave like round_w_d. |
| 1438 |
| 1439 // 1 RZ (round toward zero): Round a result to the closest |
| 1440 // representable value whose absolute value is less than or |
| 1441 // equal to the infinitely accurate result. Behave like trunc_w_d. |
| 1442 |
| 1443 // 2 RP (round up, or toward +infinity): Round a result to the |
| 1444 // next representable value up. Behave like ceil_w_d. |
| 1445 |
| 1446 // 3 RN (round down, or toward −infinity): Round a result to |
| 1447 // the next representable value down. Behave like floor_w_d. |
| 1448 switch (FCSR_ & 3) { |
| 1449 case kRoundToNearest: |
| 1450 rounded = std::floor(fs + 0.5); |
| 1451 rounded_int = static_cast<int32_t>(rounded); |
| 1452 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) { |
| 1453 // If the number is halfway between two integers, |
| 1454 // round to the even one. |
| 1455 rounded_int--; |
| 1456 } |
| 1457 break; |
| 1458 case kRoundToZero: |
| 1459 rounded = trunc(fs); |
| 1460 rounded_int = static_cast<int32_t>(rounded); |
| 1461 break; |
| 1462 case kRoundToPlusInf: |
| 1463 rounded = std::ceil(fs); |
| 1464 rounded_int = static_cast<int32_t>(rounded); |
| 1465 break; |
| 1466 case kRoundToMinusInf: |
| 1467 rounded = std::floor(fs); |
| 1468 rounded_int = static_cast<int32_t>(rounded); |
| 1469 break; |
| 1470 } |
| 1471 } |
| 1472 |
| 1473 |
| 1474 void Simulator::round64_according_to_fcsr(float toRound, float& rounded, |
| 1475 int64_t& rounded_int, float fs) { |
| 1476 // 0 RN (round to nearest): Round a result to the nearest |
| 1477 // representable value; if the result is exactly halfway between |
| 1478 // two representable values, round to zero. Behave like round_w_d. |
| 1479 |
| 1480 // 1 RZ (round toward zero): Round a result to the closest |
| 1481 // representable value whose absolute value is less than or. |
| 1482 // equal to the infinitely accurate result. Behave like trunc_w_d. |
| 1483 |
| 1484 // 2 RP (round up, or toward +infinity): Round a result to the |
| 1485 // next representable value up. Behave like ceil_w_d. |
| 1486 |
| 1487 // 3 RN (round down, or toward −infinity): Round a result to |
| 1488 // the next representable value down. Behave like floor_w_d. |
| 1489 switch (FCSR_ & 3) { |
| 1490 case kRoundToNearest: |
| 1491 rounded = std::floor(fs + 0.5); |
| 1492 rounded_int = static_cast<int64_t>(rounded); |
| 1493 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) { |
| 1494 // If the number is halfway between two integers, |
| 1495 // round to the even one. |
| 1496 rounded_int--; |
| 1497 } |
| 1498 break; |
| 1499 case kRoundToZero: |
| 1500 rounded = trunc(fs); |
| 1501 rounded_int = static_cast<int64_t>(rounded); |
| 1502 break; |
| 1503 case kRoundToPlusInf: |
| 1504 rounded = std::ceil(fs); |
| 1505 rounded_int = static_cast<int64_t>(rounded); |
| 1506 break; |
| 1507 case kRoundToMinusInf: |
| 1508 rounded = std::floor(fs); |
| 1509 rounded_int = static_cast<int64_t>(rounded); |
| 1510 break; |
| 1511 } |
| 1512 } |
| 1513 |
| 1514 |
1430 // Raw access to the PC register. | 1515 // Raw access to the PC register. |
1431 void Simulator::set_pc(int64_t value) { | 1516 void Simulator::set_pc(int64_t value) { |
1432 pc_modified_ = true; | 1517 pc_modified_ = true; |
1433 registers_[pc] = value; | 1518 registers_[pc] = value; |
1434 } | 1519 } |
1435 | 1520 |
1436 | 1521 |
1437 bool Simulator::has_bad_pc() const { | 1522 bool Simulator::has_bad_pc() const { |
1438 return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc)); | 1523 return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc)); |
1439 } | 1524 } |
(...skipping 987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2427 case DEXT: { // Mips32r2 instruction. | 2512 case DEXT: { // Mips32r2 instruction. |
2428 // Interpret rd field as 5-bit msb of extract. | 2513 // Interpret rd field as 5-bit msb of extract. |
2429 uint16_t msb = rd_reg; | 2514 uint16_t msb = rd_reg; |
2430 // Interpret sa field as 5-bit lsb of extract. | 2515 // Interpret sa field as 5-bit lsb of extract. |
2431 uint16_t lsb = sa; | 2516 uint16_t lsb = sa; |
2432 uint16_t size = msb + 1; | 2517 uint16_t size = msb + 1; |
2433 uint64_t mask = (1ULL << size) - 1; | 2518 uint64_t mask = (1ULL << size) - 1; |
2434 *alu_out = static_cast<int64_t>((rs_u & (mask << lsb)) >> lsb); | 2519 *alu_out = static_cast<int64_t>((rs_u & (mask << lsb)) >> lsb); |
2435 break; | 2520 break; |
2436 } | 2521 } |
| 2522 case BITSWAP: { // Mips32r6 instruction |
| 2523 uint32_t input = static_cast<uint32_t>(rt); |
| 2524 uint32_t output = 0; |
| 2525 uint8_t i_byte, o_byte; |
| 2526 |
| 2527 // Reverse the bit in byte for each individual byte |
| 2528 for (int i = 0; i < 4; i++) { |
| 2529 output = output >> 8; |
| 2530 i_byte = input & 0xff; |
| 2531 |
| 2532 // Fast way to reverse bits in byte |
| 2533 // Devised by Sean Anderson, July 13, 2001 |
| 2534 o_byte = static_cast<uint8_t>(((i_byte * 0x0802LU & 0x22110LU) | |
| 2535 (i_byte * 0x8020LU & 0x88440LU)) * |
| 2536 0x10101LU >> |
| 2537 16); |
| 2538 |
| 2539 output = output | (static_cast<uint32_t>(o_byte << 24)); |
| 2540 input = input >> 8; |
| 2541 } |
| 2542 |
| 2543 *alu_out = static_cast<int64_t>(static_cast<int32_t>(output)); |
| 2544 break; |
| 2545 } |
| 2546 case DBITSWAP: { |
| 2547 switch (instr->SaFieldRaw()) { |
| 2548 case DBITSWAP_SA: { // Mips64r6 |
| 2549 uint64_t input = static_cast<uint64_t>(rt); |
| 2550 uint64_t output = 0; |
| 2551 uint8_t i_byte, o_byte; |
| 2552 |
| 2553 // Reverse the bit in byte for each individual byte |
| 2554 for (int i = 0; i < 8; i++) { |
| 2555 output = output >> 8; |
| 2556 i_byte = input & 0xff; |
| 2557 |
| 2558 // Fast way to reverse bits in byte |
| 2559 // Devised by Sean Anderson, July 13, 2001 |
| 2560 o_byte = |
| 2561 static_cast<uint8_t>(((i_byte * 0x0802LU & 0x22110LU) | |
| 2562 (i_byte * 0x8020LU & 0x88440LU)) * |
| 2563 0x10101LU >> |
| 2564 16); |
| 2565 |
| 2566 output = output | ((static_cast<uint64_t>(o_byte) << 56)); |
| 2567 input = input >> 8; |
| 2568 } |
| 2569 |
| 2570 *alu_out = static_cast<int64_t>(output); |
| 2571 break; |
| 2572 } |
| 2573 default: |
| 2574 UNREACHABLE(); |
| 2575 } |
| 2576 break; |
| 2577 } |
2437 default: | 2578 default: |
2438 UNREACHABLE(); | 2579 UNREACHABLE(); |
2439 } | 2580 } |
2440 break; | 2581 break; |
2441 default: | 2582 default: |
2442 UNREACHABLE(); | 2583 UNREACHABLE(); |
2443 } | 2584 } |
2444 } | 2585 } |
2445 | 2586 |
2446 | 2587 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2523 case RSQRT_S: { | 2664 case RSQRT_S: { |
2524 float result = 1.0 / fast_sqrt(fs); | 2665 float result = 1.0 / fast_sqrt(fs); |
2525 set_fpu_register_float(fd_reg, result); | 2666 set_fpu_register_float(fd_reg, result); |
2526 break; | 2667 break; |
2527 } | 2668 } |
2528 case RECIP_S: { | 2669 case RECIP_S: { |
2529 float result = 1.0 / fs; | 2670 float result = 1.0 / fs; |
2530 set_fpu_register_float(fd_reg, result); | 2671 set_fpu_register_float(fd_reg, result); |
2531 break; | 2672 break; |
2532 } | 2673 } |
| 2674 case C_F_D: |
| 2675 set_fcsr_bit(fcsr_cc, false); |
| 2676 break; |
2533 case C_UN_D: | 2677 case C_UN_D: |
2534 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); | 2678 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); |
2535 break; | 2679 break; |
2536 case C_EQ_D: | 2680 case C_EQ_D: |
2537 set_fcsr_bit(fcsr_cc, (fs == ft)); | 2681 set_fcsr_bit(fcsr_cc, (fs == ft)); |
2538 break; | 2682 break; |
2539 case C_UEQ_D: | 2683 case C_UEQ_D: |
2540 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); | 2684 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); |
2541 break; | 2685 break; |
2542 case C_OLT_D: | 2686 case C_OLT_D: |
2543 set_fcsr_bit(fcsr_cc, (fs < ft)); | 2687 set_fcsr_bit(fcsr_cc, (fs < ft)); |
2544 break; | 2688 break; |
2545 case C_ULT_D: | 2689 case C_ULT_D: |
2546 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); | 2690 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); |
2547 break; | 2691 break; |
2548 case C_OLE_D: | 2692 case C_OLE_D: |
2549 set_fcsr_bit(fcsr_cc, (fs <= ft)); | 2693 set_fcsr_bit(fcsr_cc, (fs <= ft)); |
2550 break; | 2694 break; |
2551 case C_ULE_D: | 2695 case C_ULE_D: |
2552 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); | 2696 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); |
2553 break; | 2697 break; |
2554 case CVT_D_S: | 2698 case CVT_D_S: |
2555 set_fpu_register_double(fd_reg, static_cast<double>(fs)); | 2699 set_fpu_register_double(fd_reg, static_cast<double>(fs)); |
2556 break; | 2700 break; |
| 2701 case CLASS_S: { // Mips64r6 instruction |
| 2702 // Convert float input to uint32_t for easier bit manipulation |
| 2703 uint32_t classed = bit_cast<uint32_t>(fs); |
| 2704 |
| 2705 // Extracting sign, exponent and mantissa from the input float |
| 2706 uint32_t sign = (classed >> 31) & 1; |
| 2707 uint32_t exponent = (classed >> 23) & 0x000000ff; |
| 2708 uint32_t mantissa = classed & 0x007fffff; |
| 2709 uint32_t result; |
| 2710 float fResult; |
| 2711 |
| 2712 // Setting flags if input float is negative infinity, |
| 2713 // positive infinity, negative zero or positive zero |
| 2714 bool negInf = (classed == 0xFF800000); |
| 2715 bool posInf = (classed == 0x7F800000); |
| 2716 bool negZero = (classed == 0x80000000); |
| 2717 bool posZero = (classed == 0x00000000); |
| 2718 |
| 2719 bool signalingNan; |
| 2720 bool quietNan; |
| 2721 bool negSubnorm; |
| 2722 bool posSubnorm; |
| 2723 bool negNorm; |
| 2724 bool posNorm; |
| 2725 |
| 2726 // Setting flags if float is NaN |
| 2727 signalingNan = false; |
| 2728 quietNan = false; |
| 2729 if (!negInf && !posInf && (exponent == 0xff)) { |
| 2730 quietNan = ((mantissa & 0x00200000) == 0) && |
| 2731 ((mantissa & (0x00200000 - 1)) == 0); |
| 2732 signalingNan = !quietNan; |
| 2733 } |
| 2734 |
| 2735 // Setting flags if float is subnormal number |
| 2736 posSubnorm = false; |
| 2737 negSubnorm = false; |
| 2738 if ((exponent == 0) && (mantissa != 0)) { |
| 2739 DCHECK(sign == 0 || sign == 1); |
| 2740 posSubnorm = (sign == 0); |
| 2741 negSubnorm = (sign == 1); |
| 2742 } |
| 2743 |
| 2744 // Setting flags if float is normal number |
| 2745 posNorm = false; |
| 2746 negNorm = false; |
| 2747 if (!posSubnorm && !negSubnorm && !posInf && !negInf && !signalingNan && |
| 2748 !quietNan && !negZero && !posZero) { |
| 2749 DCHECK(sign == 0 || sign == 1); |
| 2750 posNorm = (sign == 0); |
| 2751 negNorm = (sign == 1); |
| 2752 } |
| 2753 |
| 2754 // Calculating result according to description of CLASS.S instruction |
| 2755 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | |
| 2756 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | |
| 2757 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; |
| 2758 |
| 2759 DCHECK(result != 0); |
| 2760 |
| 2761 fResult = bit_cast<float>(result); |
| 2762 set_fpu_register_float(fd_reg, fResult); |
| 2763 |
| 2764 break; |
| 2765 } |
| 2766 case CVT_L_S: { |
| 2767 float rounded; |
| 2768 int64_t result; |
| 2769 round64_according_to_fcsr(fs, rounded, result, fs); |
| 2770 set_fpu_register(fd_reg, result); |
| 2771 if (set_fcsr_round64_error(fs, rounded)) { |
| 2772 set_fpu_register(fd_reg, kFPU64InvalidResult); |
| 2773 } |
| 2774 break; |
| 2775 } |
| 2776 case CVT_W_S: { |
| 2777 float rounded; |
| 2778 int32_t result; |
| 2779 round_according_to_fcsr(fs, rounded, result, fs); |
| 2780 set_fpu_register_word(fd_reg, result); |
| 2781 if (set_fcsr_round_error(fs, rounded)) { |
| 2782 set_fpu_register_word(fd_reg, kFPUInvalidResult); |
| 2783 } |
| 2784 break; |
| 2785 } |
2557 case TRUNC_W_S: { // Truncate single to word (round towards 0). | 2786 case TRUNC_W_S: { // Truncate single to word (round towards 0). |
2558 float rounded = trunc(fs); | 2787 float rounded = trunc(fs); |
2559 int32_t result = static_cast<int32_t>(rounded); | 2788 int32_t result = static_cast<int32_t>(rounded); |
2560 set_fpu_register_word(fd_reg, result); | 2789 set_fpu_register_word(fd_reg, result); |
2561 if (set_fcsr_round_error(fs, rounded)) { | 2790 if (set_fcsr_round_error(fs, rounded)) { |
2562 set_fpu_register_word(fd_reg, kFPUInvalidResult); | 2791 set_fpu_register_word(fd_reg, kFPUInvalidResult); |
2563 } | 2792 } |
2564 } break; | 2793 } break; |
2565 case TRUNC_L_S: { // Mips64r2 instruction. | 2794 case TRUNC_L_S: { // Mips64r2 instruction. |
2566 float rounded = trunc(fs); | 2795 float rounded = trunc(fs); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2744 if (instr->Bit(16)) { // Read Tf bit. | 2973 if (instr->Bit(16)) { // Read Tf bit. |
2745 // MOVT.D | 2974 // MOVT.D |
2746 if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg, fs); | 2975 if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg, fs); |
2747 } else { | 2976 } else { |
2748 // MOVF.D | 2977 // MOVF.D |
2749 if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg, fs); | 2978 if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg, fs); |
2750 } | 2979 } |
2751 break; | 2980 break; |
2752 } | 2981 } |
2753 default: | 2982 default: |
2754 // CVT_W_S CVT_L_S TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S | 2983 // TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S |
2755 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. | 2984 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. |
2756 UNREACHABLE(); | 2985 UNREACHABLE(); |
2757 } | 2986 } |
2758 } | 2987 } |
2759 | 2988 |
2760 | 2989 |
2761 void Simulator::DecodeTypeRegisterDRsType(Instruction* instr, | 2990 void Simulator::DecodeTypeRegisterDRsType(Instruction* instr, |
2762 const int32_t& fs_reg, | 2991 const int32_t& fs_reg, |
2763 const int32_t& ft_reg, | 2992 const int32_t& ft_reg, |
2764 const int32_t& fd_reg) { | 2993 const int32_t& fd_reg) { |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3030 } break; | 3259 } break; |
3031 case CVT_S_D: // Convert double to float (single). | 3260 case CVT_S_D: // Convert double to float (single). |
3032 set_fpu_register_float(fd_reg, static_cast<float>(fs)); | 3261 set_fpu_register_float(fd_reg, static_cast<float>(fs)); |
3033 break; | 3262 break; |
3034 case CVT_L_D: { // Mips64r2: Truncate double to 64-bit long-word. | 3263 case CVT_L_D: { // Mips64r2: Truncate double to 64-bit long-word. |
3035 double rounded; | 3264 double rounded; |
3036 int64_t result; | 3265 int64_t result; |
3037 round64_according_to_fcsr(fs, rounded, result, fs); | 3266 round64_according_to_fcsr(fs, rounded, result, fs); |
3038 set_fpu_register(fd_reg, result); | 3267 set_fpu_register(fd_reg, result); |
3039 if (set_fcsr_round64_error(fs, rounded)) { | 3268 if (set_fcsr_round64_error(fs, rounded)) { |
3040 set_fpu_register(fd_reg, kFPUInvalidResult); | 3269 set_fpu_register(fd_reg, kFPU64InvalidResult); |
3041 } | 3270 } |
3042 break; | 3271 break; |
3043 } | 3272 } |
3044 case ROUND_L_D: { // Mips64r2 instruction. | 3273 case ROUND_L_D: { // Mips64r2 instruction. |
3045 double rounded = std::floor(fs + 0.5); | 3274 double rounded = std::floor(fs + 0.5); |
3046 int64_t result = static_cast<int64_t>(rounded); | 3275 int64_t result = static_cast<int64_t>(rounded); |
3047 if ((result & 1) != 0 && result - fs == 0.5) { | 3276 if ((result & 1) != 0 && result - fs == 0.5) { |
3048 // If the number is halfway between two integers, | 3277 // If the number is halfway between two integers, |
3049 // round to the even one. | 3278 // round to the even one. |
3050 result--; | 3279 result--; |
(...skipping 25 matching lines...) Expand all Loading... |
3076 } | 3305 } |
3077 case CEIL_L_D: { // Mips64r2 instruction. | 3306 case CEIL_L_D: { // Mips64r2 instruction. |
3078 double rounded = ceil(fs); | 3307 double rounded = ceil(fs); |
3079 int64_t result = static_cast<int64_t>(rounded); | 3308 int64_t result = static_cast<int64_t>(rounded); |
3080 set_fpu_register(fd_reg, result); | 3309 set_fpu_register(fd_reg, result); |
3081 if (set_fcsr_round64_error(fs, rounded)) { | 3310 if (set_fcsr_round64_error(fs, rounded)) { |
3082 set_fpu_register(fd_reg, kFPU64InvalidResult); | 3311 set_fpu_register(fd_reg, kFPU64InvalidResult); |
3083 } | 3312 } |
3084 break; | 3313 break; |
3085 } | 3314 } |
3086 case C_F_D: | 3315 case CLASS_D: { // Mips64r6 instruction |
3087 UNIMPLEMENTED_MIPS(); | 3316 // Convert double input to uint64_t for easier bit manipulation |
| 3317 uint64_t classed = bit_cast<uint64_t>(fs); |
| 3318 |
| 3319 // Extracting sign, exponent and mantissa from the input double |
| 3320 uint32_t sign = (classed >> 63) & 1; |
| 3321 uint32_t exponent = (classed >> 52) & 0x00000000000007ff; |
| 3322 uint64_t mantissa = classed & 0x000fffffffffffff; |
| 3323 uint64_t result; |
| 3324 double dResult; |
| 3325 |
| 3326 // Setting flags if input double is negative infinity, |
| 3327 // positive infinity, negative zero or positive zero |
| 3328 bool negInf = (classed == 0xFFF0000000000000); |
| 3329 bool posInf = (classed == 0x7FF0000000000000); |
| 3330 bool negZero = (classed == 0x8000000000000000); |
| 3331 bool posZero = (classed == 0x0000000000000000); |
| 3332 |
| 3333 bool signalingNan; |
| 3334 bool quietNan; |
| 3335 bool negSubnorm; |
| 3336 bool posSubnorm; |
| 3337 bool negNorm; |
| 3338 bool posNorm; |
| 3339 |
| 3340 // Setting flags if double is NaN |
| 3341 signalingNan = false; |
| 3342 quietNan = false; |
| 3343 if (!negInf && !posInf && exponent == 0x7ff) { |
| 3344 quietNan = ((mantissa & 0x0008000000000000) != 0) && |
| 3345 ((mantissa & (0x0008000000000000 - 1)) == 0); |
| 3346 signalingNan = !quietNan; |
| 3347 } |
| 3348 |
| 3349 // Setting flags if double is subnormal number |
| 3350 posSubnorm = false; |
| 3351 negSubnorm = false; |
| 3352 if ((exponent == 0) && (mantissa != 0)) { |
| 3353 DCHECK(sign == 0 || sign == 1); |
| 3354 posSubnorm = (sign == 0); |
| 3355 negSubnorm = (sign == 1); |
| 3356 } |
| 3357 |
| 3358 // Setting flags if double is normal number |
| 3359 posNorm = false; |
| 3360 negNorm = false; |
| 3361 if (!posSubnorm && !negSubnorm && !posInf && !negInf && !signalingNan && |
| 3362 !quietNan && !negZero && !posZero) { |
| 3363 DCHECK(sign == 0 || sign == 1); |
| 3364 posNorm = (sign == 0); |
| 3365 negNorm = (sign == 1); |
| 3366 } |
| 3367 |
| 3368 // Calculating result according to description of CLASS.D instruction |
| 3369 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | |
| 3370 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | |
| 3371 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; |
| 3372 |
| 3373 DCHECK(result != 0); |
| 3374 |
| 3375 dResult = bit_cast<double>(result); |
| 3376 set_fpu_register_double(fd_reg, dResult); |
| 3377 |
3088 break; | 3378 break; |
| 3379 } |
| 3380 case C_F_D: { |
| 3381 set_fcsr_bit(fcsr_cc, false); |
| 3382 break; |
| 3383 } |
3089 default: | 3384 default: |
3090 UNREACHABLE(); | 3385 UNREACHABLE(); |
3091 } | 3386 } |
3092 } | 3387 } |
3093 | 3388 |
3094 | 3389 |
3095 void Simulator::DecodeTypeRegisterWRsType(Instruction* instr, | 3390 void Simulator::DecodeTypeRegisterWRsType(Instruction* instr, |
3096 const int32_t& fs_reg, | 3391 const int32_t& fs_reg, |
3097 const int32_t& fd_reg, | 3392 const int32_t& fd_reg, |
| 3393 const int32_t& ft_reg, |
3098 int64_t& alu_out) { | 3394 int64_t& alu_out) { |
| 3395 float fs = get_fpu_register_float(fs_reg); |
| 3396 float ft = get_fpu_register_float(ft_reg); |
3099 switch (instr->FunctionFieldRaw()) { | 3397 switch (instr->FunctionFieldRaw()) { |
3100 case CVT_S_W: // Convert word to float (single). | 3398 case CVT_S_W: // Convert word to float (single). |
3101 alu_out = get_fpu_register_signed_word(fs_reg); | 3399 alu_out = get_fpu_register_signed_word(fs_reg); |
3102 set_fpu_register_float(fd_reg, static_cast<float>(alu_out)); | 3400 set_fpu_register_float(fd_reg, static_cast<float>(alu_out)); |
3103 break; | 3401 break; |
3104 case CVT_D_W: // Convert word to double. | 3402 case CVT_D_W: // Convert word to double. |
3105 alu_out = get_fpu_register_signed_word(fs_reg); | 3403 alu_out = get_fpu_register_signed_word(fs_reg); |
3106 set_fpu_register_double(fd_reg, static_cast<double>(alu_out)); | 3404 set_fpu_register_double(fd_reg, static_cast<double>(alu_out)); |
3107 break; | 3405 break; |
3108 default: // Mips64r6 CMP.S instructions unimplemented. | 3406 case CMP_AF: |
| 3407 set_fpu_register_word(fd_reg, 0); |
| 3408 break; |
| 3409 case CMP_UN: |
| 3410 if (std::isnan(fs) || std::isnan(ft)) { |
| 3411 set_fpu_register_word(fd_reg, -1); |
| 3412 } else { |
| 3413 set_fpu_register_word(fd_reg, 0); |
| 3414 } |
| 3415 break; |
| 3416 case CMP_EQ: |
| 3417 if (fs == ft) { |
| 3418 set_fpu_register_word(fd_reg, -1); |
| 3419 } else { |
| 3420 set_fpu_register_word(fd_reg, 0); |
| 3421 } |
| 3422 break; |
| 3423 case CMP_UEQ: |
| 3424 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3425 set_fpu_register_word(fd_reg, -1); |
| 3426 } else { |
| 3427 set_fpu_register_word(fd_reg, 0); |
| 3428 } |
| 3429 break; |
| 3430 case CMP_LT: |
| 3431 if (fs < ft) { |
| 3432 set_fpu_register_word(fd_reg, -1); |
| 3433 } else { |
| 3434 set_fpu_register_word(fd_reg, 0); |
| 3435 } |
| 3436 break; |
| 3437 case CMP_ULT: |
| 3438 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3439 set_fpu_register_word(fd_reg, -1); |
| 3440 } else { |
| 3441 set_fpu_register_word(fd_reg, 0); |
| 3442 } |
| 3443 break; |
| 3444 case CMP_LE: |
| 3445 if (fs <= ft) { |
| 3446 set_fpu_register_word(fd_reg, -1); |
| 3447 } else { |
| 3448 set_fpu_register_word(fd_reg, 0); |
| 3449 } |
| 3450 break; |
| 3451 case CMP_ULE: |
| 3452 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3453 set_fpu_register_word(fd_reg, -1); |
| 3454 } else { |
| 3455 set_fpu_register_word(fd_reg, 0); |
| 3456 } |
| 3457 break; |
| 3458 case CMP_OR: |
| 3459 if (!std::isnan(fs) && !std::isnan(ft)) { |
| 3460 set_fpu_register_word(fd_reg, -1); |
| 3461 } else { |
| 3462 set_fpu_register_word(fd_reg, 0); |
| 3463 } |
| 3464 break; |
| 3465 case CMP_UNE: |
| 3466 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3467 set_fpu_register_word(fd_reg, -1); |
| 3468 } else { |
| 3469 set_fpu_register_word(fd_reg, 0); |
| 3470 } |
| 3471 break; |
| 3472 case CMP_NE: |
| 3473 if (fs != ft) { |
| 3474 set_fpu_register_word(fd_reg, -1); |
| 3475 } else { |
| 3476 set_fpu_register_word(fd_reg, 0); |
| 3477 } |
| 3478 break; |
| 3479 default: |
3109 UNREACHABLE(); | 3480 UNREACHABLE(); |
3110 } | 3481 } |
3111 } | 3482 } |
3112 | 3483 |
3113 | 3484 |
3114 void Simulator::DecodeTypeRegisterLRsType(Instruction* instr, | 3485 void Simulator::DecodeTypeRegisterLRsType(Instruction* instr, |
3115 const int32_t& fs_reg, | 3486 const int32_t& fs_reg, |
3116 const int32_t& fd_reg, | 3487 const int32_t& fd_reg, |
3117 const int32_t& ft_reg) { | 3488 const int32_t& ft_reg) { |
3118 double fs = get_fpu_register_double(fs_reg); | 3489 double fs = get_fpu_register_double(fs_reg); |
3119 double ft = get_fpu_register_double(ft_reg); | 3490 double ft = get_fpu_register_double(ft_reg); |
3120 int64_t i64; | 3491 int64_t i64; |
3121 switch (instr->FunctionFieldRaw()) { | 3492 switch (instr->FunctionFieldRaw()) { |
3122 case CVT_D_L: // Mips32r2 instruction. | 3493 case CVT_D_L: // Mips32r2 instruction. |
3123 i64 = get_fpu_register(fs_reg); | 3494 i64 = get_fpu_register(fs_reg); |
3124 set_fpu_register_double(fd_reg, static_cast<double>(i64)); | 3495 set_fpu_register_double(fd_reg, static_cast<double>(i64)); |
3125 break; | 3496 break; |
3126 case CVT_S_L: | 3497 case CVT_S_L: |
3127 UNIMPLEMENTED_MIPS(); | 3498 i64 = get_fpu_register(fs_reg); |
| 3499 set_fpu_register_float(fd_reg, static_cast<float>(i64)); |
3128 break; | 3500 break; |
3129 case CMP_AF: // Mips64r6 CMP.D instructions. | 3501 case CMP_AF: |
3130 UNIMPLEMENTED_MIPS(); | 3502 set_fpu_register(fd_reg, 0); |
3131 break; | 3503 break; |
3132 case CMP_UN: | 3504 case CMP_UN: |
3133 if (std::isnan(fs) || std::isnan(ft)) { | 3505 if (std::isnan(fs) || std::isnan(ft)) { |
3134 set_fpu_register(fd_reg, -1); | 3506 set_fpu_register(fd_reg, -1); |
3135 } else { | 3507 } else { |
3136 set_fpu_register(fd_reg, 0); | 3508 set_fpu_register(fd_reg, 0); |
3137 } | 3509 } |
3138 break; | 3510 break; |
3139 case CMP_EQ: | 3511 case CMP_EQ: |
3140 if (fs == ft) { | 3512 if (fs == ft) { |
(...skipping 30 matching lines...) Expand all Loading... |
3171 set_fpu_register(fd_reg, 0); | 3543 set_fpu_register(fd_reg, 0); |
3172 } | 3544 } |
3173 break; | 3545 break; |
3174 case CMP_ULE: | 3546 case CMP_ULE: |
3175 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { | 3547 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { |
3176 set_fpu_register(fd_reg, -1); | 3548 set_fpu_register(fd_reg, -1); |
3177 } else { | 3549 } else { |
3178 set_fpu_register(fd_reg, 0); | 3550 set_fpu_register(fd_reg, 0); |
3179 } | 3551 } |
3180 break; | 3552 break; |
3181 default: // CMP_OR CMP_UNE CMP_NE UNIMPLEMENTED | 3553 case CMP_OR: |
| 3554 if (!std::isnan(fs) && !std::isnan(ft)) { |
| 3555 set_fpu_register(fd_reg, -1); |
| 3556 } else { |
| 3557 set_fpu_register(fd_reg, 0); |
| 3558 } |
| 3559 break; |
| 3560 case CMP_UNE: |
| 3561 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3562 set_fpu_register(fd_reg, -1); |
| 3563 } else { |
| 3564 set_fpu_register(fd_reg, 0); |
| 3565 } |
| 3566 break; |
| 3567 case CMP_NE: |
| 3568 if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) { |
| 3569 set_fpu_register(fd_reg, -1); |
| 3570 } else { |
| 3571 set_fpu_register(fd_reg, 0); |
| 3572 } |
| 3573 break; |
| 3574 default: |
3182 UNREACHABLE(); | 3575 UNREACHABLE(); |
3183 } | 3576 } |
3184 } | 3577 } |
3185 | 3578 |
3186 | 3579 |
3187 void Simulator::DecodeTypeRegisterCOP1( | 3580 void Simulator::DecodeTypeRegisterCOP1( |
3188 Instruction* instr, const int32_t& rs_reg, const int64_t& rs, | 3581 Instruction* instr, const int32_t& rs_reg, const int64_t& rs, |
3189 const uint64_t& rs_u, const int32_t& rt_reg, const int64_t& rt, | 3582 const uint64_t& rs_u, const int32_t& rt_reg, const int64_t& rt, |
3190 const uint64_t& rt_u, const int32_t& rd_reg, const int32_t& fr_reg, | 3583 const uint64_t& rt_u, const int32_t& rd_reg, const int32_t& fr_reg, |
3191 const int32_t& fs_reg, const int32_t& ft_reg, const int32_t& fd_reg, | 3584 const int32_t& fs_reg, const int32_t& ft_reg, const int32_t& fd_reg, |
(...skipping 28 matching lines...) Expand all Loading... |
3220 case MTHC1: | 3613 case MTHC1: |
3221 set_fpu_register_hi_word(fs_reg, registers_[rt_reg]); | 3614 set_fpu_register_hi_word(fs_reg, registers_[rt_reg]); |
3222 break; | 3615 break; |
3223 case S: | 3616 case S: |
3224 DecodeTypeRegisterSRsType(instr, fs_reg, ft_reg, fd_reg); | 3617 DecodeTypeRegisterSRsType(instr, fs_reg, ft_reg, fd_reg); |
3225 break; | 3618 break; |
3226 case D: | 3619 case D: |
3227 DecodeTypeRegisterDRsType(instr, fs_reg, ft_reg, fd_reg); | 3620 DecodeTypeRegisterDRsType(instr, fs_reg, ft_reg, fd_reg); |
3228 break; | 3621 break; |
3229 case W: | 3622 case W: |
3230 DecodeTypeRegisterWRsType(instr, fs_reg, fd_reg, alu_out); | 3623 DecodeTypeRegisterWRsType(instr, fs_reg, fd_reg, ft_reg, alu_out); |
3231 break; | 3624 break; |
3232 case L: | 3625 case L: |
3233 DecodeTypeRegisterLRsType(instr, fs_reg, fd_reg, ft_reg); | 3626 DecodeTypeRegisterLRsType(instr, fs_reg, fd_reg, ft_reg); |
3234 break; | 3627 break; |
3235 default: | 3628 default: |
3236 UNREACHABLE(); | 3629 UNREACHABLE(); |
3237 } | 3630 } |
3238 } | 3631 } |
3239 | 3632 |
3240 | 3633 |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3439 set_register(HI, Unpredictable); | 3832 set_register(HI, Unpredictable); |
3440 break; | 3833 break; |
3441 default: // For other special2 opcodes we do the default operation. | 3834 default: // For other special2 opcodes we do the default operation. |
3442 set_register(rd_reg, alu_out); | 3835 set_register(rd_reg, alu_out); |
3443 } | 3836 } |
3444 } | 3837 } |
3445 | 3838 |
3446 | 3839 |
3447 void Simulator::DecodeTypeRegisterSPECIAL3(Instruction* instr, | 3840 void Simulator::DecodeTypeRegisterSPECIAL3(Instruction* instr, |
3448 const int64_t& rt_reg, | 3841 const int64_t& rt_reg, |
| 3842 const int64_t& rd_reg, |
3449 int64_t& alu_out) { | 3843 int64_t& alu_out) { |
3450 switch (instr->FunctionFieldRaw()) { | 3844 switch (instr->FunctionFieldRaw()) { |
3451 case INS: | 3845 case INS: |
3452 // Ins instr leaves result in Rt, rather than Rd. | 3846 // Ins instr leaves result in Rt, rather than Rd. |
3453 set_register(rt_reg, alu_out); | 3847 set_register(rt_reg, alu_out); |
3454 TraceRegWr(alu_out); | 3848 TraceRegWr(alu_out); |
3455 break; | 3849 break; |
3456 case EXT: | 3850 case EXT: |
3457 case DEXT: | 3851 case DEXT: |
3458 // Dext/Ext instr leaves result in Rt, rather than Rd. | 3852 // Dext/Ext instr leaves result in Rt, rather than Rd. |
3459 set_register(rt_reg, alu_out); | 3853 set_register(rt_reg, alu_out); |
3460 TraceRegWr(alu_out); | 3854 TraceRegWr(alu_out); |
3461 break; | 3855 break; |
| 3856 case BITSWAP: |
| 3857 case DBITSWAP: |
| 3858 set_register(rd_reg, alu_out); |
| 3859 TraceRegWr(alu_out); |
| 3860 break; |
3462 default: | 3861 default: |
3463 UNREACHABLE(); | 3862 UNREACHABLE(); |
3464 } | 3863 } |
3465 } | 3864 } |
3466 | 3865 |
3467 | 3866 |
3468 void Simulator::DecodeTypeRegister(Instruction* instr) { | 3867 void Simulator::DecodeTypeRegister(Instruction* instr) { |
3469 // Instruction fields. | 3868 // Instruction fields. |
3470 const Opcode op = instr->OpcodeFieldRaw(); | 3869 const Opcode op = instr->OpcodeFieldRaw(); |
3471 const int64_t rs_reg = instr->RsValue(); | 3870 const int64_t rs_reg = instr->RsValue(); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3527 case SPECIAL: | 3926 case SPECIAL: |
3528 DecodeTypeRegisterSPECIAL( | 3927 DecodeTypeRegisterSPECIAL( |
3529 instr, rs_reg, rs, rs_u, rt_reg, rt, rt_u, rd_reg, fr_reg, fs_reg, | 3928 instr, rs_reg, rs, rs_u, rt_reg, rt, rt_u, rd_reg, fr_reg, fs_reg, |
3530 ft_reg, fd_reg, i64hilo, u64hilo, alu_out, do_interrupt, current_pc, | 3929 ft_reg, fd_reg, i64hilo, u64hilo, alu_out, do_interrupt, current_pc, |
3531 next_pc, return_addr_reg, i128resultH, i128resultL); | 3930 next_pc, return_addr_reg, i128resultH, i128resultL); |
3532 break; | 3931 break; |
3533 case SPECIAL2: | 3932 case SPECIAL2: |
3534 DecodeTypeRegisterSPECIAL2(instr, rd_reg, alu_out); | 3933 DecodeTypeRegisterSPECIAL2(instr, rd_reg, alu_out); |
3535 break; | 3934 break; |
3536 case SPECIAL3: | 3935 case SPECIAL3: |
3537 DecodeTypeRegisterSPECIAL3(instr, rt_reg, alu_out); | 3936 DecodeTypeRegisterSPECIAL3(instr, rt_reg, rd_reg, alu_out); |
3538 break; | 3937 break; |
3539 // Unimplemented opcodes raised an error in the configuration step before, | 3938 // Unimplemented opcodes raised an error in the configuration step before, |
3540 // so we can use the default here to set the destination register in common | 3939 // so we can use the default here to set the destination register in common |
3541 // cases. | 3940 // cases. |
3542 default: | 3941 default: |
3543 set_register(rd_reg, alu_out); | 3942 set_register(rd_reg, alu_out); |
3544 TraceRegWr(alu_out); | 3943 TraceRegWr(alu_out); |
3545 } | 3944 } |
3546 } | 3945 } |
3547 | 3946 |
(...skipping 632 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4180 return address; | 4579 return address; |
4181 } | 4580 } |
4182 | 4581 |
4183 | 4582 |
4184 #undef UNSUPPORTED | 4583 #undef UNSUPPORTED |
4185 } } // namespace v8::internal | 4584 } } // namespace v8::internal |
4186 | 4585 |
4187 #endif // USE_SIMULATOR | 4586 #endif // USE_SIMULATOR |
4188 | 4587 |
4189 #endif // V8_TARGET_ARCH_MIPS64 | 4588 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |