Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Unified Diff: src/arm/simulator-arm.cc

Issue 1044793002: [turbofan] Add backend support for float32 operations. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add MachineOperator unit tests. Created 5 years, 9 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 side-by-side diff with in-line comments
Download patch
Index: src/arm/simulator-arm.cc
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc
index 4c681ae764516170d68f6c0f0642e6e43e4d5d59..c972b42a7393b1cc391e54a0e910d2104873a43b 100644
--- a/src/arm/simulator-arm.cc
+++ b/src/arm/simulator-arm.cc
@@ -1309,6 +1309,33 @@ bool Simulator::OverflowFrom(int32_t alu_out,
// Support for VFP comparisons.
+void Simulator::Compute_FPSCR_Flags(float val1, float val2) {
+ if (std::isnan(val1) || std::isnan(val2)) {
+ n_flag_FPSCR_ = false;
+ z_flag_FPSCR_ = false;
+ c_flag_FPSCR_ = true;
+ v_flag_FPSCR_ = true;
+ // All non-NaN cases.
+ } else if (val1 == val2) {
+ n_flag_FPSCR_ = false;
+ z_flag_FPSCR_ = true;
+ c_flag_FPSCR_ = true;
+ v_flag_FPSCR_ = false;
+ } else if (val1 < val2) {
+ n_flag_FPSCR_ = true;
+ z_flag_FPSCR_ = false;
+ c_flag_FPSCR_ = false;
+ v_flag_FPSCR_ = false;
+ } else {
+ // Case when (val1 > val2).
+ n_flag_FPSCR_ = false;
+ z_flag_FPSCR_ = false;
+ c_flag_FPSCR_ = true;
+ v_flag_FPSCR_ = false;
+ }
+}
+
+
void Simulator::Compute_FPSCR_Flags(double val1, double val2) {
if (std::isnan(val1) || std::isnan(val2)) {
n_flag_FPSCR_ = false;
@@ -1914,6 +1941,17 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
}
+float Simulator::canonicalizeNaN(float value) {
+ // Default NaN value, see "NaN handling" in "IEEE 754 standard implementation
+ // choices" of the ARM Reference Manual.
+ const uint32_t kDefaultNaN = 0x7FC00000u;
+ if (FPSCR_default_NaN_mode_ && std::isnan(value)) {
+ value = bit_cast<float>(kDefaultNaN);
+ }
+ return value;
+}
+
+
double Simulator::canonicalizeNaN(double value) {
// Default NaN value, see "NaN handling" in "IEEE 754 standard implementation
// choices" of the ARM Reference Manual.
@@ -3009,18 +3047,30 @@ void Simulator::DecodeType7(Instruction* instr) {
// vcvt: Sd = Dm
// vcvt.f64.s32 Dd, Dd, #<fbits>
// Dd = vabs(Dm)
+// Sd = vabs(Sm)
// Dd = vneg(Dm)
+// Sd = vneg(Sm)
// Dd = vadd(Dn, Dm)
+// Sd = vadd(Sn, Sm)
// Dd = vsub(Dn, Dm)
+// Sd = vsub(Sn, Sm)
// Dd = vmul(Dn, Dm)
+// Sd = vmul(Sn, Sm)
// Dd = vdiv(Dn, Dm)
+// Sd = vdiv(Sn, Sm)
// vcmp(Dd, Dm)
-// vmrs
+// vcmp(Sd, Sm)
// Dd = vsqrt(Dm)
+// Sd = vsqrt(Sm)
+// vmrs
void Simulator::DecodeTypeVFP(Instruction* instr) {
DCHECK((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
DCHECK(instr->Bits(11, 9) == 0x5);
+ // Obtain single precision register codes.
+ int m = instr->VFPMRegValue(kSinglePrecision);
+ int d = instr->VFPDRegValue(kSinglePrecision);
+ int n = instr->VFPNRegValue(kSinglePrecision);
// Obtain double precision register codes.
int vm = instr->VFPMRegValue(kDoublePrecision);
int vd = instr->VFPDRegValue(kDoublePrecision);
@@ -3032,28 +3082,38 @@ void Simulator::DecodeTypeVFP(Instruction* instr) {
if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
// vmov register to register.
if (instr->SzValue() == 0x1) {
- int m = instr->VFPMRegValue(kDoublePrecision);
- int d = instr->VFPDRegValue(kDoublePrecision);
uint32_t data[2];
- get_d_register(m, data);
- set_d_register(d, data);
+ get_d_register(vm, data);
+ set_d_register(vd, data);
} else {
- int m = instr->VFPMRegValue(kSinglePrecision);
- int d = instr->VFPDRegValue(kSinglePrecision);
- set_s_register_from_float(d, get_float_from_s_register(m));
+ set_s_register(d, get_s_register(m));
}
} else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
// vabs
- double dm_value = get_double_from_d_register(vm);
- double dd_value = std::fabs(dm_value);
- dd_value = canonicalizeNaN(dd_value);
- set_d_register_from_double(vd, dd_value);
+ if (instr->SzValue() == 0x1) {
+ double dm_value = get_double_from_d_register(vm);
+ double dd_value = std::fabs(dm_value);
+ dd_value = canonicalizeNaN(dd_value);
+ set_d_register_from_double(vd, dd_value);
+ } else {
+ float sm_value = get_float_from_s_register(m);
+ float sd_value = std::fabs(sm_value);
+ sd_value = canonicalizeNaN(sd_value);
+ set_s_register_from_float(d, sd_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);
+ if (instr->SzValue() == 0x1) {
+ 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 {
+ float sm_value = get_float_from_s_register(m);
+ float sd_value = -sm_value;
+ sd_value = canonicalizeNaN(sd_value);
+ set_s_register_from_float(d, sd_value);
+ }
} else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
DecodeVCVTBetweenDoubleAndSingle(instr);
} else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
@@ -3073,10 +3133,17 @@ void Simulator::DecodeTypeVFP(Instruction* instr) {
DecodeVCMP(instr);
} else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
// vsqrt
- double dm_value = get_double_from_d_register(vm);
- double dd_value = fast_sqrt(dm_value);
- dd_value = canonicalizeNaN(dd_value);
- set_d_register_from_double(vd, dd_value);
+ if (instr->SzValue() == 0x1) {
+ double dm_value = get_double_from_d_register(vm);
+ double dd_value = fast_sqrt(dm_value);
+ dd_value = canonicalizeNaN(dd_value);
+ set_d_register_from_double(vd, dd_value);
+ } else {
+ float sm_value = get_float_from_s_register(m);
+ float sd_value = fast_sqrt(sm_value);
+ sd_value = canonicalizeNaN(sd_value);
+ set_s_register_from_float(d, sd_value);
+ }
} else if (instr->Opc3Value() == 0x0) {
// vmov immediate.
if (instr->SzValue() == 0x1) {
@@ -3094,72 +3161,103 @@ void Simulator::DecodeTypeVFP(Instruction* instr) {
UNREACHABLE(); // Not used by V8.
}
} else if (instr->Opc1Value() == 0x3) {
- if (instr->SzValue() != 0x1) {
- UNREACHABLE(); // Not used by V8.
- }
-
if (instr->Opc3Value() & 0x1) {
// vsub
- 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);
+ if (instr->SzValue() == 0x1) {
+ 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 {
+ float sn_value = get_float_from_s_register(n);
+ float sm_value = get_float_from_s_register(m);
+ float sd_value = sn_value - sm_value;
+ sd_value = canonicalizeNaN(sd_value);
+ set_s_register_from_float(d, sd_value);
+ }
} else {
// vadd
+ if (instr->SzValue() == 0x1) {
+ 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 {
+ float sn_value = get_float_from_s_register(n);
+ float sm_value = get_float_from_s_register(m);
+ float sd_value = sn_value + sm_value;
+ sd_value = canonicalizeNaN(sd_value);
+ set_s_register_from_float(d, sd_value);
+ }
+ }
+ } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
+ // vmul
+ if (instr->SzValue() == 0x1) {
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;
+ double dd_value = dn_value * dm_value;
dd_value = canonicalizeNaN(dd_value);
set_d_register_from_double(vd, dd_value);
+ } else {
+ float sn_value = get_float_from_s_register(n);
+ float sm_value = get_float_from_s_register(m);
+ float sd_value = sn_value * sm_value;
+ sd_value = canonicalizeNaN(sd_value);
+ set_s_register_from_float(d, sd_value);
}
- } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
- // vmul
- if (instr->SzValue() != 0x1) {
- UNREACHABLE(); // Not used by V8.
- }
-
- 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
const bool is_vmls = (instr->Opc3Value() & 0x1);
-
- if (instr->SzValue() != 0x1) {
- UNREACHABLE(); // Not used by V8.
- }
-
- const double dd_val = get_double_from_d_register(vd);
- const double dn_val = get_double_from_d_register(vn);
- const double dm_val = get_double_from_d_register(vm);
-
- // Note: we do the mul and add/sub in separate steps to avoid getting a
- // result with too high precision.
- set_d_register_from_double(vd, dn_val * dm_val);
- if (is_vmls) {
- set_d_register_from_double(
- vd,
- canonicalizeNaN(dd_val - get_double_from_d_register(vd)));
+ if (instr->SzValue() == 0x1) {
+ const double dd_val = get_double_from_d_register(vd);
+ const double dn_val = get_double_from_d_register(vn);
+ const double dm_val = get_double_from_d_register(vm);
+
+ // Note: we do the mul and add/sub in separate steps to avoid getting a
+ // result with too high precision.
+ set_d_register_from_double(vd, dn_val * dm_val);
+ if (is_vmls) {
+ set_d_register_from_double(
+ vd, canonicalizeNaN(dd_val - get_double_from_d_register(vd)));
+ } else {
+ set_d_register_from_double(
+ vd, canonicalizeNaN(dd_val + get_double_from_d_register(vd)));
+ }
} else {
- set_d_register_from_double(
- vd,
- canonicalizeNaN(dd_val + get_double_from_d_register(vd)));
+ const float sd_val = get_float_from_s_register(d);
+ const float sn_val = get_float_from_s_register(n);
+ const float sm_val = get_float_from_s_register(m);
+
+ // Note: we do the mul and add/sub in separate steps to avoid getting a
+ // result with too high precision.
+ set_s_register_from_float(d, sn_val * sm_val);
+ if (is_vmls) {
+ set_s_register_from_float(
+ d, canonicalizeNaN(sd_val - get_float_from_s_register(d)));
+ } else {
+ set_s_register_from_float(
+ d, canonicalizeNaN(sd_val + get_float_from_s_register(d)));
+ }
}
} else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
// vdiv
- if (instr->SzValue() != 0x1) {
- UNREACHABLE(); // Not used by V8.
+ if (instr->SzValue() == 0x1) {
+ 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;
+ div_zero_vfp_flag_ = (dm_value == 0);
+ dd_value = canonicalizeNaN(dd_value);
+ set_d_register_from_double(vd, dd_value);
+ } else {
+ float sn_value = get_float_from_s_register(n);
+ float sm_value = get_float_from_s_register(m);
+ float sd_value = sn_value / sm_value;
+ div_zero_vfp_flag_ = (sm_value == 0);
+ sd_value = canonicalizeNaN(sd_value);
+ set_s_register_from_float(d, sd_value);
}
-
- 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;
- 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.
}
@@ -3264,7 +3362,7 @@ void Simulator::DecodeVCMP(Instruction* instr) {
// Comparison.
VFPRegPrecision precision = kSinglePrecision;
- if (instr->SzValue() == 1) {
+ if (instr->SzValue() == 0x1) {
precision = kDoublePrecision;
}
@@ -3290,7 +3388,20 @@ void Simulator::DecodeVCMP(Instruction* instr) {
Compute_FPSCR_Flags(dd_value, dm_value);
} else {
- UNIMPLEMENTED(); // Not used by V8.
+ float sd_value = get_float_from_s_register(d);
+ float sm_value = 0.0;
+ if (instr->Opc2Value() == 0x4) {
+ sm_value = get_float_from_s_register(m);
+ }
+
+ // Raise exceptions for quiet NaNs if necessary.
+ if (instr->Bit(7) == 1) {
+ if (std::isnan(sd_value)) {
+ inv_op_vfp_flag_ = true;
+ }
+ }
+
+ Compute_FPSCR_Flags(sd_value, sm_value);
}
}

Powered by Google App Engine
This is Rietveld 408576698