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

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

Issue 1145223002: MIPS: Add float instructions and test coverage, part two (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addressed comments 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/mips/simulator-mips.h ('k') | src/mips64/assembler-mips64.h » ('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 1284 matching lines...) Expand 10 before | Expand all | Expand 10 after
1295 void Simulator::set_fcsr_rounding_mode(FPURoundingMode mode) { 1295 void Simulator::set_fcsr_rounding_mode(FPURoundingMode mode) {
1296 FCSR_ |= mode & kFPURoundingModeMask; 1296 FCSR_ |= mode & kFPURoundingModeMask;
1297 } 1297 }
1298 1298
1299 1299
1300 unsigned int Simulator::get_fcsr_rounding_mode() { 1300 unsigned int Simulator::get_fcsr_rounding_mode() {
1301 return FCSR_ & kFPURoundingModeMask; 1301 return FCSR_ & kFPURoundingModeMask;
1302 } 1302 }
1303 1303
1304 1304
1305 // Sets the rounding error codes in FCSR based on the result of the rounding.
1306 // Returns true if the operation was invalid.
1305 bool Simulator::set_fcsr_round_error(double original, double rounded) { 1307 bool Simulator::set_fcsr_round_error(double original, double rounded) {
1306 bool ret = false; 1308 bool ret = false;
1307 double max_int32 = std::numeric_limits<int32_t>::max(); 1309 double max_int32 = std::numeric_limits<int32_t>::max();
1308 double min_int32 = std::numeric_limits<int32_t>::min(); 1310 double min_int32 = std::numeric_limits<int32_t>::min();
1309 1311
1310 if (!std::isfinite(original) || !std::isfinite(rounded)) { 1312 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1311 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1313 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1312 ret = true; 1314 ret = true;
1313 } 1315 }
1314 1316
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1357 set_fcsr_bit(kFCSROverflowFlagBit, true); 1359 set_fcsr_bit(kFCSROverflowFlagBit, true);
1358 // The reference is not really clear but it seems this is required: 1360 // The reference is not really clear but it seems this is required:
1359 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1361 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1360 ret = true; 1362 ret = true;
1361 } 1363 }
1362 1364
1363 return ret; 1365 return ret;
1364 } 1366 }
1365 1367
1366 1368
1369 // Sets the rounding error codes in FCSR based on the result of the rounding.
1370 // Returns true if the operation was invalid.
1367 bool Simulator::set_fcsr_round_error(float original, float rounded) { 1371 bool Simulator::set_fcsr_round_error(float original, float rounded) {
1368 bool ret = false; 1372 bool ret = false;
1369 double max_int32 = std::numeric_limits<int32_t>::max(); 1373 double max_int32 = std::numeric_limits<int32_t>::max();
1370 double min_int32 = std::numeric_limits<int32_t>::min(); 1374 double min_int32 = std::numeric_limits<int32_t>::min();
1371 1375
1372 if (!std::isfinite(original) || !std::isfinite(rounded)) { 1376 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1373 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1377 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1374 ret = true; 1378 ret = true;
1375 } 1379 }
1376 1380
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1460 rounded_int = static_cast<int32_t>(rounded); 1464 rounded_int = static_cast<int32_t>(rounded);
1461 break; 1465 break;
1462 case kRoundToMinusInf: 1466 case kRoundToMinusInf:
1463 rounded = std::floor(fs); 1467 rounded = std::floor(fs);
1464 rounded_int = static_cast<int32_t>(rounded); 1468 rounded_int = static_cast<int32_t>(rounded);
1465 break; 1469 break;
1466 } 1470 }
1467 } 1471 }
1468 1472
1469 1473
1474 void Simulator::round_according_to_fcsr(float toRound, float& rounded,
1475 int32_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 RD (round down, or toward −infinity): Round a result to
1488 // the next representable value down. Behave like floor_w_d.
1489 switch (get_fcsr_rounding_mode()) {
1490 case kRoundToNearest:
1491 rounded = std::floor(fs + 0.5);
1492 rounded_int = static_cast<int32_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<int32_t>(rounded);
1502 break;
1503 case kRoundToPlusInf:
1504 rounded = std::ceil(fs);
1505 rounded_int = static_cast<int32_t>(rounded);
1506 break;
1507 case kRoundToMinusInf:
1508 rounded = std::floor(fs);
1509 rounded_int = static_cast<int32_t>(rounded);
1510 break;
1511 }
1512 }
1513
1514
1515 void Simulator::round64_according_to_fcsr(double toRound, double& rounded,
1516 int64_t& rounded_int, double fs) {
1517 // 0 RN (round to nearest): Round a result to the nearest
1518 // representable value; if the result is exactly halfway between
1519 // two representable values, round to zero. Behave like round_w_d.
1520
1521 // 1 RZ (round toward zero): Round a result to the closest
1522 // representable value whose absolute value is less than or.
1523 // equal to the infinitely accurate result. Behave like trunc_w_d.
1524
1525 // 2 RP (round up, or toward +infinity): Round a result to the
1526 // next representable value up. Behave like ceil_w_d.
1527
1528 // 3 RN (round down, or toward −infinity): Round a result to
1529 // the next representable value down. Behave like floor_w_d.
1530 switch (FCSR_ & 3) {
1531 case kRoundToNearest:
1532 rounded = std::floor(fs + 0.5);
1533 rounded_int = static_cast<int64_t>(rounded);
1534 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
1535 // If the number is halfway between two integers,
1536 // round to the even one.
1537 rounded_int--;
1538 }
1539 break;
1540 case kRoundToZero:
1541 rounded = trunc(fs);
1542 rounded_int = static_cast<int64_t>(rounded);
1543 break;
1544 case kRoundToPlusInf:
1545 rounded = std::ceil(fs);
1546 rounded_int = static_cast<int64_t>(rounded);
1547 break;
1548 case kRoundToMinusInf:
1549 rounded = std::floor(fs);
1550 rounded_int = static_cast<int64_t>(rounded);
1551 break;
1552 }
1553 }
1554
1555
1556 void Simulator::round64_according_to_fcsr(float toRound, float& rounded,
1557 int64_t& rounded_int, float fs) {
1558 // 0 RN (round to nearest): Round a result to the nearest
1559 // representable value; if the result is exactly halfway between
1560 // two representable values, round to zero. Behave like round_w_d.
1561
1562 // 1 RZ (round toward zero): Round a result to the closest
1563 // representable value whose absolute value is less than or.
1564 // equal to the infinitely accurate result. Behave like trunc_w_d.
1565
1566 // 2 RP (round up, or toward +infinity): Round a result to the
1567 // next representable value up. Behave like ceil_w_d.
1568
1569 // 3 RN (round down, or toward −infinity): Round a result to
1570 // the next representable value down. Behave like floor_w_d.
1571 switch (FCSR_ & 3) {
1572 case kRoundToNearest:
1573 rounded = std::floor(fs + 0.5);
1574 rounded_int = static_cast<int64_t>(rounded);
1575 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
1576 // If the number is halfway between two integers,
1577 // round to the even one.
1578 rounded_int--;
1579 }
1580 break;
1581 case kRoundToZero:
1582 rounded = trunc(fs);
1583 rounded_int = static_cast<int64_t>(rounded);
1584 break;
1585 case kRoundToPlusInf:
1586 rounded = std::ceil(fs);
1587 rounded_int = static_cast<int64_t>(rounded);
1588 break;
1589 case kRoundToMinusInf:
1590 rounded = std::floor(fs);
1591 rounded_int = static_cast<int64_t>(rounded);
1592 break;
1593 }
1594 }
1595
1596
1470 // Raw access to the PC register. 1597 // Raw access to the PC register.
1471 void Simulator::set_pc(int32_t value) { 1598 void Simulator::set_pc(int32_t value) {
1472 pc_modified_ = true; 1599 pc_modified_ = true;
1473 registers_[pc] = value; 1600 registers_[pc] = value;
1474 } 1601 }
1475 1602
1476 1603
1477 bool Simulator::has_bad_pc() const { 1604 bool Simulator::has_bad_pc() const {
1478 return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc)); 1605 return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc));
1479 } 1606 }
(...skipping 797 matching lines...) Expand 10 before | Expand all | Expand 10 after
2277 case EXT: { // Mips32r2 instruction. 2404 case EXT: { // Mips32r2 instruction.
2278 // Interpret rd field as 5-bit msb of extract. 2405 // Interpret rd field as 5-bit msb of extract.
2279 uint16_t msb = rd_reg; 2406 uint16_t msb = rd_reg;
2280 // Interpret sa field as 5-bit lsb of extract. 2407 // Interpret sa field as 5-bit lsb of extract.
2281 uint16_t lsb = sa; 2408 uint16_t lsb = sa;
2282 uint16_t size = msb + 1; 2409 uint16_t size = msb + 1;
2283 uint32_t mask = (1 << size) - 1; 2410 uint32_t mask = (1 << size) - 1;
2284 *alu_out = (rs_u & (mask << lsb)) >> lsb; 2411 *alu_out = (rs_u & (mask << lsb)) >> lsb;
2285 break; 2412 break;
2286 } 2413 }
2414 case BITSWAP: { // Mips32r6 instruction
2415 uint32_t input = static_cast<uint32_t>(rt);
2416 uint32_t output = 0;
2417 uint8_t i_byte, o_byte;
2418
2419 // Reverse the bit in byte for each individual byte
2420 for (int i = 0; i < 4; i++) {
2421 output = output >> 8;
2422 i_byte = input & 0xff;
2423
2424 // Fast way to reverse bits in byte
2425 // Devised by Sean Anderson, July 13, 2001
2426 o_byte = static_cast<uint8_t>(((i_byte * 0x0802LU & 0x22110LU) |
2427 (i_byte * 0x8020LU & 0x88440LU)) *
2428 0x10101LU >>
2429 16);
2430
2431 output = output | (static_cast<uint32_t>(o_byte << 24));
2432 input = input >> 8;
2433 }
2434
2435 *alu_out = static_cast<int32_t>(output);
2436 break;
2437 }
2287 default: 2438 default:
2288 UNREACHABLE(); 2439 UNREACHABLE();
2289 } 2440 }
2290 break; 2441 break;
2291 default: 2442 default:
2292 UNREACHABLE(); 2443 UNREACHABLE();
2293 } 2444 }
2294 } 2445 }
2295 2446
2296 2447
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
2563 int32_t result = static_cast<int32_t>(rounded); 2714 int32_t result = static_cast<int32_t>(rounded);
2564 set_fpu_register_word(fd_reg, result); 2715 set_fpu_register_word(fd_reg, result);
2565 if (set_fcsr_round_error(fs, rounded)) { 2716 if (set_fcsr_round_error(fs, rounded)) {
2566 set_fpu_register_word(fd_reg, kFPUInvalidResult); 2717 set_fpu_register_word(fd_reg, kFPUInvalidResult);
2567 } 2718 }
2568 } break; 2719 } break;
2569 case CVT_S_D: // Convert double to float (single). 2720 case CVT_S_D: // Convert double to float (single).
2570 set_fpu_register_float(fd_reg, static_cast<float>(fs)); 2721 set_fpu_register_float(fd_reg, static_cast<float>(fs));
2571 break; 2722 break;
2572 case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word. 2723 case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word.
2573 double rounded = trunc(fs);
2574 i64 = static_cast<int64_t>(rounded);
2575 if (IsFp64Mode()) { 2724 if (IsFp64Mode()) {
2576 set_fpu_register(fd_reg, i64); 2725 int64_t result;
2726 double rounded;
2727 round64_according_to_fcsr(fs, rounded, result, fs);
2728 set_fpu_register(fd_reg, result);
2729 if (set_fcsr_round64_error(fs, rounded)) {
2730 set_fpu_register(fd_reg, kFPU64InvalidResult);
2731 }
2577 } else { 2732 } else {
2578 UNSUPPORTED(); 2733 UNSUPPORTED();
2579 } 2734 }
2580 break; 2735 break;
2736 break;
2581 } 2737 }
2582 case TRUNC_L_D: { // Mips32r2 instruction. 2738 case TRUNC_L_D: { // Mips32r2 instruction.
2583 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); 2739 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2584 double rounded = trunc(fs); 2740 double rounded = trunc(fs);
2585 i64 = static_cast<int64_t>(rounded); 2741 i64 = static_cast<int64_t>(rounded);
2586 if (IsFp64Mode()) { 2742 if (IsFp64Mode()) {
2587 set_fpu_register(fd_reg, i64); 2743 set_fpu_register(fd_reg, i64);
2588 if (set_fcsr_round64_error(fs, rounded)) { 2744 if (set_fcsr_round64_error(fs, rounded)) {
2589 set_fpu_register(fd_reg, kFPU64InvalidResult); 2745 set_fpu_register(fd_reg, kFPU64InvalidResult);
2590 } 2746 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2634 if (IsFp64Mode()) { 2790 if (IsFp64Mode()) {
2635 set_fpu_register(fd_reg, i64); 2791 set_fpu_register(fd_reg, i64);
2636 if (set_fcsr_round64_error(fs, rounded)) { 2792 if (set_fcsr_round64_error(fs, rounded)) {
2637 set_fpu_register(fd_reg, kFPU64InvalidResult); 2793 set_fpu_register(fd_reg, kFPU64InvalidResult);
2638 } 2794 }
2639 } else { 2795 } else {
2640 UNSUPPORTED(); 2796 UNSUPPORTED();
2641 } 2797 }
2642 break; 2798 break;
2643 } 2799 }
2644 case C_F_D: 2800 case CLASS_D: { // Mips32r6 instruction
2645 UNIMPLEMENTED_MIPS(); 2801 // Convert double input to uint64_t for easier bit manipulation
2802 uint64_t classed = bit_cast<uint64_t>(fs);
2803
2804 // Extracting sign, exponent and mantissa from the input double
2805 uint32_t sign = (classed >> 63) & 1;
2806 uint32_t exponent = (classed >> 52) & 0x00000000000007ff;
2807 uint64_t mantissa = classed & 0x000fffffffffffff;
2808 uint64_t result;
2809 double dResult;
2810
2811 // Setting flags if input double is negative infinity,
2812 // positive infinity, negative zero or positive zero
2813 bool negInf = (classed == 0xFFF0000000000000);
2814 bool posInf = (classed == 0x7FF0000000000000);
2815 bool negZero = (classed == 0x8000000000000000);
2816 bool posZero = (classed == 0x0000000000000000);
2817
2818 bool signalingNan;
2819 bool quietNan;
2820 bool negSubnorm;
2821 bool posSubnorm;
2822 bool negNorm;
2823 bool posNorm;
2824
2825 // Setting flags if double is NaN
2826 signalingNan = false;
2827 quietNan = false;
2828 if (!negInf && !posInf && exponent == 0x7ff) {
2829 quietNan = ((mantissa & 0x0008000000000000) != 0) &&
2830 ((mantissa & (0x0008000000000000 - 1)) == 0);
2831 signalingNan = !quietNan;
2832 }
2833
2834 // Setting flags if double is subnormal number
2835 posSubnorm = false;
2836 negSubnorm = false;
2837 if ((exponent == 0) && (mantissa != 0)) {
2838 DCHECK(sign == 0 || sign == 1);
2839 posSubnorm = (sign == 0);
2840 negSubnorm = (sign == 1);
2841 }
2842
2843 // Setting flags if double is normal number
2844 posNorm = false;
2845 negNorm = false;
2846 if (!posSubnorm && !negSubnorm && !posInf && !negInf && !signalingNan &&
2847 !quietNan && !negZero && !posZero) {
2848 DCHECK(sign == 0 || sign == 1);
2849 posNorm = (sign == 0);
2850 negNorm = (sign == 1);
2851 }
2852
2853 // Calculating result according to description of CLASS.D instruction
2854 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) |
2855 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) |
2856 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan;
2857
2858 DCHECK(result != 0);
2859
2860 dResult = bit_cast<double>(result);
2861 set_fpu_register_double(fd_reg, dResult);
2862
2646 break; 2863 break;
2864 }
2865 case C_F_D: {
2866 set_fcsr_bit(fcsr_cc, false);
2867 break;
2868 }
2647 default: 2869 default:
2648 UNREACHABLE(); 2870 UNREACHABLE();
2649 } 2871 }
2650 } 2872 }
2651 2873
2652 2874
2653 void Simulator::DecodeTypeRegisterWRsType(Instruction* instr, int32_t& alu_out, 2875 void Simulator::DecodeTypeRegisterWRsType(Instruction* instr, int32_t& alu_out,
2654 const int32_t& fd_reg, 2876 const int32_t& fd_reg,
2655 const int32_t& fs_reg) { 2877 const int32_t& fs_reg,
2878 const int32_t& ft_reg) {
2879 float fs = get_fpu_register_float(fs_reg);
2880 float ft = get_fpu_register_float(ft_reg);
2656 switch (instr->FunctionFieldRaw()) { 2881 switch (instr->FunctionFieldRaw()) {
2657 case CVT_S_W: // Convert word to float (single). 2882 case CVT_S_W: // Convert word to float (single).
2658 alu_out = get_fpu_register_signed_word(fs_reg); 2883 alu_out = get_fpu_register_signed_word(fs_reg);
2659 set_fpu_register_float(fd_reg, static_cast<float>(alu_out)); 2884 set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
2660 break; 2885 break;
2661 case CVT_D_W: // Convert word to double. 2886 case CVT_D_W: // Convert word to double.
2662 alu_out = get_fpu_register_signed_word(fs_reg); 2887 alu_out = get_fpu_register_signed_word(fs_reg);
2663 set_fpu_register_double(fd_reg, static_cast<double>(alu_out)); 2888 set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
2664 break; 2889 break;
2665 default: // Mips64r6 CMP.S instructions unimplemented. 2890 case CMP_AF:
2891 set_fpu_register_word(fd_reg, 0);
2892 break;
2893 case CMP_UN:
2894 if (std::isnan(fs) || std::isnan(ft)) {
2895 set_fpu_register_word(fd_reg, -1);
2896 } else {
2897 set_fpu_register_word(fd_reg, 0);
2898 }
2899 break;
2900 case CMP_EQ:
2901 if (fs == ft) {
2902 set_fpu_register_word(fd_reg, -1);
2903 } else {
2904 set_fpu_register_word(fd_reg, 0);
2905 }
2906 break;
2907 case CMP_UEQ:
2908 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
2909 set_fpu_register_word(fd_reg, -1);
2910 } else {
2911 set_fpu_register_word(fd_reg, 0);
2912 }
2913 break;
2914 case CMP_LT:
2915 if (fs < ft) {
2916 set_fpu_register_word(fd_reg, -1);
2917 } else {
2918 set_fpu_register_word(fd_reg, 0);
2919 }
2920 break;
2921 case CMP_ULT:
2922 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
2923 set_fpu_register_word(fd_reg, -1);
2924 } else {
2925 set_fpu_register_word(fd_reg, 0);
2926 }
2927 break;
2928 case CMP_LE:
2929 if (fs <= ft) {
2930 set_fpu_register_word(fd_reg, -1);
2931 } else {
2932 set_fpu_register_word(fd_reg, 0);
2933 }
2934 break;
2935 case CMP_ULE:
2936 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
2937 set_fpu_register_word(fd_reg, -1);
2938 } else {
2939 set_fpu_register_word(fd_reg, 0);
2940 }
2941 break;
2942 case CMP_OR:
2943 if (!std::isnan(fs) && !std::isnan(ft)) {
2944 set_fpu_register_word(fd_reg, -1);
2945 } else {
2946 set_fpu_register_word(fd_reg, 0);
2947 }
2948 break;
2949 case CMP_UNE:
2950 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) {
2951 set_fpu_register_word(fd_reg, -1);
2952 } else {
2953 set_fpu_register_word(fd_reg, 0);
2954 }
2955 break;
2956 case CMP_NE:
2957 if (fs != ft) {
2958 set_fpu_register_word(fd_reg, -1);
2959 } else {
2960 set_fpu_register_word(fd_reg, 0);
2961 }
2962 break;
2963 default:
2666 UNREACHABLE(); 2964 UNREACHABLE();
2667 } 2965 }
2668 } 2966 }
2669 2967
2670 2968
2671 void Simulator::DecodeTypeRegisterSRsType(Instruction* instr, 2969 void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
2672 const int32_t& ft_reg, 2970 const int32_t& ft_reg,
2673 const int32_t& fs_reg, 2971 const int32_t& fs_reg,
2674 const int32_t& fd_reg) { 2972 const int32_t& fd_reg) {
2675 float fs, ft, fd; 2973 float fs, ft, fd;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
2747 case RSQRT_S: { 3045 case RSQRT_S: {
2748 float result = 1.0 / fast_sqrt(fs); 3046 float result = 1.0 / fast_sqrt(fs);
2749 set_fpu_register_float(fd_reg, result); 3047 set_fpu_register_float(fd_reg, result);
2750 break; 3048 break;
2751 } 3049 }
2752 case RECIP_S: { 3050 case RECIP_S: {
2753 float result = 1.0 / fs; 3051 float result = 1.0 / fs;
2754 set_fpu_register_float(fd_reg, result); 3052 set_fpu_register_float(fd_reg, result);
2755 break; 3053 break;
2756 } 3054 }
3055 case C_F_D:
3056 set_fcsr_bit(fcsr_cc, false);
3057 break;
2757 case C_UN_D: 3058 case C_UN_D:
2758 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); 3059 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2759 break; 3060 break;
2760 case C_EQ_D: 3061 case C_EQ_D:
2761 set_fcsr_bit(fcsr_cc, (fs == ft)); 3062 set_fcsr_bit(fcsr_cc, (fs == ft));
2762 break; 3063 break;
2763 case C_UEQ_D: 3064 case C_UEQ_D:
2764 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); 3065 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2765 break; 3066 break;
2766 case C_OLT_D: 3067 case C_OLT_D:
2767 set_fcsr_bit(fcsr_cc, (fs < ft)); 3068 set_fcsr_bit(fcsr_cc, (fs < ft));
2768 break; 3069 break;
2769 case C_ULT_D: 3070 case C_ULT_D:
2770 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); 3071 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
2771 break; 3072 break;
2772 case C_OLE_D: 3073 case C_OLE_D:
2773 set_fcsr_bit(fcsr_cc, (fs <= ft)); 3074 set_fcsr_bit(fcsr_cc, (fs <= ft));
2774 break; 3075 break;
2775 case C_ULE_D: 3076 case C_ULE_D:
2776 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); 3077 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
2777 break; 3078 break;
2778 case CVT_D_S: 3079 case CVT_D_S:
2779 set_fpu_register_double(fd_reg, static_cast<double>(fs)); 3080 set_fpu_register_double(fd_reg, static_cast<double>(fs));
2780 break; 3081 break;
2781 case SEL: 3082 case SEL:
2782 DCHECK(IsMipsArchVariant(kMips32r6)); 3083 DCHECK(IsMipsArchVariant(kMips32r6));
2783 set_fpu_register_float(fd_reg, (fd_int & 0x1) == 0 ? fs : ft); 3084 set_fpu_register_float(fd_reg, (fd_int & 0x1) == 0 ? fs : ft);
2784 break; 3085 break;
3086 case CLASS_S: { // Mips32r6 instruction
3087 // Convert float input to uint32_t for easier bit manipulation
3088 float fs = get_fpu_register_float(fs_reg);
3089 uint32_t classed = bit_cast<uint32_t>(fs);
3090
3091 // Extracting sign, exponent and mantissa from the input float
3092 uint32_t sign = (classed >> 31) & 1;
3093 uint32_t exponent = (classed >> 23) & 0x000000ff;
3094 uint32_t mantissa = classed & 0x007fffff;
3095 uint32_t result;
3096 float fResult;
3097
3098 // Setting flags if input float is negative infinity,
3099 // positive infinity, negative zero or positive zero
3100 bool negInf = (classed == 0xFF800000);
3101 bool posInf = (classed == 0x7F800000);
3102 bool negZero = (classed == 0x80000000);
3103 bool posZero = (classed == 0x00000000);
3104
3105 bool signalingNan;
3106 bool quietNan;
3107 bool negSubnorm;
3108 bool posSubnorm;
3109 bool negNorm;
3110 bool posNorm;
3111
3112 // Setting flags if float is NaN
3113 signalingNan = false;
3114 quietNan = false;
3115 if (!negInf && !posInf && (exponent == 0xff)) {
3116 quietNan = ((mantissa & 0x00200000) == 0) &&
3117 ((mantissa & (0x00200000 - 1)) == 0);
3118 signalingNan = !quietNan;
3119 }
3120
3121 // Setting flags if float is subnormal number
3122 posSubnorm = false;
3123 negSubnorm = false;
3124 if ((exponent == 0) && (mantissa != 0)) {
3125 DCHECK(sign == 0 || sign == 1);
3126 posSubnorm = (sign == 0);
3127 negSubnorm = (sign == 1);
3128 }
3129
3130 // Setting flags if float is normal number
3131 posNorm = false;
3132 negNorm = false;
3133 if (!posSubnorm && !negSubnorm && !posInf && !negInf && !signalingNan &&
3134 !quietNan && !negZero && !posZero) {
3135 DCHECK(sign == 0 || sign == 1);
3136 posNorm = (sign == 0);
3137 negNorm = (sign == 1);
3138 }
3139
3140 // Calculating result according to description of CLASS.S instruction
3141 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) |
3142 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) |
3143 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan;
3144
3145 DCHECK(result != 0);
3146
3147 fResult = bit_cast<float>(result);
3148 set_fpu_register_float(fd_reg, fResult);
3149
3150 break;
3151 }
2785 case SELEQZ_C: 3152 case SELEQZ_C:
2786 DCHECK(IsMipsArchVariant(kMips32r6)); 3153 DCHECK(IsMipsArchVariant(kMips32r6));
2787 set_fpu_register_float( 3154 set_fpu_register_float(
2788 fd_reg, (ft_int & 0x1) == 0 ? get_fpu_register_float(fs_reg) : 0.0); 3155 fd_reg, (ft_int & 0x1) == 0 ? get_fpu_register_float(fs_reg) : 0.0);
2789 break; 3156 break;
2790 case SELNEZ_C: 3157 case SELNEZ_C:
2791 DCHECK(IsMipsArchVariant(kMips32r6)); 3158 DCHECK(IsMipsArchVariant(kMips32r6));
2792 set_fpu_register_float( 3159 set_fpu_register_float(
2793 fd_reg, (ft_int & 0x1) != 0 ? get_fpu_register_float(fs_reg) : 0.0); 3160 fd_reg, (ft_int & 0x1) != 0 ? get_fpu_register_float(fs_reg) : 0.0);
2794 break; 3161 break;
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
2987 if (fabs(fs) < fabs(ft)) { 3354 if (fabs(fs) < fabs(ft)) {
2988 result = ft; 3355 result = ft;
2989 } else if (fabs(fs) > fabs(ft)) { 3356 } else if (fabs(fs) > fabs(ft)) {
2990 result = fs; 3357 result = fs;
2991 } else { 3358 } else {
2992 result = (fs > ft ? fs : ft); 3359 result = (fs > ft ? fs : ft);
2993 } 3360 }
2994 set_fpu_register_float(fd_reg, result); 3361 set_fpu_register_float(fd_reg, result);
2995 } 3362 }
2996 break; 3363 break;
3364 case CVT_L_S: {
3365 if (IsFp64Mode()) {
3366 int64_t result;
3367 float rounded;
3368 round64_according_to_fcsr(fs, rounded, result, fs);
3369 set_fpu_register(fd_reg, result);
3370 if (set_fcsr_round64_error(fs, rounded)) {
3371 set_fpu_register(fd_reg, kFPU64InvalidResult);
3372 }
3373 } else {
3374 UNSUPPORTED();
3375 }
3376 break;
3377 }
3378 case CVT_W_S: {
3379 float rounded;
3380 int32_t result;
3381 round_according_to_fcsr(fs, rounded, result, fs);
3382 set_fpu_register_word(fd_reg, result);
3383 if (set_fcsr_round_error(fs, rounded)) {
3384 set_fpu_register_word(fd_reg, kFPUInvalidResult);
3385 }
3386 break;
3387 }
2997 default: 3388 default:
2998 // CVT_W_S CVT_L_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S 3389 // CVT_W_S CVT_L_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S
2999 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. 3390 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented.
3000 UNREACHABLE(); 3391 UNREACHABLE();
3001 } 3392 }
3002 } 3393 }
3003 3394
3004 3395
3005 void Simulator::DecodeTypeRegisterLRsType(Instruction* instr, 3396 void Simulator::DecodeTypeRegisterLRsType(Instruction* instr,
3006 const int32_t& ft_reg, 3397 const int32_t& ft_reg,
3007 const int32_t& fs_reg, 3398 const int32_t& fs_reg,
3008 const int32_t& fd_reg) { 3399 const int32_t& fd_reg) {
3009 double fs = get_fpu_register_double(fs_reg); 3400 double fs = get_fpu_register_double(fs_reg);
3010 double ft = get_fpu_register_double(ft_reg); 3401 double ft = get_fpu_register_double(ft_reg);
3011 switch (instr->FunctionFieldRaw()) { 3402 switch (instr->FunctionFieldRaw()) {
3012 case CVT_D_L: // Mips32r2 instruction. 3403 case CVT_D_L: // Mips32r2 instruction.
3013 // Watch the signs here, we want 2 32-bit vals 3404 // Watch the signs here, we want 2 32-bit vals
3014 // to make a sign-64. 3405 // to make a sign-64.
3015 int64_t i64; 3406 int64_t i64;
3016 if (IsFp64Mode()) { 3407 if (IsFp64Mode()) {
3017 i64 = get_fpu_register(fs_reg); 3408 i64 = get_fpu_register(fs_reg);
3018 } else { 3409 } else {
3019 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg)); 3410 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg));
3020 i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg + 1)) << 32; 3411 i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg + 1)) << 32;
3021 } 3412 }
3022 set_fpu_register_double(fd_reg, static_cast<double>(i64)); 3413 set_fpu_register_double(fd_reg, static_cast<double>(i64));
3023 break; 3414 break;
3024 case CVT_S_L: 3415 case CVT_S_L:
3025 UNIMPLEMENTED_MIPS(); 3416 if (IsFp64Mode()) {
3417 i64 = get_fpu_register(fs_reg);
3418 } else {
3419 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg));
3420 i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg + 1)) << 32;
3421 }
3422 set_fpu_register_float(fd_reg, static_cast<float>(i64));
3026 break; 3423 break;
3027 case CMP_AF: // Mips64r6 CMP.D instructions. 3424 case CMP_AF: // Mips64r6 CMP.D instructions.
3028 UNIMPLEMENTED_MIPS(); 3425 set_fpu_register(fd_reg, 0);
3029 break; 3426 break;
3030 case CMP_UN: 3427 case CMP_UN:
3031 if (std::isnan(fs) || std::isnan(ft)) { 3428 if (std::isnan(fs) || std::isnan(ft)) {
3032 set_fpu_register(fd_reg, -1); 3429 set_fpu_register(fd_reg, -1);
3033 } else { 3430 } else {
3034 set_fpu_register(fd_reg, 0); 3431 set_fpu_register(fd_reg, 0);
3035 } 3432 }
3036 break; 3433 break;
3037 case CMP_EQ: 3434 case CMP_EQ:
3038 if (fs == ft) { 3435 if (fs == ft) {
(...skipping 30 matching lines...) Expand all
3069 set_fpu_register(fd_reg, 0); 3466 set_fpu_register(fd_reg, 0);
3070 } 3467 }
3071 break; 3468 break;
3072 case CMP_ULE: 3469 case CMP_ULE:
3073 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { 3470 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
3074 set_fpu_register(fd_reg, -1); 3471 set_fpu_register(fd_reg, -1);
3075 } else { 3472 } else {
3076 set_fpu_register(fd_reg, 0); 3473 set_fpu_register(fd_reg, 0);
3077 } 3474 }
3078 break; 3475 break;
3079 default: // CMP_OR CMP_UNE CMP_NE UNIMPLEMENTED. 3476 case CMP_OR:
3477 if (!std::isnan(fs) && !std::isnan(ft)) {
3478 set_fpu_register(fd_reg, -1);
3479 } else {
3480 set_fpu_register(fd_reg, 0);
3481 }
3482 break;
3483 case CMP_UNE:
3484 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) {
3485 set_fpu_register(fd_reg, -1);
3486 } else {
3487 set_fpu_register(fd_reg, 0);
3488 }
3489 break;
3490 case CMP_NE:
3491 if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) {
3492 set_fpu_register(fd_reg, -1);
3493 } else {
3494 set_fpu_register(fd_reg, 0);
3495 }
3496 break;
3497 default:
3080 UNREACHABLE(); 3498 UNREACHABLE();
3081 } 3499 }
3082 } 3500 }
3083 3501
3084 3502
3085 void Simulator::DecodeTypeRegisterCOP1( 3503 void Simulator::DecodeTypeRegisterCOP1(
3086 Instruction* instr, const int32_t& rs_reg, const int32_t& rs, 3504 Instruction* instr, const int32_t& rs_reg, const int32_t& rs,
3087 const uint32_t& rs_u, const int32_t& rt_reg, const int32_t& rt, 3505 const uint32_t& rs_u, const int32_t& rt_reg, const int32_t& rt,
3088 const uint32_t& rt_u, const int32_t& rd_reg, const int32_t& fr_reg, 3506 const uint32_t& rt_u, const int32_t& rd_reg, const int32_t& fr_reg,
3089 const int32_t& fs_reg, const int32_t& ft_reg, const int32_t& fd_reg, 3507 const int32_t& fs_reg, const int32_t& ft_reg, const int32_t& fd_reg,
(...skipping 23 matching lines...) Expand all
3113 set_fpu_register_hi_word(fs_reg, registers_[rt_reg]); 3531 set_fpu_register_hi_word(fs_reg, registers_[rt_reg]);
3114 break; 3532 break;
3115 case S: { 3533 case S: {
3116 DecodeTypeRegisterSRsType(instr, ft_reg, fs_reg, fd_reg); 3534 DecodeTypeRegisterSRsType(instr, ft_reg, fs_reg, fd_reg);
3117 break; 3535 break;
3118 } 3536 }
3119 case D: 3537 case D:
3120 DecodeTypeRegisterDRsType(instr, fr_reg, fs_reg, ft_reg, fd_reg); 3538 DecodeTypeRegisterDRsType(instr, fr_reg, fs_reg, ft_reg, fd_reg);
3121 break; 3539 break;
3122 case W: 3540 case W:
3123 DecodeTypeRegisterWRsType(instr, alu_out, fd_reg, fs_reg); 3541 DecodeTypeRegisterWRsType(instr, alu_out, fd_reg, fs_reg, ft_reg);
3124 break; 3542 break;
3125 case L: 3543 case L:
3126 DecodeTypeRegisterLRsType(instr, ft_reg, fs_reg, fd_reg); 3544 DecodeTypeRegisterLRsType(instr, ft_reg, fs_reg, fd_reg);
3127 break; 3545 break;
3128 default: 3546 default:
3129 UNREACHABLE(); 3547 UNREACHABLE();
3130 } 3548 }
3131 } 3549 }
3132 3550
3133 3551
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
3328 set_register(HI, Unpredictable); 3746 set_register(HI, Unpredictable);
3329 break; 3747 break;
3330 default: // For other special2 opcodes we do the default operation. 3748 default: // For other special2 opcodes we do the default operation.
3331 set_register(rd_reg, alu_out); 3749 set_register(rd_reg, alu_out);
3332 } 3750 }
3333 } 3751 }
3334 3752
3335 3753
3336 void Simulator::DecodeTypeRegisterSPECIAL3(Instruction* instr, 3754 void Simulator::DecodeTypeRegisterSPECIAL3(Instruction* instr,
3337 const int32_t& rt_reg, 3755 const int32_t& rt_reg,
3756 const int32_t& rd_reg,
3338 int32_t& alu_out) { 3757 int32_t& alu_out) {
3339 switch (instr->FunctionFieldRaw()) { 3758 switch (instr->FunctionFieldRaw()) {
3340 case INS: 3759 case INS:
3341 // Ins instr leaves result in Rt, rather than Rd. 3760 // Ins instr leaves result in Rt, rather than Rd.
3342 set_register(rt_reg, alu_out); 3761 set_register(rt_reg, alu_out);
3343 break; 3762 break;
3344 case EXT: 3763 case EXT:
3345 // Ext instr leaves result in Rt, rather than Rd. 3764 // Ext instr leaves result in Rt, rather than Rd.
3346 set_register(rt_reg, alu_out); 3765 set_register(rt_reg, alu_out);
3347 break; 3766 break;
3767 case BITSWAP:
3768 set_register(rd_reg, alu_out);
3769 break;
3348 default: 3770 default:
3349 UNREACHABLE(); 3771 UNREACHABLE();
3350 } 3772 }
3351 } 3773 }
3352 3774
3353 3775
3354 void Simulator::DecodeTypeRegister(Instruction* instr) { 3776 void Simulator::DecodeTypeRegister(Instruction* instr) {
3355 // Instruction fields. 3777 // Instruction fields.
3356 const Opcode op = instr->OpcodeFieldRaw(); 3778 const Opcode op = instr->OpcodeFieldRaw();
3357 const int32_t rs_reg = instr->RsValue(); 3779 const int32_t rs_reg = instr->RsValue();
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
3405 case SPECIAL: 3827 case SPECIAL:
3406 DecodeTypeRegisterSPECIAL(instr, rs_reg, rs, rs_u, rt_reg, rt, rt_u, 3828 DecodeTypeRegisterSPECIAL(instr, rs_reg, rs, rs_u, rt_reg, rt, rt_u,
3407 rd_reg, fr_reg, fs_reg, ft_reg, fd_reg, i64hilo, 3829 rd_reg, fr_reg, fs_reg, ft_reg, fd_reg, i64hilo,
3408 u64hilo, alu_out, do_interrupt, current_pc, 3830 u64hilo, alu_out, do_interrupt, current_pc,
3409 next_pc, return_addr_reg); 3831 next_pc, return_addr_reg);
3410 break; 3832 break;
3411 case SPECIAL2: 3833 case SPECIAL2:
3412 DecodeTypeRegisterSPECIAL2(instr, rd_reg, alu_out); 3834 DecodeTypeRegisterSPECIAL2(instr, rd_reg, alu_out);
3413 break; 3835 break;
3414 case SPECIAL3: 3836 case SPECIAL3:
3415 DecodeTypeRegisterSPECIAL3(instr, rt_reg, alu_out); 3837 DecodeTypeRegisterSPECIAL3(instr, rt_reg, rd_reg, alu_out);
3416 break; 3838 break;
3417 // Unimplemented opcodes raised an error in the configuration step before, 3839 // Unimplemented opcodes raised an error in the configuration step before,
3418 // so we can use the default here to set the destination register in common 3840 // so we can use the default here to set the destination register in common
3419 // cases. 3841 // cases.
3420 default: 3842 default:
3421 set_register(rd_reg, alu_out); 3843 set_register(rd_reg, alu_out);
3422 } 3844 }
3423 } 3845 }
3424 3846
3425 3847
(...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after
4009 } 4431 }
4010 4432
4011 4433
4012 #undef UNSUPPORTED 4434 #undef UNSUPPORTED
4013 4435
4014 } } // namespace v8::internal 4436 } } // namespace v8::internal
4015 4437
4016 #endif // USE_SIMULATOR 4438 #endif // USE_SIMULATOR
4017 4439
4018 #endif // V8_TARGET_ARCH_MIPS 4440 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « src/mips/simulator-mips.h ('k') | src/mips64/assembler-mips64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698