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

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

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

Powered by Google App Engine
This is Rietveld 408576698