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

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

Issue 1108583003: MIPS: Add rounding support in simulator and RINT instruction. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 8 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 1234 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698