Revision: 6236
Author: [email protected]
Date: Mon Jan 10 00:04:30 2011
Log: Landing for Martyn Capewell.
ARM: Fix comparison of NaN values.
Enables the cumulative exception flag when comparing values, and uses it to
detect NaN results.
BUG=1023
TEST=none
Code review URL: http://codereview.chromium.org/6142004
http://code.google.com/p/v8/source/detail?r=6236
Modified:
/branches/bleeding_edge/src/arm/assembler-arm.cc
/branches/bleeding_edge/src/arm/assembler-arm.h
/branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
/branches/bleeding_edge/src/arm/macro-assembler-arm.cc
/branches/bleeding_edge/src/arm/macro-assembler-arm.h
/branches/bleeding_edge/src/arm/simulator-arm.cc
=======================================
--- /branches/bleeding_edge/src/arm/assembler-arm.cc Tue Dec 7 03:31:57
2010
+++ /branches/bleeding_edge/src/arm/assembler-arm.cc Mon Jan 10 00:04:30
2011
@@ -2340,12 +2340,14 @@
const SBit s,
const Condition cond) {
// vcmp(Dd, Dm) double precision floating point comparison.
+ // We set bit E, as we want any NaN to set the cumulative exception flag
+ // in the FPSCR.
// Instruction details available in ARM DDI 0406A, A8-570.
// cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0100 (19-16) |
- // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=? | 1(6) | M(5)=? | 0(4) |
Vm(3-0)
+ // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=1 | 1(6) | M(5)=? | 0(4) |
Vm(3-0)
ASSERT(CpuFeatures::IsEnabled(VFP3));
emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 |
- src1.code()*B12 | 0x5*B9 | B8 | B6 | src2.code());
+ src1.code()*B12 | 0x5*B9 | B8 | B7 | B6 | src2.code());
}
@@ -2355,12 +2357,14 @@
const Condition cond) {
// vcmp(Dd, Dm) double precision floating point comparison.
// Instruction details available in ARM DDI 0406A, A8-570.
+ // We set bit E, as we want any NaN to set the cumulative exception flag
+ // in the FPSCR.
// cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0101 (19-16) |
- // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=? | 1(6) | M(5)=? | 0(4) |
0000(3-0)
+ // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=1 | 1(6) | M(5)=? | 0(4) |
0000(3-0)
ASSERT(CpuFeatures::IsEnabled(VFP3));
ASSERT(src2 == 0.0);
emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 | B16 |
- src1.code()*B12 | 0x5*B9 | B8 | B6);
+ src1.code()*B12 | 0x5*B9 | B8 | B7 | B6);
}
=======================================
--- /branches/bleeding_edge/src/arm/assembler-arm.h Tue Jan 4 06:32:54 2011
+++ /branches/bleeding_edge/src/arm/assembler-arm.h Mon Jan 10 00:04:30 2011
@@ -302,6 +302,8 @@
static const uint32_t kVFPRoundingModeMask = 3 << 22;
static const uint32_t kVFPFlushToZeroMask = 1 << 24;
static const uint32_t kVFPRoundToMinusInfinityBits = 2 << 22;
+static const uint32_t kVFPZConditionFlagBit = 1 << 30;
+static const uint32_t kVFPInvalidExceptionBit = 1;
// Coprocessor register
struct CRegister {
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Sun Jan 9
23:59:13 2011
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Mon Jan 10
00:04:30 2011
@@ -1076,8 +1076,16 @@
EmitBranch(true_block, false_block, nz);
} else if (r.IsDouble()) {
DoubleRegister reg = ToDoubleRegister(instr->input());
+ Register scratch = scratch0();
+
+ // Test for the double value. Zero and NaN are false.
+ // Clear the Invalid cumulative exception flags.
+ __ ClearFPSCRBits(kVFPInvalidExceptionBit, scratch);
__ vcmp(reg, 0.0);
- __ vmrs(pc); // Move vector status bits to normal status bits.
+ // Retrieve the exception and status flags and
+ // check for zero or an invalid exception.
+ __ vmrs(scratch);
+ __ tst(scratch, Operand(kVFPZConditionFlagBit |
kVFPInvalidExceptionBit));
EmitBranch(true_block, false_block, ne);
} else {
ASSERT(r.IsTagged());
@@ -1104,7 +1112,7 @@
__ tst(reg, Operand(kSmiTagMask));
__ b(eq, true_label);
- // Test for double values. Zero is false.
+ // Test for double values. Zero and NaN are false.
Label call_stub;
DoubleRegister dbl_scratch = d0;
Register scratch = scratch0();
@@ -1114,9 +1122,14 @@
__ b(ne, &call_stub);
__ sub(ip, reg, Operand(kHeapObjectTag));
__ vldr(dbl_scratch, ip, HeapNumber::kValueOffset);
+ // Clear the Invalid cumulative exception flags.
+ __ ClearFPSCRBits(kVFPInvalidExceptionBit, scratch);
__ vcmp(dbl_scratch, 0.0);
- __ vmrs(pc); // Move vector status bits to normal status bits.
- __ b(eq, false_label);
+ // Retrieve the exception and status flags and
+ // check for zero or an invalid exception.
+ __ vmrs(scratch);
+ __ tst(scratch, Operand(kVFPZConditionFlagBit |
kVFPInvalidExceptionBit));
+ __ b(ne, false_label);
__ b(true_label);
// The conversion stub doesn't cause garbage collections so it's
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Fri Jan 7
02:37:26 2011
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Mon Jan 10
00:04:30 2011
@@ -517,6 +517,13 @@
str(src2, dst2, cond);
}
}
+
+
+void MacroAssembler::ClearFPSCRBits(uint32_t bits_to_clear, Register
scratch) {
+ vmrs(scratch);
+ bic(scratch, scratch, Operand(bits_to_clear));
+ vmsr(scratch);
+}
void MacroAssembler::EnterFrame(StackFrame::Type type) {
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h Thu Jan 6
00:56:29 2011
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h Mon Jan 10
00:04:30 2011
@@ -243,6 +243,9 @@
const MemOperand& dst,
Condition cond = al);
+ // Clear FPSCR bits.
+ void ClearFPSCRBits(uint32_t bits_to_clear, Register scratch);
+
//
---------------------------------------------------------------------------
// Activation frames
=======================================
--- /branches/bleeding_edge/src/arm/simulator-arm.cc Tue Dec 7 03:31:57
2010
+++ /branches/bleeding_edge/src/arm/simulator-arm.cc Mon Jan 10 00:04:30
2011
@@ -2599,11 +2599,6 @@
if (instr->SzField() == 1) {
precision = kDoublePrecision;
}
-
- if (instr->Bit(7) != 0) {
- // Raising exceptions for quiet NaNs are not supported.
- UNIMPLEMENTED(); // Not used by V8.
- }
int d = instr->VFPDRegCode(precision);
int m = 0;
@@ -2617,6 +2612,13 @@
if (instr->Opc2Field() == 0x4) {
dm_value = get_double_from_d_register(m);
}
+
+ // Raise exceptions for quiet NaNs if necessary.
+ if (instr->Bit(7) == 1) {
+ if (isnan(dd_value)) {
+ inv_op_vfp_flag_ = true;
+ }
+ }
Compute_FPSCR_Flags(dd_value, dm_value);
} else {
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev