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

Side by Side Diff: src/mips64/simulator-mips64.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/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 1264 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
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
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
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
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
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