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

Powered by Google App Engine
This is Rietveld 408576698