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 1264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |