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

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

Powered by Google App Engine
This is Rietveld 408576698