Index: src/arm/simulator-arm.cc |
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc |
index e3ef926ca0c0f88afc6c49bed1f55a02a27995a9..f043f1fffe46e0f0f2de412e048b800e1edaabc9 100644 |
--- a/src/arm/simulator-arm.cc |
+++ b/src/arm/simulator-arm.cc |
@@ -773,6 +773,7 @@ Simulator::Simulator(Isolate* isolate) : isolate_(isolate) { |
c_flag_FPSCR_ = false; |
v_flag_FPSCR_ = false; |
FPSCR_rounding_mode_ = RZ; |
+ FPSCR_default_NaN_mode_ = true; |
inv_op_vfp_flag_ = false; |
div_zero_vfp_flag_ = false; |
@@ -1868,6 +1869,11 @@ void Simulator::SoftwareInterrupt(Instruction* instr) { |
} |
+double Simulator::canonicalizeNaN(double value) { |
+ return (FPSCR_default_NaN_mode_ && isnan(value)) ? |
+ FixedDoubleArray::canonical_not_the_hole_nan_as_double(): value; |
ulan
2013/04/15 15:00:56
Add space before ":".
|
+} |
+ |
// Stop helper functions. |
bool Simulator::isStopInstruction(Instruction* instr) { |
return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode); |
@@ -2728,11 +2734,13 @@ void Simulator::DecodeTypeVFP(Instruction* instr) { |
// vabs |
double dm_value = get_double_from_d_register(vm); |
double dd_value = fabs(dm_value); |
+ dd_value = canonicalizeNaN(dd_value); |
set_d_register_from_double(vd, dd_value); |
} else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) { |
// vneg |
double dm_value = get_double_from_d_register(vm); |
double dd_value = -dm_value; |
+ dd_value = canonicalizeNaN(dd_value); |
set_d_register_from_double(vd, dd_value); |
} else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) { |
DecodeVCVTBetweenDoubleAndSingle(instr); |
@@ -2748,6 +2756,7 @@ void Simulator::DecodeTypeVFP(Instruction* instr) { |
// vsqrt |
double dm_value = get_double_from_d_register(vm); |
double dd_value = sqrt(dm_value); |
+ dd_value = canonicalizeNaN(dd_value); |
set_d_register_from_double(vd, dd_value); |
} else if (instr->Opc3Value() == 0x0) { |
// vmov immediate. |
@@ -2769,12 +2778,14 @@ void Simulator::DecodeTypeVFP(Instruction* instr) { |
double dn_value = get_double_from_d_register(vn); |
double dm_value = get_double_from_d_register(vm); |
double dd_value = dn_value - dm_value; |
+ dd_value = canonicalizeNaN(dd_value); |
set_d_register_from_double(vd, dd_value); |
} else { |
// vadd |
double dn_value = get_double_from_d_register(vn); |
double dm_value = get_double_from_d_register(vm); |
double dd_value = dn_value + dm_value; |
+ dd_value = canonicalizeNaN(dd_value); |
set_d_register_from_double(vd, dd_value); |
} |
} else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) { |
@@ -2786,6 +2797,7 @@ void Simulator::DecodeTypeVFP(Instruction* instr) { |
double dn_value = get_double_from_d_register(vn); |
double dm_value = get_double_from_d_register(vm); |
double dd_value = dn_value * dm_value; |
+ dd_value = canonicalizeNaN(dd_value); |
set_d_register_from_double(vd, dd_value); |
} else if ((instr->Opc1Value() == 0x0)) { |
// vmla, vmls |
@@ -2803,9 +2815,13 @@ void Simulator::DecodeTypeVFP(Instruction* instr) { |
// result with too high precision. |
set_d_register_from_double(vd, dn_val * dm_val); |
if (is_vmls) { |
- set_d_register_from_double(vd, dd_val - get_double_from_d_register(vd)); |
+ set_d_register_from_double( |
+ vd, |
+ canonicalizeNaN(dd_val - get_double_from_d_register(vd))); |
} else { |
- set_d_register_from_double(vd, dd_val + get_double_from_d_register(vd)); |
+ set_d_register_from_double( |
+ vd, |
+ canonicalizeNaN(dd_val + get_double_from_d_register(vd))); |
} |
} else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) { |
// vdiv |
@@ -2817,6 +2833,7 @@ void Simulator::DecodeTypeVFP(Instruction* instr) { |
double dm_value = get_double_from_d_register(vm); |
double dd_value = dn_value / dm_value; |
div_zero_vfp_flag_ = (dm_value == 0); |
+ dd_value = canonicalizeNaN(dd_value); |
set_d_register_from_double(vd, dd_value); |
} else { |
UNIMPLEMENTED(); // Not used by V8. |
@@ -2850,6 +2867,7 @@ void Simulator::DecodeTypeVFP(Instruction* instr) { |
(z_flag_FPSCR_ << 30) | |
(c_flag_FPSCR_ << 29) | |
(v_flag_FPSCR_ << 28) | |
+ (FPSCR_default_NaN_mode_ << 25) | |
(inexact_vfp_flag_ << 4) | |
(underflow_vfp_flag_ << 3) | |
(overflow_vfp_flag_ << 2) | |
@@ -2872,6 +2890,7 @@ void Simulator::DecodeTypeVFP(Instruction* instr) { |
z_flag_FPSCR_ = (rt_value >> 30) & 1; |
c_flag_FPSCR_ = (rt_value >> 29) & 1; |
v_flag_FPSCR_ = (rt_value >> 28) & 1; |
+ FPSCR_default_NaN_mode_ = (rt_value >> 25) & 1; |
inexact_vfp_flag_ = (rt_value >> 4) & 1; |
underflow_vfp_flag_ = (rt_value >> 3) & 1; |
overflow_vfp_flag_ = (rt_value >> 2) & 1; |