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

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

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