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

Side by Side Diff: src/mips/simulator-mips.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 1264 matching lines...) Expand 10 before | Expand all | Expand 10 after
1275 void Simulator::set_fcsr_rounding_mode(FPURoundingMode mode) { 1275 void Simulator::set_fcsr_rounding_mode(FPURoundingMode mode) {
1276 FCSR_ |= mode & kFPURoundingModeMask; 1276 FCSR_ |= mode & kFPURoundingModeMask;
1277 } 1277 }
1278 1278
1279 1279
1280 unsigned int Simulator::get_fcsr_rounding_mode() { 1280 unsigned int Simulator::get_fcsr_rounding_mode() {
1281 return FCSR_ & kFPURoundingModeMask; 1281 return FCSR_ & kFPURoundingModeMask;
1282 } 1282 }
1283 1283
1284 1284
1285 // Sets the rounding error codes in FCSR based on the result of the rounding.
1286 // Returns true if the operation was invalid.
1287 bool Simulator::set_fcsr_round_error(double original, double rounded) { 1285 bool Simulator::set_fcsr_round_error(double original, double rounded) {
1288 bool ret = false; 1286 bool ret = false;
1289 double max_int32 = std::numeric_limits<int32_t>::max(); 1287 double max_int32 = std::numeric_limits<int32_t>::max();
1290 double min_int32 = std::numeric_limits<int32_t>::min(); 1288 double min_int32 = std::numeric_limits<int32_t>::min();
1291 1289
1292 if (!std::isfinite(original) || !std::isfinite(rounded)) { 1290 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1293 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1291 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1294 ret = true; 1292 ret = true;
1295 } 1293 }
1296 1294
1297 if (original != rounded) { 1295 if (original != rounded) {
1298 set_fcsr_bit(kFCSRInexactFlagBit, true); 1296 set_fcsr_bit(kFCSRInexactFlagBit, true);
1299 } 1297 }
1300 1298
1301 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) { 1299 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1302 set_fcsr_bit(kFCSRUnderflowFlagBit, true); 1300 set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1303 ret = true; 1301 ret = true;
1304 } 1302 }
1305 1303
1306 if (rounded > max_int32 || rounded < min_int32) { 1304 if (rounded >= max_int32 || rounded <= min_int32) {
1307 set_fcsr_bit(kFCSROverflowFlagBit, true); 1305 set_fcsr_bit(kFCSROverflowFlagBit, true);
1308 // The reference is not really clear but it seems this is required: 1306 // The reference is not really clear but it seems this is required:
1309 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1307 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1308 ret = true;
1309 }
1310
1311 return ret;
1312 }
1313
1314
1315 // Sets the rounding error codes in FCSR based on the result of the rounding.
1316 // Returns true if the operation was invalid.
1317 bool Simulator::set_fcsr_round64_error(double original, double rounded) {
1318 bool ret = false;
1319 double max_int64 = std::numeric_limits<int64_t>::max();
1320 double min_int64 = std::numeric_limits<int64_t>::min();
1321
1322 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1323 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1324 ret = true;
1325 }
1326
1327 if (original != rounded) {
1328 set_fcsr_bit(kFCSRInexactFlagBit, true);
1329 }
1330
1331 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1332 set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1333 ret = true;
1334 }
1335
1336 if (rounded >= max_int64 || rounded <= min_int64) {
1337 set_fcsr_bit(kFCSROverflowFlagBit, true);
1338 // The reference is not really clear but it seems this is required:
1339 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1340 ret = true;
1341 }
1342
1343 return ret;
1344 }
1345
1346
1347 bool Simulator::set_fcsr_round_error(float original, float rounded) {
1348 bool ret = false;
1349 double max_int32 = std::numeric_limits<int32_t>::max();
1350 double min_int32 = std::numeric_limits<int32_t>::min();
1351
1352 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1353 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1354 ret = true;
1355 }
1356
1357 if (original != rounded) {
1358 set_fcsr_bit(kFCSRInexactFlagBit, true);
1359 }
1360
1361 if (rounded < FLT_MIN && rounded > -FLT_MIN && rounded != 0) {
1362 set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1363 ret = true;
1364 }
1365
1366 if (rounded >= max_int32 || rounded <= min_int32) {
1367 set_fcsr_bit(kFCSROverflowFlagBit, true);
1368 // The reference is not really clear but it seems this is required:
1369 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1370 ret = true;
1371 }
1372
1373 return ret;
1374 }
1375
1376
1377 // Sets the rounding error codes in FCSR based on the result of the rounding.
1378 // Returns true if the operation was invalid.
1379 bool Simulator::set_fcsr_round64_error(float original, float rounded) {
1380 bool ret = false;
1381 double max_int64 = std::numeric_limits<int64_t>::max();
1382 double min_int64 = std::numeric_limits<int64_t>::min();
1383
1384 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1385 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1386 ret = true;
1387 }
1388
1389 if (original != rounded) {
1390 set_fcsr_bit(kFCSRInexactFlagBit, true);
1391 }
1392
1393 if (rounded < FLT_MIN && rounded > -FLT_MIN && rounded != 0) {
1394 set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1395 ret = true;
1396 }
1397
1398 if (rounded >= max_int64 || rounded <= min_int64) {
1399 set_fcsr_bit(kFCSROverflowFlagBit, true);
1400 // The reference is not really clear but it seems this is required:
1401 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1310 ret = true; 1402 ret = true;
1311 } 1403 }
1312 1404
1313 return ret; 1405 return ret;
1314 } 1406 }
1315 1407
1316 1408
1317 void Simulator::round_according_to_fcsr(double toRound, double& rounded, 1409 void Simulator::round_according_to_fcsr(double toRound, double& rounded,
1318 int32_t& rounded_int, double fs) { 1410 int32_t& rounded_int, double fs) {
1319 // 0 RN (round to nearest): Round a result to the nearest 1411 // 0 RN (round to nearest): Round a result to the nearest
(...skipping 864 matching lines...) Expand 10 before | Expand all | Expand 10 after
2184 2276
2185 void Simulator::DecodeTypeRegisterDRsType(Instruction* instr, 2277 void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
2186 const int32_t& fr_reg, 2278 const int32_t& fr_reg,
2187 const int32_t& fs_reg, 2279 const int32_t& fs_reg,
2188 const int32_t& ft_reg, 2280 const int32_t& ft_reg,
2189 const int32_t& fd_reg) { 2281 const int32_t& fd_reg) {
2190 double ft, fs, fd; 2282 double ft, fs, fd;
2191 uint32_t cc, fcsr_cc; 2283 uint32_t cc, fcsr_cc;
2192 int64_t i64; 2284 int64_t i64;
2193 fs = get_fpu_register_double(fs_reg); 2285 fs = get_fpu_register_double(fs_reg);
2194 ft = get_fpu_register_double(ft_reg); 2286 if (instr->FunctionFieldRaw() != MOVF) {
2287 ft = get_fpu_register_double(ft_reg);
2288 }
2289 fd = get_fpu_register_double(fd_reg);
2195 int64_t ft_int = bit_cast<int64_t>(ft); 2290 int64_t ft_int = bit_cast<int64_t>(ft);
2196 int64_t fd_int = bit_cast<int64_t>(fd); 2291 int64_t fd_int = bit_cast<int64_t>(fd);
2197 cc = instr->FCccValue(); 2292 cc = instr->FCccValue();
2198 fcsr_cc = get_fcsr_condition_bit(cc); 2293 fcsr_cc = get_fcsr_condition_bit(cc);
2199 switch (instr->FunctionFieldRaw()) { 2294 switch (instr->FunctionFieldRaw()) {
2200 case RINT: { 2295 case RINT: {
2201 DCHECK(IsMipsArchVariant(kMips32r6)); 2296 DCHECK(IsMipsArchVariant(kMips32r6));
2202 double result, temp, temp_result; 2297 double result, temp, temp_result;
2203 double upper = std::ceil(fs); 2298 double upper = std::ceil(fs);
2204 double lower = std::floor(fs); 2299 double lower = std::floor(fs);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2239 set_fpu_register_double(fd_reg, (fd_int & 0x1) == 0 ? fs : ft); 2334 set_fpu_register_double(fd_reg, (fd_int & 0x1) == 0 ? fs : ft);
2240 break; 2335 break;
2241 case SELEQZ_C: 2336 case SELEQZ_C:
2242 DCHECK(IsMipsArchVariant(kMips32r6)); 2337 DCHECK(IsMipsArchVariant(kMips32r6));
2243 set_fpu_register_double(fd_reg, (ft_int & 0x1) == 0 ? fs : 0.0); 2338 set_fpu_register_double(fd_reg, (ft_int & 0x1) == 0 ? fs : 0.0);
2244 break; 2339 break;
2245 case SELNEZ_C: 2340 case SELNEZ_C:
2246 DCHECK(IsMipsArchVariant(kMips32r6)); 2341 DCHECK(IsMipsArchVariant(kMips32r6));
2247 set_fpu_register_double(fd_reg, (ft_int & 0x1) != 0 ? fs : 0.0); 2342 set_fpu_register_double(fd_reg, (ft_int & 0x1) != 0 ? fs : 0.0);
2248 break; 2343 break;
2344 case MOVZ_C: {
2345 DCHECK(IsMipsArchVariant(kMips32r2));
2346 int32_t rt_reg = instr->RtValue();
2347 int32_t rt = get_register(rt_reg);
2348 if (rt == 0) {
2349 set_fpu_register_double(fd_reg, fs);
2350 }
2351 break;
2352 }
2353 case MOVN_C: {
2354 DCHECK(IsMipsArchVariant(kMips32r2));
2355 int32_t rt_reg = instr->RtValue();
2356 int32_t rt = get_register(rt_reg);
2357 if (rt != 0) {
2358 set_fpu_register_double(fd_reg, fs);
2359 }
2360 break;
2361 }
2362 case MOVF: {
2363 // Same function field for MOVT.D and MOVF.D
2364 uint32_t ft_cc = (ft_reg >> 2) & 0x7;
2365 ft_cc = get_fcsr_condition_bit(ft_cc);
2366 if (instr->Bit(16)) { // Read Tf bit.
2367 // MOVT.D
2368 if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg, fs);
2369 } else {
2370 // MOVF.D
2371 if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg, fs);
2372 }
2373 break;
2374 }
2249 case MIN: 2375 case MIN:
2250 DCHECK(IsMipsArchVariant(kMips32r6)); 2376 DCHECK(IsMipsArchVariant(kMips32r6));
2251 fs = get_fpu_register_double(fs_reg); 2377 fs = get_fpu_register_double(fs_reg);
2252 if (std::isnan(fs) && std::isnan(ft)) { 2378 if (std::isnan(fs) && std::isnan(ft)) {
2253 set_fpu_register_double(fd_reg, fs); 2379 set_fpu_register_double(fd_reg, fs);
2254 } else if (std::isnan(fs) && !std::isnan(ft)) { 2380 } else if (std::isnan(fs) && !std::isnan(ft)) {
2255 set_fpu_register_double(fd_reg, ft); 2381 set_fpu_register_double(fd_reg, ft);
2256 } else if (!std::isnan(fs) && std::isnan(ft)) { 2382 } else if (!std::isnan(fs) && std::isnan(ft)) {
2257 set_fpu_register_double(fd_reg, fs); 2383 set_fpu_register_double(fd_reg, fs);
2258 } else { 2384 } else {
2259 set_fpu_register_double(fd_reg, (fs >= ft) ? ft : fs); 2385 set_fpu_register_double(fd_reg, (fs >= ft) ? ft : fs);
2260 } 2386 }
2261 break; 2387 break;
2388 case MINA:
2389 DCHECK(IsMipsArchVariant(kMips32r6));
2390 fs = get_fpu_register_double(fs_reg);
2391 if (std::isnan(fs) && std::isnan(ft)) {
2392 set_fpu_register_double(fd_reg, fs);
2393 } else if (std::isnan(fs) && !std::isnan(ft)) {
2394 set_fpu_register_double(fd_reg, ft);
2395 } else if (!std::isnan(fs) && std::isnan(ft)) {
2396 set_fpu_register_double(fd_reg, fs);
2397 } else {
2398 double result;
2399 if (fabs(fs) > fabs(ft)) {
2400 result = ft;
2401 } else if (fabs(fs) < fabs(ft)) {
2402 result = fs;
2403 } else {
2404 result = (fs > ft ? fs : ft);
2405 }
2406 set_fpu_register_double(fd_reg, result);
2407 }
2408 break;
2409 case MAXA:
2410 DCHECK(IsMipsArchVariant(kMips32r6));
2411 fs = get_fpu_register_double(fs_reg);
2412 if (std::isnan(fs) && std::isnan(ft)) {
2413 set_fpu_register_double(fd_reg, fs);
2414 } else if (std::isnan(fs) && !std::isnan(ft)) {
2415 set_fpu_register_double(fd_reg, ft);
2416 } else if (!std::isnan(fs) && std::isnan(ft)) {
2417 set_fpu_register_double(fd_reg, fs);
2418 } else {
2419 double result;
2420 if (fabs(fs) < fabs(ft)) {
2421 result = ft;
2422 } else if (fabs(fs) > fabs(ft)) {
2423 result = fs;
2424 } else {
2425 result = (fs > ft ? fs : ft);
2426 }
2427 set_fpu_register_double(fd_reg, result);
2428 }
2429 break;
2262 case MAX: 2430 case MAX:
2263 DCHECK(IsMipsArchVariant(kMips32r6)); 2431 DCHECK(IsMipsArchVariant(kMips32r6));
2264 fs = get_fpu_register_double(fs_reg); 2432 fs = get_fpu_register_double(fs_reg);
2265 if (std::isnan(fs) && std::isnan(ft)) { 2433 if (std::isnan(fs) && std::isnan(ft)) {
2266 set_fpu_register_double(fd_reg, fs); 2434 set_fpu_register_double(fd_reg, fs);
2267 } else if (std::isnan(fs) && !std::isnan(ft)) { 2435 } else if (std::isnan(fs) && !std::isnan(ft)) {
2268 set_fpu_register_double(fd_reg, ft); 2436 set_fpu_register_double(fd_reg, ft);
2269 } else if (!std::isnan(fs) && std::isnan(ft)) { 2437 } else if (!std::isnan(fs) && std::isnan(ft)) {
2270 set_fpu_register_double(fd_reg, fs); 2438 set_fpu_register_double(fd_reg, fs);
2271 } else { 2439 } else {
(...skipping 18 matching lines...) Expand all
2290 break; 2458 break;
2291 case MOV_D: 2459 case MOV_D:
2292 set_fpu_register_double(fd_reg, fs); 2460 set_fpu_register_double(fd_reg, fs);
2293 break; 2461 break;
2294 case NEG_D: 2462 case NEG_D:
2295 set_fpu_register_double(fd_reg, -fs); 2463 set_fpu_register_double(fd_reg, -fs);
2296 break; 2464 break;
2297 case SQRT_D: 2465 case SQRT_D:
2298 set_fpu_register_double(fd_reg, fast_sqrt(fs)); 2466 set_fpu_register_double(fd_reg, fast_sqrt(fs));
2299 break; 2467 break;
2468 case RSQRT_D: {
2469 double result = 1.0 / fast_sqrt(fs);
2470 set_fpu_register_double(fd_reg, result);
2471 break;
2472 }
2473 case RECIP: {
2474 double result = 1.0 / fs;
2475 set_fpu_register_double(fd_reg, result);
2476 break;
2477 }
2300 case C_UN_D: 2478 case C_UN_D:
2301 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); 2479 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2302 break; 2480 break;
2303 case C_EQ_D: 2481 case C_EQ_D:
2304 set_fcsr_bit(fcsr_cc, (fs == ft)); 2482 set_fcsr_bit(fcsr_cc, (fs == ft));
2305 break; 2483 break;
2306 case C_UEQ_D: 2484 case C_UEQ_D:
2307 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); 2485 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2308 break; 2486 break;
2309 case C_OLT_D: 2487 case C_OLT_D:
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
2380 set_fpu_register_word(fd_reg, i64 & 0xffffffff); 2558 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2381 set_fpu_register_word(fd_reg + 1, i64 >> 32); 2559 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2382 } 2560 }
2383 break; 2561 break;
2384 } 2562 }
2385 case TRUNC_L_D: { // Mips32r2 instruction. 2563 case TRUNC_L_D: { // Mips32r2 instruction.
2386 double rounded = trunc(fs); 2564 double rounded = trunc(fs);
2387 i64 = static_cast<int64_t>(rounded); 2565 i64 = static_cast<int64_t>(rounded);
2388 if (IsFp64Mode()) { 2566 if (IsFp64Mode()) {
2389 set_fpu_register(fd_reg, i64); 2567 set_fpu_register(fd_reg, i64);
2568 if (set_fcsr_round64_error(fs, rounded)) {
2569 set_fpu_register(fd_reg, kFPU64InvalidResult);
2570 }
2390 } else { 2571 } else {
2391 set_fpu_register_word(fd_reg, i64 & 0xffffffff); 2572 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2392 set_fpu_register_word(fd_reg + 1, i64 >> 32); 2573 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2574 if (set_fcsr_round64_error(fs, rounded)) {
2575 set_fpu_register_word(fd_reg, kFPU64InvalidResult & 0xffffffff);
2576 set_fpu_register_word(fd_reg + 1, kFPU64InvalidResult >> 32);
2577 }
2393 } 2578 }
2394 break; 2579 break;
2395 } 2580 }
2396 case ROUND_L_D: { // Mips32r2 instruction. 2581 case ROUND_L_D: { // Mips32r2 instruction.
2397 double rounded = fs > 0 ? std::floor(fs + 0.5) : std::ceil(fs - 0.5); 2582 double rounded = std::floor(fs + 0.5);
2398 i64 = static_cast<int64_t>(rounded); 2583 int64_t result = static_cast<int64_t>(rounded);
2584 if ((result & 1) != 0 && result - fs == 0.5) {
2585 // If the number is halfway between two integers,
2586 // round to the even one.
2587 result--;
2588 }
2589 int64_t i64 = static_cast<int64_t>(result);
2399 if (IsFp64Mode()) { 2590 if (IsFp64Mode()) {
2400 set_fpu_register(fd_reg, i64); 2591 set_fpu_register(fd_reg, i64);
2592 if (set_fcsr_round64_error(fs, rounded)) {
2593 set_fpu_register(fd_reg, kFPU64InvalidResult);
2594 }
2401 } else { 2595 } else {
2402 set_fpu_register_word(fd_reg, i64 & 0xffffffff); 2596 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2403 set_fpu_register_word(fd_reg + 1, i64 >> 32); 2597 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2598 if (set_fcsr_round64_error(fs, rounded)) {
2599 set_fpu_register_word(fd_reg, kFPU64InvalidResult & 0xffffffff);
2600 set_fpu_register_word(fd_reg + 1, kFPU64InvalidResult >> 32);
2601 }
2404 } 2602 }
2405 break; 2603 break;
2406 } 2604 }
2407 case FLOOR_L_D: // Mips32r2 instruction. 2605 case FLOOR_L_D: { // Mips32r2 instruction.
2408 i64 = static_cast<int64_t>(std::floor(fs)); 2606 double rounded = std::floor(fs);
2607 int64_t i64 = static_cast<int64_t>(rounded);
2409 if (IsFp64Mode()) { 2608 if (IsFp64Mode()) {
2410 set_fpu_register(fd_reg, i64); 2609 set_fpu_register(fd_reg, i64);
2610 if (set_fcsr_round64_error(fs, rounded)) {
2611 set_fpu_register(fd_reg, kFPU64InvalidResult);
2612 }
2411 } else { 2613 } else {
2412 set_fpu_register_word(fd_reg, i64 & 0xffffffff); 2614 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2413 set_fpu_register_word(fd_reg + 1, i64 >> 32); 2615 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2616 if (set_fcsr_round64_error(fs, rounded)) {
2617 set_fpu_register_word(fd_reg, kFPU64InvalidResult & 0xffffffff);
2618 set_fpu_register_word(fd_reg + 1, kFPU64InvalidResult >> 32);
2619 }
2414 } 2620 }
2415 break; 2621 break;
2416 case CEIL_L_D: // Mips32r2 instruction. 2622 }
2417 i64 = static_cast<int64_t>(std::ceil(fs)); 2623 case CEIL_L_D: { // Mips32r2 instruction.
2624 double rounded = std::ceil(fs);
2625 int64_t i64 = static_cast<int64_t>(rounded);
2418 if (IsFp64Mode()) { 2626 if (IsFp64Mode()) {
2419 set_fpu_register(fd_reg, i64); 2627 set_fpu_register(fd_reg, i64);
2628 if (set_fcsr_round64_error(fs, rounded)) {
2629 set_fpu_register(fd_reg, kFPU64InvalidResult);
2630 }
2420 } else { 2631 } else {
2421 set_fpu_register_word(fd_reg, i64 & 0xffffffff); 2632 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2422 set_fpu_register_word(fd_reg + 1, i64 >> 32); 2633 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2634 if (set_fcsr_round64_error(fs, rounded)) {
2635 set_fpu_register_word(fd_reg, kFPU64InvalidResult & 0xffffffff);
2636 set_fpu_register_word(fd_reg + 1, kFPU64InvalidResult >> 32);
2637 }
2423 } 2638 }
2424 break; 2639 break;
2640 }
2425 case C_F_D: 2641 case C_F_D:
2426 UNIMPLEMENTED_MIPS(); 2642 UNIMPLEMENTED_MIPS();
2427 break; 2643 break;
2428 default: 2644 default:
2429 UNREACHABLE(); 2645 UNREACHABLE();
2430 } 2646 }
2431 } 2647 }
2432 2648
2433 2649
2434 void Simulator::DecodeTypeRegisterWRsType(Instruction* instr, int32_t& alu_out, 2650 void Simulator::DecodeTypeRegisterWRsType(Instruction* instr, int32_t& alu_out,
(...skipping 11 matching lines...) Expand all
2446 default: // Mips64r6 CMP.S instructions unimplemented. 2662 default: // Mips64r6 CMP.S instructions unimplemented.
2447 UNREACHABLE(); 2663 UNREACHABLE();
2448 } 2664 }
2449 } 2665 }
2450 2666
2451 2667
2452 void Simulator::DecodeTypeRegisterSRsType(Instruction* instr, 2668 void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
2453 const int32_t& ft_reg, 2669 const int32_t& ft_reg,
2454 const int32_t& fs_reg, 2670 const int32_t& fs_reg,
2455 const int32_t& fd_reg) { 2671 const int32_t& fd_reg) {
2456 float fs, ft; 2672 float fs, ft, fd;
2457 fs = get_fpu_register_float(fs_reg); 2673 fs = get_fpu_register_float(fs_reg);
2458 ft = get_fpu_register_float(ft_reg); 2674 ft = get_fpu_register_float(ft_reg);
2459 int64_t ft_int = static_cast<int64_t>(get_fpu_register_double(ft_reg)); 2675 fd = get_fpu_register_float(fd_reg);
2676 int32_t ft_int = bit_cast<int32_t>(ft);
2677 int32_t fd_int = bit_cast<int32_t>(fd);
2460 uint32_t cc, fcsr_cc; 2678 uint32_t cc, fcsr_cc;
2461 cc = instr->FCccValue(); 2679 cc = instr->FCccValue();
2462 fcsr_cc = get_fcsr_condition_bit(cc); 2680 fcsr_cc = get_fcsr_condition_bit(cc);
2463 switch (instr->FunctionFieldRaw()) { 2681 switch (instr->FunctionFieldRaw()) {
2682 case RINT: {
2683 DCHECK(IsMipsArchVariant(kMips32r6));
2684 float result, temp_result;
2685 double temp;
2686 float upper = std::ceil(fs);
2687 float lower = std::floor(fs);
2688 switch (get_fcsr_rounding_mode()) {
2689 case kRoundToNearest:
2690 if (upper - fs < fs - lower) {
2691 result = upper;
2692 } else if (upper - fs > fs - lower) {
2693 result = lower;
2694 } else {
2695 temp_result = upper / 2;
2696 float reminder = modf(temp_result, &temp);
2697 if (reminder == 0) {
2698 result = upper;
2699 } else {
2700 result = lower;
2701 }
2702 }
2703 break;
2704 case kRoundToZero:
2705 result = (fs > 0 ? lower : upper);
2706 break;
2707 case kRoundToPlusInf:
2708 result = upper;
2709 break;
2710 case kRoundToMinusInf:
2711 result = lower;
2712 break;
2713 }
2714 set_fpu_register_float(fd_reg, result);
2715 if (result != fs) {
2716 set_fcsr_bit(kFCSRInexactFlagBit, true);
2717 }
2718 break;
2719 }
2464 case ADD_D: 2720 case ADD_D:
2465 set_fpu_register_float(fd_reg, fs + ft); 2721 set_fpu_register_float(fd_reg, fs + ft);
2466 break; 2722 break;
2467 case SUB_D: 2723 case SUB_D:
2468 set_fpu_register_float(fd_reg, fs - ft); 2724 set_fpu_register_float(fd_reg, fs - ft);
2469 break; 2725 break;
2470 case MUL_D: 2726 case MUL_D:
2471 set_fpu_register_float(fd_reg, fs * ft); 2727 set_fpu_register_float(fd_reg, fs * ft);
2472 break; 2728 break;
2473 case DIV_D: 2729 case DIV_D:
2474 set_fpu_register_float(fd_reg, fs / ft); 2730 set_fpu_register_float(fd_reg, fs / ft);
2475 break; 2731 break;
2476 case ABS_D: 2732 case ABS_D:
2477 set_fpu_register_float(fd_reg, fabs(fs)); 2733 set_fpu_register_float(fd_reg, fabs(fs));
2478 break; 2734 break;
2479 case MOV_D: 2735 case MOV_D:
2480 set_fpu_register_float(fd_reg, fs); 2736 set_fpu_register_float(fd_reg, fs);
2481 break; 2737 break;
2482 case NEG_D: 2738 case NEG_D:
2483 set_fpu_register_float(fd_reg, -fs); 2739 set_fpu_register_float(fd_reg, -fs);
2484 break; 2740 break;
2485 case SQRT_D: 2741 case SQRT_D:
2486 set_fpu_register_float(fd_reg, fast_sqrt(fs)); 2742 set_fpu_register_float(fd_reg, fast_sqrt(fs));
2487 break; 2743 break;
2744 case RSQRT_D: {
2745 float result = 1.0 / fast_sqrt(fs);
2746 set_fpu_register_float(fd_reg, result);
2747 break;
2748 }
2749 case RECIP: {
2750 float result = 1.0 / fs;
2751 set_fpu_register_float(fd_reg, result);
2752 break;
2753 }
2488 case C_UN_D: 2754 case C_UN_D:
2489 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); 2755 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2490 break; 2756 break;
2491 case C_EQ_D: 2757 case C_EQ_D:
2492 set_fcsr_bit(fcsr_cc, (fs == ft)); 2758 set_fcsr_bit(fcsr_cc, (fs == ft));
2493 break; 2759 break;
2494 case C_UEQ_D: 2760 case C_UEQ_D:
2495 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); 2761 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2496 break; 2762 break;
2497 case C_OLT_D: 2763 case C_OLT_D:
2498 set_fcsr_bit(fcsr_cc, (fs < ft)); 2764 set_fcsr_bit(fcsr_cc, (fs < ft));
2499 break; 2765 break;
2500 case C_ULT_D: 2766 case C_ULT_D:
2501 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); 2767 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
2502 break; 2768 break;
2503 case C_OLE_D: 2769 case C_OLE_D:
2504 set_fcsr_bit(fcsr_cc, (fs <= ft)); 2770 set_fcsr_bit(fcsr_cc, (fs <= ft));
2505 break; 2771 break;
2506 case C_ULE_D: 2772 case C_ULE_D:
2507 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); 2773 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
2508 break; 2774 break;
2509 case CVT_D_S: 2775 case CVT_D_S:
2510 set_fpu_register_double(fd_reg, static_cast<double>(fs)); 2776 set_fpu_register_double(fd_reg, static_cast<double>(fs));
2511 break; 2777 break;
2778 case SEL:
2779 DCHECK(IsMipsArchVariant(kMips32r6));
2780 set_fpu_register_float(fd_reg, (fd_int & 0x1) == 0 ? fs : ft);
2781 break;
2512 case SELEQZ_C: 2782 case SELEQZ_C:
2513 DCHECK(IsMipsArchVariant(kMips32r6)); 2783 DCHECK(IsMipsArchVariant(kMips32r6));
2514 set_fpu_register_double( 2784 set_fpu_register_float(
2515 fd_reg, (ft_int & 0x1) == 0 ? get_fpu_register_double(fs_reg) : 0.0); 2785 fd_reg, (ft_int & 0x1) == 0 ? get_fpu_register_float(fs_reg) : 0.0);
2516 break; 2786 break;
2517 case SELNEZ_C: 2787 case SELNEZ_C:
2518 DCHECK(IsMipsArchVariant(kMips32r6)); 2788 DCHECK(IsMipsArchVariant(kMips32r6));
2519 set_fpu_register_double( 2789 set_fpu_register_float(
2520 fd_reg, (ft_int & 0x1) != 0 ? get_fpu_register_double(fs_reg) : 0.0); 2790 fd_reg, (ft_int & 0x1) != 0 ? get_fpu_register_float(fs_reg) : 0.0);
2791 break;
2792 case MOVZ_C: {
2793 DCHECK(IsMipsArchVariant(kMips32r2));
2794 int32_t rt_reg = instr->RtValue();
2795 int32_t rt = get_register(rt_reg);
2796 if (rt == 0) {
2797 set_fpu_register_float(fd_reg, fs);
2798 }
2799 break;
2800 }
2801 case MOVN_C: {
2802 DCHECK(IsMipsArchVariant(kMips32r2));
2803 int32_t rt_reg = instr->RtValue();
2804 int32_t rt = get_register(rt_reg);
2805 if (rt != 0) {
2806 set_fpu_register_float(fd_reg, fs);
2807 }
2808 break;
2809 }
2810 case MOVF: {
2811 // Same function field for MOVT.D and MOVF.D
2812 uint32_t ft_cc = (ft_reg >> 2) & 0x7;
2813 ft_cc = get_fcsr_condition_bit(ft_cc);
2814
2815 if (instr->Bit(16)) { // Read Tf bit.
2816 // MOVT.D
2817 if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg, fs);
2818 } else {
2819 // MOVF.D
2820 if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg, fs);
2821 }
2822 break;
2823 }
2824 case TRUNC_W_S: { // Truncate single to word (round towards 0).
2825 float rounded = trunc(fs);
2826 int32_t result = static_cast<int32_t>(rounded);
2827 set_fpu_register_word(fd_reg, result);
2828 if (set_fcsr_round_error(fs, rounded)) {
2829 set_fpu_register_word(fd_reg, kFPUInvalidResult);
2830 }
2831 } break;
2832 case TRUNC_L_S: { // Mips32r2 instruction.
2833 float rounded = trunc(fs);
2834 int64_t i64 = static_cast<int64_t>(rounded);
2835 if (IsFp64Mode()) {
2836 set_fpu_register(fd_reg, i64);
2837 if (set_fcsr_round64_error(fs, rounded)) {
2838 set_fpu_register(fd_reg, kFPU64InvalidResult);
2839 }
2840 } else {
2841 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2842 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2843 if (set_fcsr_round64_error(fs, rounded)) {
2844 set_fpu_register_word(fd_reg, kFPU64InvalidResult & 0xffffffff);
2845 set_fpu_register_word(fd_reg + 1, kFPU64InvalidResult >> 32);
2846 }
2847 }
2848 break;
2849 }
2850 case FLOOR_W_S: // Round double to word towards negative infinity.
2851 {
2852 float rounded = std::floor(fs);
2853 int32_t result = static_cast<int32_t>(rounded);
2854 set_fpu_register_word(fd_reg, result);
2855 if (set_fcsr_round_error(fs, rounded)) {
2856 set_fpu_register_word(fd_reg, kFPUInvalidResult);
2857 }
2858 } break;
2859 case FLOOR_L_D: { // Mips32r2 instruction.
2860 float rounded = std::floor(fs);
2861 int64_t i64 = static_cast<int64_t>(rounded);
2862 if (IsFp64Mode()) {
2863 set_fpu_register(fd_reg, i64);
2864 if (set_fcsr_round64_error(fs, rounded)) {
2865 set_fpu_register(fd_reg, kFPU64InvalidResult);
2866 }
2867 } else {
2868 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2869 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2870 if (set_fcsr_round64_error(fs, rounded)) {
2871 set_fpu_register_word(fd_reg, kFPU64InvalidResult & 0xffffffff);
2872 set_fpu_register_word(fd_reg + 1, kFPU64InvalidResult >> 32);
2873 }
2874 }
2875 break;
2876 }
2877 case ROUND_W_S: {
2878 float rounded = std::floor(fs + 0.5);
2879 int32_t result = static_cast<int32_t>(rounded);
2880 if ((result & 1) != 0 && result - fs == 0.5) {
2881 // If the number is halfway between two integers,
2882 // round to the even one.
2883 result--;
2884 }
2885 set_fpu_register_word(fd_reg, result);
2886 if (set_fcsr_round_error(fs, rounded)) {
2887 set_fpu_register_word(fd_reg, kFPUInvalidResult);
2888 }
2889 break;
2890 }
2891 case ROUND_L_S: { // Mips32r2 instruction.
2892 float rounded = std::floor(fs + 0.5);
2893 int64_t result = static_cast<int64_t>(rounded);
2894 if ((result & 1) != 0 && result - fs == 0.5) {
2895 // If the number is halfway between two integers,
2896 // round to the even one.
2897 result--;
2898 }
2899 int64_t i64 = static_cast<int64_t>(result);
2900 if (IsFp64Mode()) {
2901 set_fpu_register(fd_reg, i64);
2902 if (set_fcsr_round64_error(fs, rounded)) {
2903 set_fpu_register(fd_reg, kFPU64InvalidResult);
2904 }
2905 } else {
2906 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2907 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2908 if (set_fcsr_round64_error(fs, rounded)) {
2909 set_fpu_register_word(fd_reg, kFPU64InvalidResult & 0xffffffff);
2910 set_fpu_register_word(fd_reg + 1, kFPU64InvalidResult >> 32);
2911 }
2912 }
2913 break;
2914 }
2915 case CEIL_W_S: // Round double to word towards positive infinity.
2916 {
2917 float rounded = std::ceil(fs);
2918 int32_t result = static_cast<int32_t>(rounded);
2919 set_fpu_register_word(fd_reg, result);
2920 if (set_fcsr_round_error(fs, rounded)) {
2921 set_fpu_register_word(fd_reg, kFPUInvalidResult);
2922 }
2923 } break;
2924 case CEIL_L_S: { // Mips32r2 instruction.
2925 float rounded = std::ceil(fs);
2926 int64_t i64 = static_cast<int64_t>(rounded);
2927 if (IsFp64Mode()) {
2928 set_fpu_register(fd_reg, i64);
2929 if (set_fcsr_round64_error(fs, rounded)) {
2930 set_fpu_register(fd_reg, kFPU64InvalidResult);
2931 }
2932 } else {
2933 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2934 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2935 if (set_fcsr_round64_error(fs, rounded)) {
2936 set_fpu_register_word(fd_reg, kFPU64InvalidResult & 0xffffffff);
2937 set_fpu_register_word(fd_reg + 1, kFPU64InvalidResult >> 32);
2938 }
2939 }
2940 break;
2941 }
2942 case MIN:
2943 DCHECK(IsMipsArchVariant(kMips32r6));
2944 fs = get_fpu_register_float(fs_reg);
2945 if (std::isnan(fs) && std::isnan(ft)) {
2946 set_fpu_register_float(fd_reg, fs);
2947 } else if (std::isnan(fs) && !std::isnan(ft)) {
2948 set_fpu_register_float(fd_reg, ft);
2949 } else if (!std::isnan(fs) && std::isnan(ft)) {
2950 set_fpu_register_float(fd_reg, fs);
2951 } else {
2952 set_fpu_register_float(fd_reg, (fs >= ft) ? ft : fs);
2953 }
2954 break;
2955 case MAX:
2956 DCHECK(IsMipsArchVariant(kMips32r6));
2957 fs = get_fpu_register_float(fs_reg);
2958 if (std::isnan(fs) && std::isnan(ft)) {
2959 set_fpu_register_float(fd_reg, fs);
2960 } else if (std::isnan(fs) && !std::isnan(ft)) {
2961 set_fpu_register_float(fd_reg, ft);
2962 } else if (!std::isnan(fs) && std::isnan(ft)) {
2963 set_fpu_register_float(fd_reg, fs);
2964 } else {
2965 set_fpu_register_float(fd_reg, (fs <= ft) ? ft : fs);
2966 }
2967 break;
2968 case MINA:
2969 DCHECK(IsMipsArchVariant(kMips32r6));
2970 fs = get_fpu_register_float(fs_reg);
2971 if (std::isnan(fs) && std::isnan(ft)) {
2972 set_fpu_register_float(fd_reg, fs);
2973 } else if (std::isnan(fs) && !std::isnan(ft)) {
2974 set_fpu_register_float(fd_reg, ft);
2975 } else if (!std::isnan(fs) && std::isnan(ft)) {
2976 set_fpu_register_float(fd_reg, fs);
2977 } else {
2978 float result;
2979 if (fabs(fs) > fabs(ft)) {
2980 result = ft;
2981 } else if (fabs(fs) < fabs(ft)) {
2982 result = fs;
2983 } else {
2984 result = (fs > ft ? fs : ft);
2985 }
2986 set_fpu_register_float(fd_reg, result);
2987 }
2988 break;
2989 case MAXA:
2990 DCHECK(IsMipsArchVariant(kMips32r6));
2991 fs = get_fpu_register_float(fs_reg);
2992 if (std::isnan(fs) && std::isnan(ft)) {
2993 set_fpu_register_float(fd_reg, fs);
2994 } else if (std::isnan(fs) && !std::isnan(ft)) {
2995 set_fpu_register_float(fd_reg, ft);
2996 } else if (!std::isnan(fs) && std::isnan(ft)) {
2997 set_fpu_register_float(fd_reg, fs);
2998 } else {
2999 float result;
3000 if (fabs(fs) < fabs(ft)) {
3001 result = ft;
3002 } else if (fabs(fs) > fabs(ft)) {
3003 result = fs;
3004 } else {
3005 result = (fs > ft ? fs : ft);
3006 }
3007 set_fpu_register_float(fd_reg, result);
3008 }
2521 break; 3009 break;
2522 default: 3010 default:
2523 // CVT_W_S CVT_L_S TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S 3011 // CVT_W_S CVT_L_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S
2524 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. 3012 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented.
2525 UNREACHABLE(); 3013 UNREACHABLE();
2526 } 3014 }
2527 } 3015 }
2528 3016
2529 3017
2530 void Simulator::DecodeTypeRegisterLRsType(Instruction* instr, 3018 void Simulator::DecodeTypeRegisterLRsType(Instruction* instr,
2531 const int32_t& ft_reg, 3019 const int32_t& ft_reg,
2532 const int32_t& fs_reg, 3020 const int32_t& fs_reg,
2533 const int32_t& fd_reg) { 3021 const int32_t& fd_reg) {
(...skipping 1000 matching lines...) Expand 10 before | Expand all | Expand 10 after
3534 } 4022 }
3535 4023
3536 4024
3537 #undef UNSUPPORTED 4025 #undef UNSUPPORTED
3538 4026
3539 } } // namespace v8::internal 4027 } } // namespace v8::internal
3540 4028
3541 #endif // USE_SIMULATOR 4029 #endif // USE_SIMULATOR
3542 4030
3543 #endif // V8_TARGET_ARCH_MIPS 4031 #endif // V8_TARGET_ARCH_MIPS
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698