Index: src/arm/macro-assembler-arm.cc |
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc |
index a3379d59f54297975a57ba03e7a93a009984d7a3..7df0c0a1ff0514457fb37754902cc6072f789503 100644 |
--- a/src/arm/macro-assembler-arm.cc |
+++ b/src/arm/macro-assembler-arm.cc |
@@ -773,6 +773,23 @@ void MacroAssembler::Strd(Register src1, Register src2, |
} |
+void MacroAssembler::VFPEnsureFPSCRState(Register scratch) { |
+ // If needed, restore wanted bits of FPSCR. |
+ Label fpscr_done; |
+ vmrs(scratch); |
+ tst(scratch, Operand(kVFPDefaultNaNModeControlBit)); |
+ b(ne, &fpscr_done); |
+ orr(scratch, scratch, Operand(kVFPDefaultNaNModeControlBit)); |
+ vmsr(scratch); |
+ bind(&fpscr_done); |
+} |
+ |
+void MacroAssembler::VFPCanonicalizeNaN(const DwVfpRegister value, |
+ const Condition cond) { |
+ vsub(value, value, kDoubleRegZero, cond); |
+} |
+ |
+ |
void MacroAssembler::VFPCompareAndSetFlags(const DwVfpRegister src1, |
const DwVfpRegister src2, |
const Condition cond) { |
@@ -1983,7 +2000,7 @@ void MacroAssembler::StoreNumberToDoubleElements(Register value_reg, |
Register scratch4, |
Label* fail, |
int elements_offset) { |
- Label smi_value, maybe_nan, have_double_value, is_nan, done; |
+ Label smi_value, store; |
Register mantissa_reg = scratch2; |
Register exponent_reg = scratch3; |
@@ -1997,68 +2014,28 @@ void MacroAssembler::StoreNumberToDoubleElements(Register value_reg, |
fail, |
DONT_DO_SMI_CHECK); |
- // Check for nan: all NaN values have a value greater (signed) than 0x7ff00000 |
- // in the exponent. |
- mov(scratch1, Operand(kNaNOrInfinityLowerBoundUpper32)); |
- ldr(exponent_reg, FieldMemOperand(value_reg, HeapNumber::kExponentOffset)); |
- cmp(exponent_reg, scratch1); |
- b(ge, &maybe_nan); |
- |
- ldr(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset)); |
- |
- bind(&have_double_value); |
- add(scratch1, elements_reg, |
- Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize)); |
- str(mantissa_reg, FieldMemOperand( |
- scratch1, FixedDoubleArray::kHeaderSize - elements_offset)); |
- uint32_t offset = FixedDoubleArray::kHeaderSize - elements_offset + |
- sizeof(kHoleNanLower32); |
- str(exponent_reg, FieldMemOperand(scratch1, offset)); |
- jmp(&done); |
- |
- bind(&maybe_nan); |
- // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise |
- // it's an Infinity, and the non-NaN code path applies. |
- b(gt, &is_nan); |
- ldr(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset)); |
- cmp(mantissa_reg, Operand::Zero()); |
- b(eq, &have_double_value); |
- bind(&is_nan); |
- // Load canonical NaN for storing into the double array. |
- uint64_t nan_int64 = BitCast<uint64_t>( |
- FixedDoubleArray::canonical_not_the_hole_nan_as_double()); |
- mov(mantissa_reg, Operand(static_cast<uint32_t>(nan_int64))); |
- mov(exponent_reg, Operand(static_cast<uint32_t>(nan_int64 >> 32))); |
- jmp(&have_double_value); |
+ vldr(d0, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); |
+ // Force a canonical NaN. |
+ if (emit_debug_code()) { |
+ vmrs(ip); |
+ tst(ip, Operand(kVFPDefaultNaNModeControlBit)); |
+ Assert(ne, "Default NaN mode not set"); |
+ } |
+ VFPCanonicalizeNaN(d0); |
+ b(&store); |
bind(&smi_value); |
+ Register untagged_value = scratch1; |
+ SmiUntag(untagged_value, value_reg); |
+ FloatingPointHelper::ConvertIntToDouble( |
+ this, untagged_value, FloatingPointHelper::kVFPRegisters, d0, |
+ mantissa_reg, exponent_reg, scratch4, s2); |
+ |
+ bind(&store); |
add(scratch1, elements_reg, |
- Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag - |
- elements_offset)); |
- add(scratch1, scratch1, |
Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize)); |
- // scratch1 is now effective address of the double element |
- |
- FloatingPointHelper::Destination destination; |
- destination = FloatingPointHelper::kVFPRegisters; |
- |
- Register untagged_value = elements_reg; |
- SmiUntag(untagged_value, value_reg); |
- FloatingPointHelper::ConvertIntToDouble(this, |
- untagged_value, |
- destination, |
- d0, |
- mantissa_reg, |
- exponent_reg, |
- scratch4, |
- s2); |
- if (destination == FloatingPointHelper::kVFPRegisters) { |
- vstr(d0, scratch1, 0); |
- } else { |
- str(mantissa_reg, MemOperand(scratch1, 0)); |
- str(exponent_reg, MemOperand(scratch1, Register::kSizeInBytes)); |
- } |
- bind(&done); |
+ vstr(d0, FieldMemOperand(scratch1, |
+ FixedDoubleArray::kHeaderSize - elements_offset)); |
} |