summaryrefslogtreecommitdiff
path: root/deps/v8/src/arm/simulator-arm.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/arm/simulator-arm.cc')
-rw-r--r--deps/v8/src/arm/simulator-arm.cc108
1 files changed, 93 insertions, 15 deletions
diff --git a/deps/v8/src/arm/simulator-arm.cc b/deps/v8/src/arm/simulator-arm.cc
index cb91520f3a..3ec5f449d8 100644
--- a/deps/v8/src/arm/simulator-arm.cc
+++ b/deps/v8/src/arm/simulator-arm.cc
@@ -705,6 +705,7 @@ Simulator::Simulator() {
z_flag_FPSCR_ = false;
c_flag_FPSCR_ = false;
v_flag_FPSCR_ = false;
+ FPSCR_rounding_mode_ = RZ;
inv_op_vfp_flag_ = false;
div_zero_vfp_flag_ = false;
@@ -2501,10 +2502,45 @@ void Simulator::DecodeTypeVFP(Instr* instr) {
(instr->VAField() == 0x7) &&
(instr->Bits(19, 16) == 0x1)) {
// vmrs
- if (instr->RtField() == 0xF)
+ uint32_t rt = instr->RtField();
+ if (rt == 0xF) {
Copy_FPSCR_to_APSR();
- else
- UNIMPLEMENTED(); // Not used by V8.
+ } else {
+ // Emulate FPSCR from the Simulator flags.
+ uint32_t fpscr = (n_flag_FPSCR_ << 31) |
+ (z_flag_FPSCR_ << 30) |
+ (c_flag_FPSCR_ << 29) |
+ (v_flag_FPSCR_ << 28) |
+ (inexact_vfp_flag_ << 4) |
+ (underflow_vfp_flag_ << 3) |
+ (overflow_vfp_flag_ << 2) |
+ (div_zero_vfp_flag_ << 1) |
+ (inv_op_vfp_flag_ << 0) |
+ (FPSCR_rounding_mode_ << 22);
+ set_register(rt, fpscr);
+ }
+ } else if ((instr->VLField() == 0x0) &&
+ (instr->VCField() == 0x0) &&
+ (instr->VAField() == 0x7) &&
+ (instr->Bits(19, 16) == 0x1)) {
+ // vmsr
+ uint32_t rt = instr->RtField();
+ if (rt == pc) {
+ UNREACHABLE();
+ } else {
+ uint32_t rt_value = get_register(rt);
+ n_flag_FPSCR_ = (rt_value >> 31) & 1;
+ z_flag_FPSCR_ = (rt_value >> 30) & 1;
+ c_flag_FPSCR_ = (rt_value >> 29) & 1;
+ v_flag_FPSCR_ = (rt_value >> 28) & 1;
+ inexact_vfp_flag_ = (rt_value >> 4) & 1;
+ underflow_vfp_flag_ = (rt_value >> 3) & 1;
+ overflow_vfp_flag_ = (rt_value >> 2) & 1;
+ div_zero_vfp_flag_ = (rt_value >> 1) & 1;
+ inv_op_vfp_flag_ = (rt_value >> 0) & 1;
+ FPSCR_rounding_mode_ =
+ static_cast<FPSCRRoundingModes>((rt_value >> 22) & 3);
+ }
} else {
UNIMPLEMENTED(); // Not used by V8.
}
@@ -2605,29 +2641,71 @@ void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr) {
if (to_integer) {
bool unsigned_integer = (instr->Bit(16) == 0);
+ FPSCRRoundingModes mode;
if (instr->Bit(7) != 1) {
- // Only rounding towards zero supported.
- UNIMPLEMENTED(); // Not used by V8.
+ // Use FPSCR defined rounding mode.
+ mode = FPSCR_rounding_mode_;
+ // Only RZ and RM modes are supported.
+ ASSERT((mode == RM) || (mode == RZ));
+ } else {
+ // VFP uses round towards zero by default.
+ mode = RZ;
}
int dst = instr->VFPDRegCode(kSinglePrecision);
int src = instr->VFPMRegCode(src_precision);
+ int32_t kMaxInt = v8::internal::kMaxInt;
+ int32_t kMinInt = v8::internal::kMinInt;
+ switch (mode) {
+ case RM:
+ if (src_precision == kDoublePrecision) {
+ double val = get_double_from_d_register(src);
- if (src_precision == kDoublePrecision) {
- double val = get_double_from_d_register(src);
+ inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val);
- int sint = unsigned_integer ? static_cast<uint32_t>(val) :
- static_cast<int32_t>(val);
+ int sint = unsigned_integer ? static_cast<uint32_t>(val) :
+ static_cast<int32_t>(val);
+ sint = sint > val ? sint - 1 : sint;
- set_s_register_from_sinteger(dst, sint);
- } else {
- float val = get_float_from_s_register(src);
+ set_s_register_from_sinteger(dst, sint);
+ } else {
+ float val = get_float_from_s_register(src);
+
+ inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val);
- int sint = unsigned_integer ? static_cast<uint32_t>(val) :
- static_cast<int32_t>(val);
+ int sint = unsigned_integer ? static_cast<uint32_t>(val) :
+ static_cast<int32_t>(val);
+ sint = sint > val ? sint - 1 : sint;
- set_s_register_from_sinteger(dst, sint);
+ set_s_register_from_sinteger(dst, sint);
+ }
+ break;
+ case RZ:
+ if (src_precision == kDoublePrecision) {
+ double val = get_double_from_d_register(src);
+
+ inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val);
+
+ int sint = unsigned_integer ? static_cast<uint32_t>(val) :
+ static_cast<int32_t>(val);
+
+ set_s_register_from_sinteger(dst, sint);
+ } else {
+ float val = get_float_from_s_register(src);
+
+ inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val);
+
+ int sint = unsigned_integer ? static_cast<uint32_t>(val) :
+ static_cast<int32_t>(val);
+
+ set_s_register_from_sinteger(dst, sint);
+ }
+ break;
+
+ default:
+ UNREACHABLE();
}
+
} else {
bool unsigned_integer = (instr->Bit(7) == 0);