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 1234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1245 set_fcsr_bit(kFCSROverflowFlagBit, true); | 1245 set_fcsr_bit(kFCSROverflowFlagBit, true); |
1246 // The reference is not really clear but it seems this is required: | 1246 // The reference is not really clear but it seems this is required: |
1247 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); | 1247 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); |
1248 ret = true; | 1248 ret = true; |
1249 } | 1249 } |
1250 | 1250 |
1251 return ret; | 1251 return ret; |
1252 } | 1252 } |
1253 | 1253 |
1254 | 1254 |
1255 // for cvt instructions only | |
paul.l...
2015/04/27 05:12:50
Style nit: Comments should start with capital lett
Djordje.Pesic
2015/04/27 12:46:58
I've dropped the comment
| |
1256 void Simulator::round_according_to_fcsr(double toRound, double& rounded, | |
1257 int32_t& rounded_int, double fs) { | |
1258 // 0 RN (round to nearest): Round a result to the nearest | |
1259 // representable value; if the result is exactly halfway between | |
1260 // two representable values, round to zero. Behave like round_w_d | |
1261 | |
1262 // 1 RZ (round toward zero): Round a result to the closest | |
1263 // representable value whose absolute value is less than or | |
1264 // equal to the infinitely accurate result. Behave like trunc_w_d | |
1265 | |
1266 // 2 RP (round up, or toward +infinity): Round a result to the | |
1267 // next representable value up. Behave like ceil_w_d | |
1268 | |
1269 // 3 RN (round down, or toward −infinity): Round a result to | |
1270 // the next representable value down. Behave like floor_w_d | |
1271 switch (FCSR_ & 3) { | |
1272 case kRoundToNearest: | |
1273 rounded = std::floor(fs + 0.5); | |
1274 rounded_int = static_cast<int32_t>(rounded); | |
1275 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) { | |
1276 // If the number is halfway between two integers, | |
1277 // round to the even one. | |
1278 rounded_int--; | |
1279 } | |
1280 break; | |
1281 case kRoundToZero: | |
1282 rounded = trunc(fs); | |
1283 rounded_int = static_cast<int32_t>(rounded); | |
1284 break; | |
1285 case kRoundToPlusInf: | |
1286 rounded = std::ceil(fs); | |
1287 rounded_int = static_cast<int32_t>(rounded); | |
1288 break; | |
1289 case kRoundToMinusInf: | |
1290 rounded = std::floor(fs); | |
1291 rounded_int = static_cast<int32_t>(rounded); | |
1292 break; | |
1293 } | |
1294 } | |
1295 | |
1296 | |
1297 // for cvt instructions only | |
1298 void Simulator::round64_according_to_fcsr(double toRound, double& rounded, | |
1299 int64_t& rounded_int, double fs) { | |
1300 // 0 RN (round to nearest): Round a result to the nearest | |
1301 // representable value; if the result is exactly halfway between | |
1302 // two representable values, round to zero. Behave like round_w_d | |
1303 | |
1304 // 1 RZ (round toward zero): Round a result to the closest | |
1305 // representable value whose absolute value is less than or | |
1306 // equal to the infinitely accurate result. Behave like trunc_w_d | |
1307 | |
1308 // 2 RP (round up, or toward +infinity): Round a result to the | |
1309 // next representable value up. Behave like ceil_w_d | |
1310 | |
1311 // 3 RN (round down, or toward −infinity): Round a result to | |
1312 // the next representable value down. Behave like floor_w_d | |
1313 switch (FCSR_ & 3) { | |
1314 case kRoundToNearest: | |
1315 rounded = std::floor(fs + 0.5); | |
1316 rounded_int = static_cast<int64_t>(rounded); | |
1317 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) { | |
1318 // If the number is halfway between two integers, | |
1319 // round to the even one. | |
1320 rounded_int--; | |
1321 } | |
1322 break; | |
1323 case kRoundToZero: | |
1324 rounded = trunc(fs); | |
1325 rounded_int = static_cast<int64_t>(rounded); | |
1326 break; | |
1327 case kRoundToPlusInf: | |
1328 rounded = std::ceil(fs); | |
1329 rounded_int = static_cast<int64_t>(rounded); | |
1330 break; | |
1331 case kRoundToMinusInf: | |
1332 rounded = std::floor(fs); | |
1333 rounded_int = static_cast<int64_t>(rounded); | |
1334 break; | |
1335 } | |
1336 } | |
1337 | |
1338 | |
1255 // Raw access to the PC register. | 1339 // Raw access to the PC register. |
1256 void Simulator::set_pc(int64_t value) { | 1340 void Simulator::set_pc(int64_t value) { |
1257 pc_modified_ = true; | 1341 pc_modified_ = true; |
1258 registers_[pc] = value; | 1342 registers_[pc] = value; |
1259 } | 1343 } |
1260 | 1344 |
1261 | 1345 |
1262 bool Simulator::has_bad_pc() const { | 1346 bool Simulator::has_bad_pc() const { |
1263 return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc)); | 1347 return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc)); |
1264 } | 1348 } |
(...skipping 1078 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2343 double ft, fs, fd; | 2427 double ft, fs, fd; |
2344 uint32_t cc, fcsr_cc; | 2428 uint32_t cc, fcsr_cc; |
2345 fs = get_fpu_register_double(fs_reg); | 2429 fs = get_fpu_register_double(fs_reg); |
2346 ft = get_fpu_register_double(ft_reg); | 2430 ft = get_fpu_register_double(ft_reg); |
2347 fd = get_fpu_register_double(fd_reg); | 2431 fd = get_fpu_register_double(fd_reg); |
2348 cc = instr->FCccValue(); | 2432 cc = instr->FCccValue(); |
2349 fcsr_cc = get_fcsr_condition_bit(cc); | 2433 fcsr_cc = get_fcsr_condition_bit(cc); |
2350 int64_t ft_int = bit_cast<int64_t>(ft); | 2434 int64_t ft_int = bit_cast<int64_t>(ft); |
2351 int64_t fd_int = bit_cast<int64_t>(fd); | 2435 int64_t fd_int = bit_cast<int64_t>(fd); |
2352 switch (instr->FunctionFieldRaw()) { | 2436 switch (instr->FunctionFieldRaw()) { |
2437 case RINT: { | |
2438 DCHECK(kArchVariant == kMips64r6); | |
2439 double result, temp, temp_result; | |
2440 double upper = std::ceil(fs); | |
2441 double lower = std::floor(fs); | |
2442 switch (FCSR_ & 0x3) { | |
2443 case kRoundToNearest: | |
2444 if (upper - fs < fs - lower) { | |
2445 result = upper; | |
2446 } else if (upper - fs > fs - lower) { | |
2447 result = lower; | |
2448 } else { | |
2449 temp_result = upper / 2; | |
2450 double reminder = modf(temp_result, &temp); | |
2451 if (reminder == 0) { | |
2452 result = upper; | |
2453 } else { | |
2454 result = lower; | |
2455 } | |
2456 } | |
2457 break; | |
2458 case kRoundToZero: | |
2459 result = (fs > 0 ? lower : upper); | |
2460 break; | |
2461 case kRoundToPlusInf: | |
2462 result = upper; | |
2463 break; | |
2464 case kRoundToMinusInf: | |
2465 result = lower; | |
2466 break; | |
2467 } | |
2468 set_fpu_register_double(fd_reg, result); | |
2469 if (result != fs) { | |
2470 set_fcsr_bit(kFCSRInexactFlagBit, true); | |
2471 } | |
2472 break; | |
2473 } | |
2353 case SEL: | 2474 case SEL: |
2354 DCHECK(kArchVariant == kMips64r6); | 2475 DCHECK(kArchVariant == kMips64r6); |
2355 set_fpu_register_double(fd_reg, (fd_int & 0x1) == 0 ? fs : ft); | 2476 set_fpu_register_double(fd_reg, (fd_int & 0x1) == 0 ? fs : ft); |
2356 break; | 2477 break; |
2357 case SELEQZ_C: | 2478 case SELEQZ_C: |
2358 DCHECK(kArchVariant == kMips64r6); | 2479 DCHECK(kArchVariant == kMips64r6); |
2359 set_fpu_register_double(fd_reg, (ft_int & 0x1) == 0 ? fs : 0.0); | 2480 set_fpu_register_double(fd_reg, (ft_int & 0x1) == 0 ? fs : 0.0); |
2360 break; | 2481 break; |
2361 case SELNEZ_C: | 2482 case SELNEZ_C: |
2362 DCHECK(kArchVariant == kMips64r6); | 2483 DCHECK(kArchVariant == kMips64r6); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2426 break; | 2547 break; |
2427 case C_ULT_D: | 2548 case C_ULT_D: |
2428 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); | 2549 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); |
2429 break; | 2550 break; |
2430 case C_OLE_D: | 2551 case C_OLE_D: |
2431 set_fcsr_bit(fcsr_cc, (fs <= ft)); | 2552 set_fcsr_bit(fcsr_cc, (fs <= ft)); |
2432 break; | 2553 break; |
2433 case C_ULE_D: | 2554 case C_ULE_D: |
2434 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); | 2555 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); |
2435 break; | 2556 break; |
2436 case CVT_W_D: // Convert double to word. | 2557 case CVT_W_D: { // Convert double to word. |
2437 // Rounding modes are not yet supported. | 2558 double rounded; |
2438 DCHECK((FCSR_ & 3) == 0); | 2559 int32_t result; |
2439 // In rounding mode 0 it should behave like ROUND. | 2560 round_according_to_fcsr(fs, rounded, result, fs); |
2440 // No break. | 2561 set_fpu_register_word(fd_reg, result); |
2562 if (set_fcsr_round_error(fs, rounded)) { | |
2563 set_fpu_register_word(fd_reg, kFPUInvalidResult); | |
2564 } | |
2565 break; | |
2566 } | |
2441 case ROUND_W_D: // Round double to word (round half to even). | 2567 case ROUND_W_D: // Round double to word (round half to even). |
2442 { | 2568 { |
2443 double rounded = std::floor(fs + 0.5); | 2569 double rounded = std::floor(fs + 0.5); |
2444 int32_t result = static_cast<int32_t>(rounded); | 2570 int32_t result = static_cast<int32_t>(rounded); |
2445 if ((result & 1) != 0 && result - fs == 0.5) { | 2571 if ((result & 1) != 0 && result - fs == 0.5) { |
2446 // If the number is halfway between two integers, | 2572 // If the number is halfway between two integers, |
2447 // round to the even one. | 2573 // round to the even one. |
2448 result--; | 2574 result--; |
2449 } | 2575 } |
2450 set_fpu_register_word(fd_reg, result); | 2576 set_fpu_register_word(fd_reg, result); |
(...skipping 24 matching lines...) Expand all Loading... | |
2475 double rounded = std::ceil(fs); | 2601 double rounded = std::ceil(fs); |
2476 int32_t result = static_cast<int32_t>(rounded); | 2602 int32_t result = static_cast<int32_t>(rounded); |
2477 set_fpu_register_word(fd_reg, result); | 2603 set_fpu_register_word(fd_reg, result); |
2478 if (set_fcsr_round_error(fs, rounded)) { | 2604 if (set_fcsr_round_error(fs, rounded)) { |
2479 set_fpu_register(fd_reg, kFPUInvalidResult); | 2605 set_fpu_register(fd_reg, kFPUInvalidResult); |
2480 } | 2606 } |
2481 } break; | 2607 } break; |
2482 case CVT_S_D: // Convert double to float (single). | 2608 case CVT_S_D: // Convert double to float (single). |
2483 set_fpu_register_float(fd_reg, static_cast<float>(fs)); | 2609 set_fpu_register_float(fd_reg, static_cast<float>(fs)); |
2484 break; | 2610 break; |
2485 case CVT_L_D: // Mips64r2: Truncate double to 64-bit long-word. | 2611 case CVT_L_D: { // Mips64r2: Truncate double to 64-bit long-word. |
2486 // Rounding modes are not yet supported. | 2612 double rounded; |
2487 DCHECK((FCSR_ & 3) == 0); | 2613 int64_t result; |
2488 // In rounding mode 0 it should behave like ROUND. | 2614 round64_according_to_fcsr(fs, rounded, result, fs); |
2489 // No break. | 2615 set_fpu_register(fd_reg, result); |
2616 if (set_fcsr_round64_error(fs, rounded)) { | |
2617 set_fpu_register(fd_reg, kFPUInvalidResult); | |
2618 } | |
2619 break; | |
2620 } | |
2490 case ROUND_L_D: { // Mips64r2 instruction. | 2621 case ROUND_L_D: { // Mips64r2 instruction. |
2491 // check error cases | 2622 // check error cases |
2492 double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5); | 2623 double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5); |
2493 int64_t result = static_cast<int64_t>(rounded); | 2624 int64_t result = static_cast<int64_t>(rounded); |
2494 set_fpu_register(fd_reg, result); | 2625 set_fpu_register(fd_reg, result); |
2495 if (set_fcsr_round64_error(fs, rounded)) { | 2626 if (set_fcsr_round64_error(fs, rounded)) { |
2496 set_fpu_register(fd_reg, kFPU64InvalidResult); | 2627 set_fpu_register(fd_reg, kFPU64InvalidResult); |
2497 } | 2628 } |
2498 break; | 2629 break; |
2499 } | 2630 } |
(...skipping 1116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3616 uintptr_t Simulator::PopAddress() { | 3747 uintptr_t Simulator::PopAddress() { |
3617 int64_t current_sp = get_register(sp); | 3748 int64_t current_sp = get_register(sp); |
3618 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); | 3749 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); |
3619 uintptr_t address = *stack_slot; | 3750 uintptr_t address = *stack_slot; |
3620 set_register(sp, current_sp + sizeof(uintptr_t)); | 3751 set_register(sp, current_sp + sizeof(uintptr_t)); |
3621 return address; | 3752 return address; |
3622 } | 3753 } |
3623 | 3754 |
3624 | 3755 |
3625 #undef UNSUPPORTED | 3756 #undef UNSUPPORTED |
3626 | |
3627 } } // namespace v8::internal | 3757 } } // namespace v8::internal |
3628 | 3758 |
3629 #endif // USE_SIMULATOR | 3759 #endif // USE_SIMULATOR |
3630 | 3760 |
3631 #endif // V8_TARGET_ARCH_MIPS64 | 3761 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |