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

Side by Side Diff: src/mips/simulator-mips.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, 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 1254 matching lines...) Expand 10 before | Expand all | Expand 10 after
1265 FCSR_ &= ~(1 << cc); 1265 FCSR_ &= ~(1 << cc);
1266 } 1266 }
1267 } 1267 }
1268 1268
1269 1269
1270 bool Simulator::test_fcsr_bit(uint32_t cc) { 1270 bool Simulator::test_fcsr_bit(uint32_t cc) {
1271 return FCSR_ & (1 << cc); 1271 return FCSR_ & (1 << cc);
1272 } 1272 }
1273 1273
1274 1274
1275 void Simulator::set_fcsr_rounding_mode(FPURoundingMode mode) {
1276 FCSR_ |= mode & kFPURoundingModeMask;
1277 }
1278
1279
1280 unsigned int Simulator::get_fcsr_rounding_mode() {
1281 return FCSR_ & kFPURoundingModeMask;
1282 }
1283
1284
1275 // 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.
1276 // Returns true if the operation was invalid. 1286 // Returns true if the operation was invalid.
1277 bool Simulator::set_fcsr_round_error(double original, double rounded) { 1287 bool Simulator::set_fcsr_round_error(double original, double rounded) {
1278 bool ret = false; 1288 bool ret = false;
1279 double max_int32 = std::numeric_limits<int32_t>::max(); 1289 double max_int32 = std::numeric_limits<int32_t>::max();
1280 double min_int32 = std::numeric_limits<int32_t>::min(); 1290 double min_int32 = std::numeric_limits<int32_t>::min();
1281 1291
1282 if (!std::isfinite(original) || !std::isfinite(rounded)) { 1292 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1283 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1293 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1284 ret = true; 1294 ret = true;
(...skipping 12 matching lines...) Expand all
1297 set_fcsr_bit(kFCSROverflowFlagBit, true); 1307 set_fcsr_bit(kFCSROverflowFlagBit, true);
1298 // 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:
1299 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1309 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1300 ret = true; 1310 ret = true;
1301 } 1311 }
1302 1312
1303 return ret; 1313 return ret;
1304 } 1314 }
1305 1315
1306 1316
1317 void Simulator::round_according_to_fcsr(double toRound, double& rounded,
1318 int32_t& rounded_int, double fs) {
1319 // 0 RN (round to nearest): Round a result to the nearest
1320 // representable value; if the result is exactly halfway between
1321 // two representable values, round to zero. Behave like round_w_d.
1322
1323 // 1 RZ (round toward zero): Round a result to the closest
1324 // representable value whose absolute value is less than or
1325 // equal to the infinitely accurate result. Behave like trunc_w_d.
1326
1327 // 2 RP (round up, or toward infinity): Round a result to the
1328 // next representable value up. Behave like ceil_w_d.
1329
1330 // 3 RD (round down, or toward −infinity): Round a result to
1331 // the next representable value down. Behave like floor_w_d.
1332 switch (get_fcsr_rounding_mode()) {
1333 case kRoundToNearest:
1334 rounded = std::floor(fs + 0.5);
1335 rounded_int = static_cast<int32_t>(rounded);
1336 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
1337 // If the number is halfway between two integers,
1338 // round to the even one.
1339 rounded_int--;
1340 }
1341 break;
1342 case kRoundToZero:
1343 rounded = trunc(fs);
1344 rounded_int = static_cast<int32_t>(rounded);
1345 break;
1346 case kRoundToPlusInf:
1347 rounded = std::ceil(fs);
1348 rounded_int = static_cast<int32_t>(rounded);
1349 break;
1350 case kRoundToMinusInf:
1351 rounded = std::floor(fs);
1352 rounded_int = static_cast<int32_t>(rounded);
1353 break;
1354 }
1355 }
1356
1357
1307 // Raw access to the PC register. 1358 // Raw access to the PC register.
1308 void Simulator::set_pc(int32_t value) { 1359 void Simulator::set_pc(int32_t value) {
1309 pc_modified_ = true; 1360 pc_modified_ = true;
1310 registers_[pc] = value; 1361 registers_[pc] = value;
1311 } 1362 }
1312 1363
1313 1364
1314 bool Simulator::has_bad_pc() const { 1365 bool Simulator::has_bad_pc() const {
1315 return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc)); 1366 return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc));
1316 } 1367 }
(...skipping 822 matching lines...) Expand 10 before | Expand all | Expand 10 after
2139 double ft, fs, fd; 2190 double ft, fs, fd;
2140 uint32_t cc, fcsr_cc; 2191 uint32_t cc, fcsr_cc;
2141 int64_t i64; 2192 int64_t i64;
2142 fs = get_fpu_register_double(fs_reg); 2193 fs = get_fpu_register_double(fs_reg);
2143 ft = get_fpu_register_double(ft_reg); 2194 ft = get_fpu_register_double(ft_reg);
2144 int64_t ft_int = bit_cast<int64_t>(ft); 2195 int64_t ft_int = bit_cast<int64_t>(ft);
2145 int64_t fd_int = bit_cast<int64_t>(fd); 2196 int64_t fd_int = bit_cast<int64_t>(fd);
2146 cc = instr->FCccValue(); 2197 cc = instr->FCccValue();
2147 fcsr_cc = get_fcsr_condition_bit(cc); 2198 fcsr_cc = get_fcsr_condition_bit(cc);
2148 switch (instr->FunctionFieldRaw()) { 2199 switch (instr->FunctionFieldRaw()) {
2200 case RINT: {
2201 DCHECK(IsMipsArchVariant(kMips32r6));
2202 double result, temp, temp_result;
2203 double upper = std::ceil(fs);
2204 double lower = std::floor(fs);
2205 switch (get_fcsr_rounding_mode()) {
2206 case kRoundToNearest:
2207 if (upper - fs < fs - lower) {
2208 result = upper;
2209 } else if (upper - fs > fs - lower) {
2210 result = lower;
2211 } else {
2212 temp_result = upper / 2;
2213 double reminder = modf(temp_result, &temp);
2214 if (reminder == 0) {
2215 result = upper;
2216 } else {
2217 result = lower;
2218 }
2219 }
2220 break;
2221 case kRoundToZero:
2222 result = (fs > 0 ? lower : upper);
2223 break;
2224 case kRoundToPlusInf:
2225 result = upper;
2226 break;
2227 case kRoundToMinusInf:
2228 result = lower;
2229 break;
2230 }
2231 set_fpu_register_double(fd_reg, result);
2232 if (result != fs) {
2233 set_fcsr_bit(kFCSRInexactFlagBit, true);
2234 }
2235 break;
2236 }
2149 case SEL: 2237 case SEL:
2150 DCHECK(IsMipsArchVariant(kMips32r6)); 2238 DCHECK(IsMipsArchVariant(kMips32r6));
2151 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);
2152 break; 2240 break;
2153 case SELEQZ_C: 2241 case SELEQZ_C:
2154 DCHECK(IsMipsArchVariant(kMips32r6)); 2242 DCHECK(IsMipsArchVariant(kMips32r6));
2155 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);
2156 break; 2244 break;
2157 case SELNEZ_C: 2245 case SELNEZ_C:
2158 DCHECK(IsMipsArchVariant(kMips32r6)); 2246 DCHECK(IsMipsArchVariant(kMips32r6));
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
2223 break; 2311 break;
2224 case C_ULT_D: 2312 case C_ULT_D:
2225 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); 2313 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
2226 break; 2314 break;
2227 case C_OLE_D: 2315 case C_OLE_D:
2228 set_fcsr_bit(fcsr_cc, (fs <= ft)); 2316 set_fcsr_bit(fcsr_cc, (fs <= ft));
2229 break; 2317 break;
2230 case C_ULE_D: 2318 case C_ULE_D:
2231 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); 2319 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
2232 break; 2320 break;
2233 case CVT_W_D: // Convert double to word. 2321 case CVT_W_D: { // Convert double to word.
2234 // Rounding modes are not yet supported. 2322 double rounded;
2235 DCHECK((FCSR_ & 3) == 0); 2323 int32_t result;
2236 // In rounding mode 0 it should behave like ROUND. 2324 round_according_to_fcsr(fs, rounded, result, fs);
2325 set_fpu_register_word(fd_reg, result);
2326 if (set_fcsr_round_error(fs, rounded)) {
2327 set_fpu_register_word(fd_reg, kFPUInvalidResult);
2328 }
2329 } break;
2237 case ROUND_W_D: // Round double to word (round half to even). 2330 case ROUND_W_D: // Round double to word (round half to even).
2238 { 2331 {
2239 double rounded = std::floor(fs + 0.5); 2332 double rounded = std::floor(fs + 0.5);
2240 int32_t result = static_cast<int32_t>(rounded); 2333 int32_t result = static_cast<int32_t>(rounded);
2241 if ((result & 1) != 0 && result - fs == 0.5) { 2334 if ((result & 1) != 0 && result - fs == 0.5) {
2242 // If the number is halfway between two integers, 2335 // If the number is halfway between two integers,
2243 // round to the even one. 2336 // round to the even one.
2244 result--; 2337 result--;
2245 } 2338 }
2246 set_fpu_register_word(fd_reg, result); 2339 set_fpu_register_word(fd_reg, result);
(...skipping 1194 matching lines...) Expand 10 before | Expand all | Expand 10 after
3441 } 3534 }
3442 3535
3443 3536
3444 #undef UNSUPPORTED 3537 #undef UNSUPPORTED
3445 3538
3446 } } // namespace v8::internal 3539 } } // namespace v8::internal
3447 3540
3448 #endif // USE_SIMULATOR 3541 #endif // USE_SIMULATOR
3449 3542
3450 #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