| 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 1254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |