 Chromium Code Reviews
 Chromium Code Reviews Issue 1119203003:
  MIPS: Add float instructions and test coverage, part one  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master
    
  
    Issue 1119203003:
  MIPS: Add float instructions and test coverage, part one  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master| 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) { FCSR_ |= mode; } | |
| 
paul.l...
2015/05/09 01:07:48
As you did in previous CL for mips32, please use t
 
Djordje.Pesic
2015/05/14 13:22:31
Done.
 | |
| 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 Loading... | |
| 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 | |
| 
paul.l...
2015/05/09 01:07:48
I like the comments that you have on the set_fcsr_
 
Djordje.Pesic
2015/05/14 13:22:31
Done.
 | |
| 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 Loading... | |
| 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. | |
| 
paul.l...
2015/05/09 01:07:48
mips64r2.
We don't support earlier than mips64r2,
 
Djordje.Pesic
2015/05/14 13:22:31
Done.
 | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 | 
| OLD | NEW |