| Index: src/arm/lithium-codegen-arm.cc
|
| ===================================================================
|
| --- src/arm/lithium-codegen-arm.cc (revision 7157)
|
| +++ src/arm/lithium-codegen-arm.cc (working copy)
|
| @@ -3310,19 +3310,30 @@
|
|
|
|
|
| void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
|
| - Label done;
|
| Register input_reg = ToRegister(instr->InputAt(0));
|
| - Register scratch = scratch0();
|
| - DoubleRegister dbl_scratch = d0;
|
| - SwVfpRegister flt_scratch = s0;
|
| - DoubleRegister dbl_tmp = ToDoubleRegister(instr->TempAt(0));
|
| + Register scratch1 = scratch0();
|
| + Register scratch2 = ToRegister(instr->TempAt(0));
|
| + DwVfpRegister double_scratch = double_scratch0();
|
| + SwVfpRegister single_scratch = double_scratch.low();
|
|
|
| + ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2));
|
| + ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1));
|
| +
|
| + Label done;
|
| +
|
| // Heap number map check.
|
| - __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
|
| + __ ldr(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset));
|
| __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
|
| - __ cmp(scratch, Operand(ip));
|
| + __ cmp(scratch1, Operand(ip));
|
|
|
| if (instr->truncating()) {
|
| + Register scratch3 = ToRegister(instr->TempAt(1));
|
| + DwVfpRegister double_scratch2 = ToDoubleRegister(instr->TempAt(2));
|
| + ASSERT(!scratch3.is(input_reg) &&
|
| + !scratch3.is(scratch1) &&
|
| + !scratch3.is(scratch2));
|
| + // Performs a truncating conversion of a floating point number as used by
|
| + // the JS bitwise operations.
|
| Label heap_number;
|
| __ b(eq, &heap_number);
|
| // Check for undefined. Undefined is converted to zero for truncating
|
| @@ -3334,36 +3345,38 @@
|
| __ b(&done);
|
|
|
| __ bind(&heap_number);
|
| - __ sub(ip, input_reg, Operand(kHeapObjectTag));
|
| - __ vldr(dbl_tmp, ip, HeapNumber::kValueOffset);
|
| - __ vcmp(dbl_tmp, 0.0); // Sets overflow bit in FPSCR flags if NaN.
|
| - __ vcvt_s32_f64(flt_scratch, dbl_tmp);
|
| - __ vmov(input_reg, flt_scratch); // 32-bit result of conversion.
|
| - __ vmrs(pc); // Move vector status bits to normal status bits.
|
| - // Overflow bit is set if dbl_tmp is Nan.
|
| - __ cmn(input_reg, Operand(1), vc); // 0x7fffffff + 1 -> overflow.
|
| - __ cmp(input_reg, Operand(1), vc); // 0x80000000 - 1 -> overflow.
|
| - DeoptimizeIf(vs, instr->environment()); // Saturation may have occured.
|
| + __ sub(scratch1, input_reg, Operand(kHeapObjectTag));
|
| + __ vldr(double_scratch2, scratch1, HeapNumber::kValueOffset);
|
|
|
| + __ EmitECMATruncate(input_reg,
|
| + double_scratch2,
|
| + single_scratch,
|
| + scratch1,
|
| + scratch2,
|
| + scratch3);
|
| +
|
| } else {
|
| + CpuFeatures::Scope scope(VFP3);
|
| // Deoptimize if we don't have a heap number.
|
| DeoptimizeIf(ne, instr->environment());
|
|
|
| __ sub(ip, input_reg, Operand(kHeapObjectTag));
|
| - __ vldr(dbl_tmp, ip, HeapNumber::kValueOffset);
|
| - __ vcvt_s32_f64(flt_scratch, dbl_tmp);
|
| - __ vmov(input_reg, flt_scratch); // 32-bit result of conversion.
|
| - // Non-truncating conversion means that we cannot lose bits, so we convert
|
| - // back to check; note that using non-overlapping s and d regs would be
|
| - // slightly faster.
|
| - __ vcvt_f64_s32(dbl_scratch, flt_scratch);
|
| - __ VFPCompareAndSetFlags(dbl_scratch, dbl_tmp);
|
| - DeoptimizeIf(ne, instr->environment()); // Not equal or unordered.
|
| + __ vldr(double_scratch, ip, HeapNumber::kValueOffset);
|
| + __ EmitVFPTruncate(kRoundToZero,
|
| + single_scratch,
|
| + double_scratch,
|
| + scratch1,
|
| + scratch2,
|
| + kCheckForInexactConversion);
|
| + DeoptimizeIf(ne, instr->environment());
|
| + // Load the result.
|
| + __ vmov(input_reg, single_scratch);
|
| +
|
| if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| - __ tst(input_reg, Operand(input_reg));
|
| + __ cmp(input_reg, Operand(0));
|
| __ b(ne, &done);
|
| - __ vmov(lr, ip, dbl_tmp);
|
| - __ tst(ip, Operand(1 << 31)); // Test sign bit.
|
| + __ vmov(scratch1, double_scratch.high());
|
| + __ tst(scratch1, Operand(HeapNumber::kSignMask));
|
| DeoptimizeIf(ne, instr->environment());
|
| }
|
| }
|
| @@ -3405,48 +3418,38 @@
|
|
|
|
|
| void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
|
| - LOperand* input = instr->InputAt(0);
|
| - ASSERT(input->IsDoubleRegister());
|
| - LOperand* result = instr->result();
|
| - ASSERT(result->IsRegister());
|
| -
|
| - DoubleRegister double_input = ToDoubleRegister(input);
|
| - Register result_reg = ToRegister(result);
|
| - SwVfpRegister single_scratch = double_scratch0().low();
|
| + Register result_reg = ToRegister(instr->result());
|
| Register scratch1 = scratch0();
|
| Register scratch2 = ToRegister(instr->TempAt(0));
|
| + DwVfpRegister double_input = ToDoubleRegister(instr->InputAt(0));
|
| + DwVfpRegister double_scratch = double_scratch0();
|
| + SwVfpRegister single_scratch = double_scratch0().low();
|
|
|
| - __ EmitVFPTruncate(kRoundToZero,
|
| - single_scratch,
|
| - double_input,
|
| - scratch1,
|
| - scratch2);
|
| + Label done;
|
|
|
| - // Deoptimize if we had a vfp invalid exception.
|
| - DeoptimizeIf(ne, instr->environment());
|
| -
|
| - // Retrieve the result.
|
| - __ vmov(result_reg, single_scratch);
|
| -
|
| - if (!instr->truncating()) {
|
| - // Convert result back to double and compare with input
|
| - // to check if the conversion was exact.
|
| - __ vmov(single_scratch, result_reg);
|
| - __ vcvt_f64_s32(double_scratch0(), single_scratch);
|
| - __ VFPCompareAndSetFlags(double_scratch0(), double_input);
|
| + if (instr->truncating()) {
|
| + Register scratch3 = ToRegister(instr->TempAt(1));
|
| + __ EmitECMATruncate(result_reg,
|
| + double_input,
|
| + single_scratch,
|
| + scratch1,
|
| + scratch2,
|
| + scratch3);
|
| + } else {
|
| + VFPRoundingMode rounding_mode = kRoundToMinusInf;
|
| + __ EmitVFPTruncate(rounding_mode,
|
| + single_scratch,
|
| + double_input,
|
| + scratch1,
|
| + scratch2,
|
| + kCheckForInexactConversion);
|
| + // Deoptimize if we had a vfp invalid exception,
|
| + // including inexact operation.
|
| DeoptimizeIf(ne, instr->environment());
|
| - if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| - Label done;
|
| - __ cmp(result_reg, Operand(0));
|
| - __ b(ne, &done);
|
| - // Check for -0.
|
| - __ vmov(scratch1, double_input.high());
|
| - __ tst(scratch1, Operand(HeapNumber::kSignMask));
|
| - DeoptimizeIf(ne, instr->environment());
|
| -
|
| - __ bind(&done);
|
| - }
|
| + // Retrieve the result.
|
| + __ vmov(result_reg, single_scratch);
|
| }
|
| + __ bind(&done);
|
| }
|
|
|
|
|
|
|