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

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

Issue 1143473003: Revert of MIPS: Add float instructions and test coverage, part one (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/mips/simulator-mips.h ('k') | src/mips64/assembler-mips64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <limits.h> 5 #include <limits.h>
6 #include <stdarg.h> 6 #include <stdarg.h>
7 #include <stdlib.h> 7 #include <stdlib.h>
8 #include <cmath> 8 #include <cmath>
9 9
10 #include "src/v8.h" 10 #include "src/v8.h"
(...skipping 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 bool Simulator::set_fcsr_round_error(double original, double rounded) {
1286 bool ret = false;
1287 double max_int32 = std::numeric_limits<int32_t>::max();
1288 double min_int32 = std::numeric_limits<int32_t>::min();
1289
1290 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1291 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1292 ret = true;
1293 }
1294
1295 if (original != rounded) {
1296 set_fcsr_bit(kFCSRInexactFlagBit, true);
1297 }
1298
1299 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1300 set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1301 ret = true;
1302 }
1303
1304 if (rounded >= max_int32 || rounded <= min_int32) {
1305 set_fcsr_bit(kFCSROverflowFlagBit, true);
1306 // The reference is not really clear but it seems this is required:
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. 1285 // Sets the rounding error codes in FCSR based on the result of the rounding.
1316 // Returns true if the operation was invalid. 1286 // Returns true if the operation was invalid.
1317 bool Simulator::set_fcsr_round64_error(double original, double rounded) { 1287 bool Simulator::set_fcsr_round_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; 1288 bool ret = false;
1349 double max_int32 = std::numeric_limits<int32_t>::max(); 1289 double max_int32 = std::numeric_limits<int32_t>::max();
1350 double min_int32 = std::numeric_limits<int32_t>::min(); 1290 double min_int32 = std::numeric_limits<int32_t>::min();
1351 1291
1352 if (!std::isfinite(original) || !std::isfinite(rounded)) { 1292 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1353 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1293 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1354 ret = true; 1294 ret = true;
1355 } 1295 }
1356 1296
1357 if (original != rounded) { 1297 if (original != rounded) {
1358 set_fcsr_bit(kFCSRInexactFlagBit, true); 1298 set_fcsr_bit(kFCSRInexactFlagBit, true);
1359 } 1299 }
1360 1300
1361 if (rounded < FLT_MIN && rounded > -FLT_MIN && rounded != 0) { 1301 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1362 set_fcsr_bit(kFCSRUnderflowFlagBit, true); 1302 set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1363 ret = true; 1303 ret = true;
1364 } 1304 }
1365 1305
1366 if (rounded >= max_int32 || rounded <= min_int32) { 1306 if (rounded > max_int32 || rounded < min_int32) {
1367 set_fcsr_bit(kFCSROverflowFlagBit, true); 1307 set_fcsr_bit(kFCSROverflowFlagBit, true);
1368 // The reference is not really clear but it seems this is required: 1308 // The reference is not really clear but it seems this is required:
1369 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1309 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);
1402 ret = true; 1310 ret = true;
1403 } 1311 }
1404 1312
1405 return ret; 1313 return ret;
1406 } 1314 }
1407 1315
1408 1316
1409 void Simulator::round_according_to_fcsr(double toRound, double& rounded, 1317 void Simulator::round_according_to_fcsr(double toRound, double& rounded,
1410 int32_t& rounded_int, double fs) { 1318 int32_t& rounded_int, double fs) {
1411 // 0 RN (round to nearest): Round a result to the nearest 1319 // 0 RN (round to nearest): Round a result to the nearest
(...skipping 864 matching lines...) Expand 10 before | Expand all | Expand 10 after
2276 2184
2277 void Simulator::DecodeTypeRegisterDRsType(Instruction* instr, 2185 void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
2278 const int32_t& fr_reg, 2186 const int32_t& fr_reg,
2279 const int32_t& fs_reg, 2187 const int32_t& fs_reg,
2280 const int32_t& ft_reg, 2188 const int32_t& ft_reg,
2281 const int32_t& fd_reg) { 2189 const int32_t& fd_reg) {
2282 double ft, fs, fd; 2190 double ft, fs, fd;
2283 uint32_t cc, fcsr_cc; 2191 uint32_t cc, fcsr_cc;
2284 int64_t i64; 2192 int64_t i64;
2285 fs = get_fpu_register_double(fs_reg); 2193 fs = get_fpu_register_double(fs_reg);
2286 if (instr->FunctionFieldRaw() != MOVF) { 2194 ft = get_fpu_register_double(ft_reg);
2287 ft = get_fpu_register_double(ft_reg);
2288 }
2289 fd = get_fpu_register_double(fd_reg);
2290 int64_t ft_int = bit_cast<int64_t>(ft); 2195 int64_t ft_int = bit_cast<int64_t>(ft);
2291 int64_t fd_int = bit_cast<int64_t>(fd); 2196 int64_t fd_int = bit_cast<int64_t>(fd);
2292 cc = instr->FCccValue(); 2197 cc = instr->FCccValue();
2293 fcsr_cc = get_fcsr_condition_bit(cc); 2198 fcsr_cc = get_fcsr_condition_bit(cc);
2294 switch (instr->FunctionFieldRaw()) { 2199 switch (instr->FunctionFieldRaw()) {
2295 case RINT: { 2200 case RINT: {
2296 DCHECK(IsMipsArchVariant(kMips32r6)); 2201 DCHECK(IsMipsArchVariant(kMips32r6));
2297 double result, temp, temp_result; 2202 double result, temp, temp_result;
2298 double upper = std::ceil(fs); 2203 double upper = std::ceil(fs);
2299 double lower = std::floor(fs); 2204 double lower = std::floor(fs);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2334 set_fpu_register_double(fd_reg, (fd_int & 0x1) == 0 ? fs : ft); 2239 set_fpu_register_double(fd_reg, (fd_int & 0x1) == 0 ? fs : ft);
2335 break; 2240 break;
2336 case SELEQZ_C: 2241 case SELEQZ_C:
2337 DCHECK(IsMipsArchVariant(kMips32r6)); 2242 DCHECK(IsMipsArchVariant(kMips32r6));
2338 set_fpu_register_double(fd_reg, (ft_int & 0x1) == 0 ? fs : 0.0); 2243 set_fpu_register_double(fd_reg, (ft_int & 0x1) == 0 ? fs : 0.0);
2339 break; 2244 break;
2340 case SELNEZ_C: 2245 case SELNEZ_C:
2341 DCHECK(IsMipsArchVariant(kMips32r6)); 2246 DCHECK(IsMipsArchVariant(kMips32r6));
2342 set_fpu_register_double(fd_reg, (ft_int & 0x1) != 0 ? fs : 0.0); 2247 set_fpu_register_double(fd_reg, (ft_int & 0x1) != 0 ? fs : 0.0);
2343 break; 2248 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 }
2375 case MIN: 2249 case MIN:
2376 DCHECK(IsMipsArchVariant(kMips32r6)); 2250 DCHECK(IsMipsArchVariant(kMips32r6));
2377 fs = get_fpu_register_double(fs_reg); 2251 fs = get_fpu_register_double(fs_reg);
2378 if (std::isnan(fs) && std::isnan(ft)) { 2252 if (std::isnan(fs) && std::isnan(ft)) {
2379 set_fpu_register_double(fd_reg, fs); 2253 set_fpu_register_double(fd_reg, fs);
2380 } else if (std::isnan(fs) && !std::isnan(ft)) { 2254 } else if (std::isnan(fs) && !std::isnan(ft)) {
2381 set_fpu_register_double(fd_reg, ft); 2255 set_fpu_register_double(fd_reg, ft);
2382 } else if (!std::isnan(fs) && std::isnan(ft)) { 2256 } else if (!std::isnan(fs) && std::isnan(ft)) {
2383 set_fpu_register_double(fd_reg, fs); 2257 set_fpu_register_double(fd_reg, fs);
2384 } else { 2258 } else {
2385 set_fpu_register_double(fd_reg, (fs >= ft) ? ft : fs); 2259 set_fpu_register_double(fd_reg, (fs >= ft) ? ft : fs);
2386 } 2260 }
2387 break; 2261 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;
2430 case MAX: 2262 case MAX:
2431 DCHECK(IsMipsArchVariant(kMips32r6)); 2263 DCHECK(IsMipsArchVariant(kMips32r6));
2432 fs = get_fpu_register_double(fs_reg); 2264 fs = get_fpu_register_double(fs_reg);
2433 if (std::isnan(fs) && std::isnan(ft)) { 2265 if (std::isnan(fs) && std::isnan(ft)) {
2434 set_fpu_register_double(fd_reg, fs); 2266 set_fpu_register_double(fd_reg, fs);
2435 } else if (std::isnan(fs) && !std::isnan(ft)) { 2267 } else if (std::isnan(fs) && !std::isnan(ft)) {
2436 set_fpu_register_double(fd_reg, ft); 2268 set_fpu_register_double(fd_reg, ft);
2437 } else if (!std::isnan(fs) && std::isnan(ft)) { 2269 } else if (!std::isnan(fs) && std::isnan(ft)) {
2438 set_fpu_register_double(fd_reg, fs); 2270 set_fpu_register_double(fd_reg, fs);
2439 } else { 2271 } else {
(...skipping 18 matching lines...) Expand all
2458 break; 2290 break;
2459 case MOV_D: 2291 case MOV_D:
2460 set_fpu_register_double(fd_reg, fs); 2292 set_fpu_register_double(fd_reg, fs);
2461 break; 2293 break;
2462 case NEG_D: 2294 case NEG_D:
2463 set_fpu_register_double(fd_reg, -fs); 2295 set_fpu_register_double(fd_reg, -fs);
2464 break; 2296 break;
2465 case SQRT_D: 2297 case SQRT_D:
2466 set_fpu_register_double(fd_reg, fast_sqrt(fs)); 2298 set_fpu_register_double(fd_reg, fast_sqrt(fs));
2467 break; 2299 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_D: {
2474 double result = 1.0 / fs;
2475 set_fpu_register_double(fd_reg, result);
2476 break;
2477 }
2478 case C_UN_D: 2300 case C_UN_D:
2479 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); 2301 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2480 break; 2302 break;
2481 case C_EQ_D: 2303 case C_EQ_D:
2482 set_fcsr_bit(fcsr_cc, (fs == ft)); 2304 set_fcsr_bit(fcsr_cc, (fs == ft));
2483 break; 2305 break;
2484 case C_UEQ_D: 2306 case C_UEQ_D:
2485 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); 2307 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2486 break; 2308 break;
2487 case C_OLT_D: 2309 case C_OLT_D:
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2548 } break; 2370 } break;
2549 case CVT_S_D: // Convert double to float (single). 2371 case CVT_S_D: // Convert double to float (single).
2550 set_fpu_register_float(fd_reg, static_cast<float>(fs)); 2372 set_fpu_register_float(fd_reg, static_cast<float>(fs));
2551 break; 2373 break;
2552 case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word. 2374 case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word.
2553 double rounded = trunc(fs); 2375 double rounded = trunc(fs);
2554 i64 = static_cast<int64_t>(rounded); 2376 i64 = static_cast<int64_t>(rounded);
2555 if (IsFp64Mode()) { 2377 if (IsFp64Mode()) {
2556 set_fpu_register(fd_reg, i64); 2378 set_fpu_register(fd_reg, i64);
2557 } else { 2379 } else {
2558 UNSUPPORTED(); 2380 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2381 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2559 } 2382 }
2560 break; 2383 break;
2561 } 2384 }
2562 case TRUNC_L_D: { // Mips32r2 instruction. 2385 case TRUNC_L_D: { // Mips32r2 instruction.
2563 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2564 double rounded = trunc(fs); 2386 double rounded = trunc(fs);
2565 i64 = static_cast<int64_t>(rounded); 2387 i64 = static_cast<int64_t>(rounded);
2566 if (IsFp64Mode()) { 2388 if (IsFp64Mode()) {
2567 set_fpu_register(fd_reg, i64); 2389 set_fpu_register(fd_reg, i64);
2568 if (set_fcsr_round64_error(fs, rounded)) {
2569 set_fpu_register(fd_reg, kFPU64InvalidResult);
2570 }
2571 } else { 2390 } else {
2572 UNSUPPORTED(); 2391 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2392 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2573 } 2393 }
2574 break; 2394 break;
2575 } 2395 }
2576 case ROUND_L_D: { // Mips32r2 instruction. 2396 case ROUND_L_D: { // Mips32r2 instruction.
2577 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); 2397 double rounded = fs > 0 ? std::floor(fs + 0.5) : std::ceil(fs - 0.5);
2578 double rounded = std::floor(fs + 0.5); 2398 i64 = static_cast<int64_t>(rounded);
2579 int64_t result = static_cast<int64_t>(rounded);
2580 if ((result & 1) != 0 && result - fs == 0.5) {
2581 // If the number is halfway between two integers,
2582 // round to the even one.
2583 result--;
2584 }
2585 int64_t i64 = static_cast<int64_t>(result);
2586 if (IsFp64Mode()) { 2399 if (IsFp64Mode()) {
2587 set_fpu_register(fd_reg, i64); 2400 set_fpu_register(fd_reg, i64);
2588 if (set_fcsr_round64_error(fs, rounded)) {
2589 set_fpu_register(fd_reg, kFPU64InvalidResult);
2590 }
2591 } else { 2401 } else {
2592 UNSUPPORTED(); 2402 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2403 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2593 } 2404 }
2594 break; 2405 break;
2595 } 2406 }
2596 case FLOOR_L_D: { // Mips32r2 instruction. 2407 case FLOOR_L_D: // Mips32r2 instruction.
2597 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); 2408 i64 = static_cast<int64_t>(std::floor(fs));
2598 double rounded = std::floor(fs);
2599 int64_t i64 = static_cast<int64_t>(rounded);
2600 if (IsFp64Mode()) { 2409 if (IsFp64Mode()) {
2601 set_fpu_register(fd_reg, i64); 2410 set_fpu_register(fd_reg, i64);
2602 if (set_fcsr_round64_error(fs, rounded)) {
2603 set_fpu_register(fd_reg, kFPU64InvalidResult);
2604 }
2605 } else { 2411 } else {
2606 UNSUPPORTED(); 2412 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2413 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2607 } 2414 }
2608 break; 2415 break;
2609 } 2416 case CEIL_L_D: // Mips32r2 instruction.
2610 case CEIL_L_D: { // Mips32r2 instruction. 2417 i64 = static_cast<int64_t>(std::ceil(fs));
2611 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2612 double rounded = std::ceil(fs);
2613 int64_t i64 = static_cast<int64_t>(rounded);
2614 if (IsFp64Mode()) { 2418 if (IsFp64Mode()) {
2615 set_fpu_register(fd_reg, i64); 2419 set_fpu_register(fd_reg, i64);
2616 if (set_fcsr_round64_error(fs, rounded)) {
2617 set_fpu_register(fd_reg, kFPU64InvalidResult);
2618 }
2619 } else { 2420 } else {
2620 UNSUPPORTED(); 2421 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2422 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2621 } 2423 }
2622 break; 2424 break;
2623 }
2624 case C_F_D: 2425 case C_F_D:
2625 UNIMPLEMENTED_MIPS(); 2426 UNIMPLEMENTED_MIPS();
2626 break; 2427 break;
2627 default: 2428 default:
2628 UNREACHABLE(); 2429 UNREACHABLE();
2629 } 2430 }
2630 } 2431 }
2631 2432
2632 2433
2633 void Simulator::DecodeTypeRegisterWRsType(Instruction* instr, int32_t& alu_out, 2434 void Simulator::DecodeTypeRegisterWRsType(Instruction* instr, int32_t& alu_out,
(...skipping 11 matching lines...) Expand all
2645 default: // Mips64r6 CMP.S instructions unimplemented. 2446 default: // Mips64r6 CMP.S instructions unimplemented.
2646 UNREACHABLE(); 2447 UNREACHABLE();
2647 } 2448 }
2648 } 2449 }
2649 2450
2650 2451
2651 void Simulator::DecodeTypeRegisterSRsType(Instruction* instr, 2452 void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
2652 const int32_t& ft_reg, 2453 const int32_t& ft_reg,
2653 const int32_t& fs_reg, 2454 const int32_t& fs_reg,
2654 const int32_t& fd_reg) { 2455 const int32_t& fd_reg) {
2655 float fs, ft, fd; 2456 float fs, ft;
2656 fs = get_fpu_register_float(fs_reg); 2457 fs = get_fpu_register_float(fs_reg);
2657 ft = get_fpu_register_float(ft_reg); 2458 ft = get_fpu_register_float(ft_reg);
2658 fd = get_fpu_register_float(fd_reg); 2459 int64_t ft_int = static_cast<int64_t>(get_fpu_register_double(ft_reg));
2659 int32_t ft_int = bit_cast<int32_t>(ft);
2660 int32_t fd_int = bit_cast<int32_t>(fd);
2661 uint32_t cc, fcsr_cc; 2460 uint32_t cc, fcsr_cc;
2662 cc = instr->FCccValue(); 2461 cc = instr->FCccValue();
2663 fcsr_cc = get_fcsr_condition_bit(cc); 2462 fcsr_cc = get_fcsr_condition_bit(cc);
2664 switch (instr->FunctionFieldRaw()) { 2463 switch (instr->FunctionFieldRaw()) {
2665 case RINT: { 2464 case ADD_D:
2666 DCHECK(IsMipsArchVariant(kMips32r6));
2667 float result, temp_result;
2668 double temp;
2669 float upper = std::ceil(fs);
2670 float lower = std::floor(fs);
2671 switch (get_fcsr_rounding_mode()) {
2672 case kRoundToNearest:
2673 if (upper - fs < fs - lower) {
2674 result = upper;
2675 } else if (upper - fs > fs - lower) {
2676 result = lower;
2677 } else {
2678 temp_result = upper / 2;
2679 float reminder = modf(temp_result, &temp);
2680 if (reminder == 0) {
2681 result = upper;
2682 } else {
2683 result = lower;
2684 }
2685 }
2686 break;
2687 case kRoundToZero:
2688 result = (fs > 0 ? lower : upper);
2689 break;
2690 case kRoundToPlusInf:
2691 result = upper;
2692 break;
2693 case kRoundToMinusInf:
2694 result = lower;
2695 break;
2696 }
2697 set_fpu_register_float(fd_reg, result);
2698 if (result != fs) {
2699 set_fcsr_bit(kFCSRInexactFlagBit, true);
2700 }
2701 break;
2702 }
2703 case ADD_S:
2704 set_fpu_register_float(fd_reg, fs + ft); 2465 set_fpu_register_float(fd_reg, fs + ft);
2705 break; 2466 break;
2706 case SUB_S: 2467 case SUB_D:
2707 set_fpu_register_float(fd_reg, fs - ft); 2468 set_fpu_register_float(fd_reg, fs - ft);
2708 break; 2469 break;
2709 case MUL_S: 2470 case MUL_D:
2710 set_fpu_register_float(fd_reg, fs * ft); 2471 set_fpu_register_float(fd_reg, fs * ft);
2711 break; 2472 break;
2712 case DIV_S: 2473 case DIV_D:
2713 set_fpu_register_float(fd_reg, fs / ft); 2474 set_fpu_register_float(fd_reg, fs / ft);
2714 break; 2475 break;
2715 case ABS_S: 2476 case ABS_D:
2716 set_fpu_register_float(fd_reg, fabs(fs)); 2477 set_fpu_register_float(fd_reg, fabs(fs));
2717 break; 2478 break;
2718 case MOV_S: 2479 case MOV_D:
2719 set_fpu_register_float(fd_reg, fs); 2480 set_fpu_register_float(fd_reg, fs);
2720 break; 2481 break;
2721 case NEG_S: 2482 case NEG_D:
2722 set_fpu_register_float(fd_reg, -fs); 2483 set_fpu_register_float(fd_reg, -fs);
2723 break; 2484 break;
2724 case SQRT_S: 2485 case SQRT_D:
2725 set_fpu_register_float(fd_reg, fast_sqrt(fs)); 2486 set_fpu_register_float(fd_reg, fast_sqrt(fs));
2726 break; 2487 break;
2727 case RSQRT_S: {
2728 float result = 1.0 / fast_sqrt(fs);
2729 set_fpu_register_float(fd_reg, result);
2730 break;
2731 }
2732 case RECIP_S: {
2733 float result = 1.0 / fs;
2734 set_fpu_register_float(fd_reg, result);
2735 break;
2736 }
2737 case C_UN_D: 2488 case C_UN_D:
2738 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); 2489 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2739 break; 2490 break;
2740 case C_EQ_D: 2491 case C_EQ_D:
2741 set_fcsr_bit(fcsr_cc, (fs == ft)); 2492 set_fcsr_bit(fcsr_cc, (fs == ft));
2742 break; 2493 break;
2743 case C_UEQ_D: 2494 case C_UEQ_D:
2744 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); 2495 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2745 break; 2496 break;
2746 case C_OLT_D: 2497 case C_OLT_D:
2747 set_fcsr_bit(fcsr_cc, (fs < ft)); 2498 set_fcsr_bit(fcsr_cc, (fs < ft));
2748 break; 2499 break;
2749 case C_ULT_D: 2500 case C_ULT_D:
2750 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); 2501 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
2751 break; 2502 break;
2752 case C_OLE_D: 2503 case C_OLE_D:
2753 set_fcsr_bit(fcsr_cc, (fs <= ft)); 2504 set_fcsr_bit(fcsr_cc, (fs <= ft));
2754 break; 2505 break;
2755 case C_ULE_D: 2506 case C_ULE_D:
2756 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); 2507 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
2757 break; 2508 break;
2758 case CVT_D_S: 2509 case CVT_D_S:
2759 set_fpu_register_double(fd_reg, static_cast<double>(fs)); 2510 set_fpu_register_double(fd_reg, static_cast<double>(fs));
2760 break; 2511 break;
2761 case SEL:
2762 DCHECK(IsMipsArchVariant(kMips32r6));
2763 set_fpu_register_float(fd_reg, (fd_int & 0x1) == 0 ? fs : ft);
2764 break;
2765 case SELEQZ_C: 2512 case SELEQZ_C:
2766 DCHECK(IsMipsArchVariant(kMips32r6)); 2513 DCHECK(IsMipsArchVariant(kMips32r6));
2767 set_fpu_register_float( 2514 set_fpu_register_double(
2768 fd_reg, (ft_int & 0x1) == 0 ? get_fpu_register_float(fs_reg) : 0.0); 2515 fd_reg, (ft_int & 0x1) == 0 ? get_fpu_register_double(fs_reg) : 0.0);
2769 break; 2516 break;
2770 case SELNEZ_C: 2517 case SELNEZ_C:
2771 DCHECK(IsMipsArchVariant(kMips32r6)); 2518 DCHECK(IsMipsArchVariant(kMips32r6));
2772 set_fpu_register_float( 2519 set_fpu_register_double(
2773 fd_reg, (ft_int & 0x1) != 0 ? get_fpu_register_float(fs_reg) : 0.0); 2520 fd_reg, (ft_int & 0x1) != 0 ? get_fpu_register_double(fs_reg) : 0.0);
2774 break;
2775 case MOVZ_C: {
2776 DCHECK(IsMipsArchVariant(kMips32r2));
2777 int32_t rt_reg = instr->RtValue();
2778 int32_t rt = get_register(rt_reg);
2779 if (rt == 0) {
2780 set_fpu_register_float(fd_reg, fs);
2781 }
2782 break;
2783 }
2784 case MOVN_C: {
2785 DCHECK(IsMipsArchVariant(kMips32r2));
2786 int32_t rt_reg = instr->RtValue();
2787 int32_t rt = get_register(rt_reg);
2788 if (rt != 0) {
2789 set_fpu_register_float(fd_reg, fs);
2790 }
2791 break;
2792 }
2793 case MOVF: {
2794 // Same function field for MOVT.D and MOVF.D
2795 uint32_t ft_cc = (ft_reg >> 2) & 0x7;
2796 ft_cc = get_fcsr_condition_bit(ft_cc);
2797
2798 if (instr->Bit(16)) { // Read Tf bit.
2799 // MOVT.D
2800 if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg, fs);
2801 } else {
2802 // MOVF.D
2803 if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg, fs);
2804 }
2805 break;
2806 }
2807 case TRUNC_W_S: { // Truncate single to word (round towards 0).
2808 float rounded = trunc(fs);
2809 int32_t result = static_cast<int32_t>(rounded);
2810 set_fpu_register_word(fd_reg, result);
2811 if (set_fcsr_round_error(fs, rounded)) {
2812 set_fpu_register_word(fd_reg, kFPUInvalidResult);
2813 }
2814 } break;
2815 case TRUNC_L_S: { // Mips32r2 instruction.
2816 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2817 float rounded = trunc(fs);
2818 int64_t i64 = static_cast<int64_t>(rounded);
2819 if (IsFp64Mode()) {
2820 set_fpu_register(fd_reg, i64);
2821 if (set_fcsr_round64_error(fs, rounded)) {
2822 set_fpu_register(fd_reg, kFPU64InvalidResult);
2823 }
2824 } else {
2825 UNSUPPORTED();
2826 }
2827 break;
2828 }
2829 case FLOOR_W_S: // Round double to word towards negative infinity.
2830 {
2831 float rounded = std::floor(fs);
2832 int32_t result = static_cast<int32_t>(rounded);
2833 set_fpu_register_word(fd_reg, result);
2834 if (set_fcsr_round_error(fs, rounded)) {
2835 set_fpu_register_word(fd_reg, kFPUInvalidResult);
2836 }
2837 } break;
2838 case FLOOR_L_S: { // Mips32r2 instruction.
2839 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2840 float rounded = std::floor(fs);
2841 int64_t i64 = static_cast<int64_t>(rounded);
2842 if (IsFp64Mode()) {
2843 set_fpu_register(fd_reg, i64);
2844 if (set_fcsr_round64_error(fs, rounded)) {
2845 set_fpu_register(fd_reg, kFPU64InvalidResult);
2846 }
2847 } else {
2848 UNSUPPORTED();
2849 }
2850 break;
2851 }
2852 case ROUND_W_S: {
2853 float rounded = std::floor(fs + 0.5);
2854 int32_t result = static_cast<int32_t>(rounded);
2855 if ((result & 1) != 0 && result - fs == 0.5) {
2856 // If the number is halfway between two integers,
2857 // round to the even one.
2858 result--;
2859 }
2860 set_fpu_register_word(fd_reg, result);
2861 if (set_fcsr_round_error(fs, rounded)) {
2862 set_fpu_register_word(fd_reg, kFPUInvalidResult);
2863 }
2864 break;
2865 }
2866 case ROUND_L_S: { // Mips32r2 instruction.
2867 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2868 float rounded = std::floor(fs + 0.5);
2869 int64_t result = static_cast<int64_t>(rounded);
2870 if ((result & 1) != 0 && result - fs == 0.5) {
2871 // If the number is halfway between two integers,
2872 // round to the even one.
2873 result--;
2874 }
2875 int64_t i64 = static_cast<int64_t>(result);
2876 if (IsFp64Mode()) {
2877 set_fpu_register(fd_reg, i64);
2878 if (set_fcsr_round64_error(fs, rounded)) {
2879 set_fpu_register(fd_reg, kFPU64InvalidResult);
2880 }
2881 } else {
2882 UNSUPPORTED();
2883 }
2884 break;
2885 }
2886 case CEIL_W_S: // Round double to word towards positive infinity.
2887 {
2888 float rounded = std::ceil(fs);
2889 int32_t result = static_cast<int32_t>(rounded);
2890 set_fpu_register_word(fd_reg, result);
2891 if (set_fcsr_round_error(fs, rounded)) {
2892 set_fpu_register_word(fd_reg, kFPUInvalidResult);
2893 }
2894 } break;
2895 case CEIL_L_S: { // Mips32r2 instruction.
2896 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2897 float rounded = std::ceil(fs);
2898 int64_t i64 = static_cast<int64_t>(rounded);
2899 if (IsFp64Mode()) {
2900 set_fpu_register(fd_reg, i64);
2901 if (set_fcsr_round64_error(fs, rounded)) {
2902 set_fpu_register(fd_reg, kFPU64InvalidResult);
2903 }
2904 } else {
2905 UNSUPPORTED();
2906 }
2907 break;
2908 }
2909 case MIN:
2910 DCHECK(IsMipsArchVariant(kMips32r6));
2911 fs = get_fpu_register_float(fs_reg);
2912 if (std::isnan(fs) && std::isnan(ft)) {
2913 set_fpu_register_float(fd_reg, fs);
2914 } else if (std::isnan(fs) && !std::isnan(ft)) {
2915 set_fpu_register_float(fd_reg, ft);
2916 } else if (!std::isnan(fs) && std::isnan(ft)) {
2917 set_fpu_register_float(fd_reg, fs);
2918 } else {
2919 set_fpu_register_float(fd_reg, (fs >= ft) ? ft : fs);
2920 }
2921 break;
2922 case MAX:
2923 DCHECK(IsMipsArchVariant(kMips32r6));
2924 fs = get_fpu_register_float(fs_reg);
2925 if (std::isnan(fs) && std::isnan(ft)) {
2926 set_fpu_register_float(fd_reg, fs);
2927 } else if (std::isnan(fs) && !std::isnan(ft)) {
2928 set_fpu_register_float(fd_reg, ft);
2929 } else if (!std::isnan(fs) && std::isnan(ft)) {
2930 set_fpu_register_float(fd_reg, fs);
2931 } else {
2932 set_fpu_register_float(fd_reg, (fs <= ft) ? ft : fs);
2933 }
2934 break;
2935 case MINA:
2936 DCHECK(IsMipsArchVariant(kMips32r6));
2937 fs = get_fpu_register_float(fs_reg);
2938 if (std::isnan(fs) && std::isnan(ft)) {
2939 set_fpu_register_float(fd_reg, fs);
2940 } else if (std::isnan(fs) && !std::isnan(ft)) {
2941 set_fpu_register_float(fd_reg, ft);
2942 } else if (!std::isnan(fs) && std::isnan(ft)) {
2943 set_fpu_register_float(fd_reg, fs);
2944 } else {
2945 float result;
2946 if (fabs(fs) > fabs(ft)) {
2947 result = ft;
2948 } else if (fabs(fs) < fabs(ft)) {
2949 result = fs;
2950 } else {
2951 result = (fs > ft ? fs : ft);
2952 }
2953 set_fpu_register_float(fd_reg, result);
2954 }
2955 break;
2956 case MAXA:
2957 DCHECK(IsMipsArchVariant(kMips32r6));
2958 fs = get_fpu_register_float(fs_reg);
2959 if (std::isnan(fs) && std::isnan(ft)) {
2960 set_fpu_register_float(fd_reg, fs);
2961 } else if (std::isnan(fs) && !std::isnan(ft)) {
2962 set_fpu_register_float(fd_reg, ft);
2963 } else if (!std::isnan(fs) && std::isnan(ft)) {
2964 set_fpu_register_float(fd_reg, fs);
2965 } else {
2966 float result;
2967 if (fabs(fs) < fabs(ft)) {
2968 result = ft;
2969 } else if (fabs(fs) > fabs(ft)) {
2970 result = fs;
2971 } else {
2972 result = (fs > ft ? fs : ft);
2973 }
2974 set_fpu_register_float(fd_reg, result);
2975 }
2976 break; 2521 break;
2977 default: 2522 default:
2978 // CVT_W_S CVT_L_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S 2523 // CVT_W_S CVT_L_S TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S
2979 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. 2524 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented.
2980 UNREACHABLE(); 2525 UNREACHABLE();
2981 } 2526 }
2982 } 2527 }
2983 2528
2984 2529
2985 void Simulator::DecodeTypeRegisterLRsType(Instruction* instr, 2530 void Simulator::DecodeTypeRegisterLRsType(Instruction* instr,
2986 const int32_t& ft_reg, 2531 const int32_t& ft_reg,
2987 const int32_t& fs_reg, 2532 const int32_t& fs_reg,
2988 const int32_t& fd_reg) { 2533 const int32_t& fd_reg) {
(...skipping 1000 matching lines...) Expand 10 before | Expand all | Expand 10 after
3989 } 3534 }
3990 3535
3991 3536
3992 #undef UNSUPPORTED 3537 #undef UNSUPPORTED
3993 3538
3994 } } // namespace v8::internal 3539 } } // namespace v8::internal
3995 3540
3996 #endif // USE_SIMULATOR 3541 #endif // USE_SIMULATOR
3997 3542
3998 #endif // V8_TARGET_ARCH_MIPS 3543 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « src/mips/simulator-mips.h ('k') | src/mips64/assembler-mips64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698