OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <limits.h> | 5 #include <limits.h> |
6 #include <stdarg.h> | 6 #include <stdarg.h> |
7 #include <stdlib.h> | 7 #include <stdlib.h> |
8 #include <cmath> | 8 #include <cmath> |
9 | 9 |
10 #include "src/v8.h" | 10 #include "src/v8.h" |
(...skipping 1170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |