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 |