| Index: src/arm/codegen-arm.cc
|
| ===================================================================
|
| --- src/arm/codegen-arm.cc (revision 3208)
|
| +++ src/arm/codegen-arm.cc (working copy)
|
| @@ -4602,6 +4602,21 @@
|
| }
|
|
|
|
|
| +static void IntegerToDoubleConversionWithVFP3(MacroAssembler* masm,
|
| + Register inReg,
|
| + Register outHighReg,
|
| + Register outLowReg) {
|
| + // ARMv7 VFP3 instructions to implement integer to double conversion.
|
| + // This VFP3 implementation is known to work
|
| + // on ARMv7-VFP3 Snapdragon processor.
|
| +
|
| + __ mov(r7, Operand(inReg, ASR, kSmiTagSize));
|
| + __ fmsr(s15, r7);
|
| + __ fsitod(d7, s15);
|
| + __ fmrrd(outLowReg, outHighReg, d7);
|
| +}
|
| +
|
| +
|
| // See comment at call site.
|
| static void EmitSmiNonsmiComparison(MacroAssembler* masm,
|
| Label* rhs_not_nan,
|
| @@ -4625,9 +4640,16 @@
|
|
|
| // Rhs is a smi, lhs is a number.
|
| __ push(lr);
|
| - __ mov(r7, Operand(r1));
|
| - ConvertToDoubleStub stub1(r3, r2, r7, r6);
|
| - __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET);
|
| +
|
| + if (CpuFeatures::IsSupported(CpuFeatures::VFP3)) {
|
| + IntegerToDoubleConversionWithVFP3(masm, r1, r3, r2);
|
| + } else {
|
| + __ mov(r7, Operand(r1));
|
| + ConvertToDoubleStub stub1(r3, r2, r7, r6);
|
| + __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET);
|
| + }
|
| +
|
| +
|
| // r3 and r2 are rhs as double.
|
| __ ldr(r1, FieldMemOperand(r0, HeapNumber::kValueOffset + kPointerSize));
|
| __ ldr(r0, FieldMemOperand(r0, HeapNumber::kValueOffset));
|
| @@ -4655,9 +4677,15 @@
|
| __ push(lr);
|
| __ ldr(r2, FieldMemOperand(r1, HeapNumber::kValueOffset));
|
| __ ldr(r3, FieldMemOperand(r1, HeapNumber::kValueOffset + kPointerSize));
|
| - __ mov(r7, Operand(r0));
|
| - ConvertToDoubleStub stub2(r1, r0, r7, r6);
|
| - __ Call(stub2.GetCode(), RelocInfo::CODE_TARGET);
|
| +
|
| + if (CpuFeatures::IsSupported(CpuFeatures::VFP3)) {
|
| + IntegerToDoubleConversionWithVFP3(masm, r0, r1, r0);
|
| + } else {
|
| + __ mov(r7, Operand(r0));
|
| + ConvertToDoubleStub stub2(r1, r0, r7, r6);
|
| + __ Call(stub2.GetCode(), RelocInfo::CODE_TARGET);
|
| + }
|
| +
|
| __ pop(lr);
|
| // Fall through to both_loaded_as_doubles.
|
| }
|
| @@ -4860,10 +4888,26 @@
|
| // fall through if neither is a NaN. Also binds rhs_not_nan.
|
| EmitNanCheck(masm, &rhs_not_nan, cc_);
|
|
|
| - // Compares two doubles in r0, r1, r2, r3 that are not NaNs. Returns the
|
| - // answer. Never falls through.
|
| - EmitTwoNonNanDoubleComparison(masm, cc_);
|
| + if (CpuFeatures::IsSupported(CpuFeatures::VFP3)) {
|
| + // ARMv7 VFP3 instructions to implement double precision comparison.
|
| + // This VFP3 implementation is known to work on
|
| + // ARMv7-VFP3 Snapdragon processor.
|
|
|
| + __ fmdrr(d6, r0, r1);
|
| + __ fmdrr(d7, r2, r3);
|
| +
|
| + __ fcmp(d6, d7);
|
| + __ vmrs(pc);
|
| + __ mov(r0, Operand(0), LeaveCC, eq);
|
| + __ mov(r0, Operand(1), LeaveCC, lt);
|
| + __ mvn(r0, Operand(0), LeaveCC, gt);
|
| + __ mov(pc, Operand(lr));
|
| + } else {
|
| + // Compares two doubles in r0, r1, r2, r3 that are not NaNs. Returns the
|
| + // answer. Never falls through.
|
| + EmitTwoNonNanDoubleComparison(masm, cc_);
|
| + }
|
| +
|
| __ bind(¬_smis);
|
| // At this point we know we are dealing with two different objects,
|
| // and neither of them is a Smi. The objects are in r0 and r1.
|
| @@ -4962,16 +5006,23 @@
|
| // Since both are Smis there is no heap number to overwrite, so allocate.
|
| // The new heap number is in r5. r6 and r7 are scratch.
|
| AllocateHeapNumber(masm, &slow, r5, r6, r7);
|
| - // Write Smi from r0 to r3 and r2 in double format. r6 is scratch.
|
| - __ mov(r7, Operand(r0));
|
| - ConvertToDoubleStub stub1(r3, r2, r7, r6);
|
| - __ push(lr);
|
| - __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET);
|
| - // Write Smi from r1 to r1 and r0 in double format. r6 is scratch.
|
| - __ mov(r7, Operand(r1));
|
| - ConvertToDoubleStub stub2(r1, r0, r7, r6);
|
| - __ Call(stub2.GetCode(), RelocInfo::CODE_TARGET);
|
| - __ pop(lr);
|
| +
|
| + if (CpuFeatures::IsSupported(CpuFeatures::VFP3)) {
|
| + IntegerToDoubleConversionWithVFP3(masm, r0, r3, r2);
|
| + IntegerToDoubleConversionWithVFP3(masm, r1, r1, r0);
|
| + } else {
|
| + // Write Smi from r0 to r3 and r2 in double format. r6 is scratch.
|
| + __ mov(r7, Operand(r0));
|
| + ConvertToDoubleStub stub1(r3, r2, r7, r6);
|
| + __ push(lr);
|
| + __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET);
|
| + // Write Smi from r1 to r1 and r0 in double format. r6 is scratch.
|
| + __ mov(r7, Operand(r1));
|
| + ConvertToDoubleStub stub2(r1, r0, r7, r6);
|
| + __ Call(stub2.GetCode(), RelocInfo::CODE_TARGET);
|
| + __ pop(lr);
|
| + }
|
| +
|
| __ jmp(&do_the_call); // Tail call. No return.
|
|
|
| // We jump to here if something goes wrong (one param is not a number of any
|
| @@ -5007,12 +5058,19 @@
|
| // We can't overwrite a Smi so get address of new heap number into r5.
|
| AllocateHeapNumber(masm, &slow, r5, r6, r7);
|
| }
|
| - // Write Smi from r0 to r3 and r2 in double format.
|
| - __ mov(r7, Operand(r0));
|
| - ConvertToDoubleStub stub3(r3, r2, r7, r6);
|
| - __ push(lr);
|
| - __ Call(stub3.GetCode(), RelocInfo::CODE_TARGET);
|
| - __ pop(lr);
|
| +
|
| +
|
| + if (CpuFeatures::IsSupported(CpuFeatures::VFP3)) {
|
| + IntegerToDoubleConversionWithVFP3(masm, r0, r3, r2);
|
| + } else {
|
| + // Write Smi from r0 to r3 and r2 in double format.
|
| + __ mov(r7, Operand(r0));
|
| + ConvertToDoubleStub stub3(r3, r2, r7, r6);
|
| + __ push(lr);
|
| + __ Call(stub3.GetCode(), RelocInfo::CODE_TARGET);
|
| + __ pop(lr);
|
| + }
|
| +
|
| __ bind(&finished_loading_r0);
|
|
|
| // Move r1 to a double in r0-r1.
|
| @@ -5032,12 +5090,18 @@
|
| // We can't overwrite a Smi so get address of new heap number into r5.
|
| AllocateHeapNumber(masm, &slow, r5, r6, r7);
|
| }
|
| - // Write Smi from r1 to r1 and r0 in double format.
|
| - __ mov(r7, Operand(r1));
|
| - ConvertToDoubleStub stub4(r1, r0, r7, r6);
|
| - __ push(lr);
|
| - __ Call(stub4.GetCode(), RelocInfo::CODE_TARGET);
|
| - __ pop(lr);
|
| +
|
| + if (CpuFeatures::IsSupported(CpuFeatures::VFP3)) {
|
| + IntegerToDoubleConversionWithVFP3(masm, r1, r1, r0);
|
| + } else {
|
| + // Write Smi from r1 to r1 and r0 in double format.
|
| + __ mov(r7, Operand(r1));
|
| + ConvertToDoubleStub stub4(r1, r0, r7, r6);
|
| + __ push(lr);
|
| + __ Call(stub4.GetCode(), RelocInfo::CODE_TARGET);
|
| + __ pop(lr);
|
| + }
|
| +
|
| __ bind(&finished_loading_r1);
|
|
|
| __ bind(&do_the_call);
|
| @@ -5046,6 +5110,33 @@
|
| // r2: Right value (least significant part of mantissa).
|
| // r3: Right value (sign, exponent, top of mantissa).
|
| // r5: Address of heap number for result.
|
| +
|
| + if (CpuFeatures::IsSupported(CpuFeatures::VFP3) &&
|
| + ((Token::MUL == operation) ||
|
| + (Token::DIV == operation) ||
|
| + (Token::ADD == operation) ||
|
| + (Token::SUB == operation))) {
|
| + // ARMv7 VFP3 instructions to implement
|
| + // double precision, add, subtract, multiply, divide.
|
| + // This VFP3 implementation is known to work on
|
| + // ARMv7-VFP3 Snapdragon processor
|
| +
|
| + __ fmdrr(d6, r0, r1);
|
| + __ fmdrr(d7, r2, r3);
|
| +
|
| + if (Token::MUL == operation) __ fmuld(d5, d6, d7);
|
| + else if (Token::DIV == operation) __ fdivd(d5, d6, d7);
|
| + else if (Token::ADD == operation) __ faddd(d5, d6, d7);
|
| + else if (Token::SUB == operation) __ fsubd(d5, d6, d7);
|
| +
|
| + __ fmrrd(r0, r1, d5);
|
| +
|
| + __ str(r0, FieldMemOperand(r5, HeapNumber::kValueOffset));
|
| + __ str(r1, FieldMemOperand(r5, HeapNumber::kValueOffset + 4));
|
| + __ mov(r0, Operand(r5));
|
| + __ mov(pc, lr);
|
| + return;
|
| + }
|
| __ push(lr); // For later.
|
| __ push(r5); // Address of heap number that is answer.
|
| __ AlignStack(0);
|
| @@ -5114,38 +5205,50 @@
|
| __ sub(scratch2, scratch2, Operand(zero_exponent), SetCC);
|
| // Dest already has a Smi zero.
|
| __ b(lt, &done);
|
| - // We have a shifted exponent between 0 and 30 in scratch2.
|
| - __ mov(dest, Operand(scratch2, LSR, HeapNumber::kExponentShift));
|
| - // We now have the exponent in dest. Subtract from 30 to get
|
| - // how much to shift down.
|
| - __ rsb(dest, dest, Operand(30));
|
| -
|
| + if (!CpuFeatures::IsSupported(CpuFeatures::VFP3)) {
|
| + // We have a shifted exponent between 0 and 30 in scratch2.
|
| + __ mov(dest, Operand(scratch2, LSR, HeapNumber::kExponentShift));
|
| + // We now have the exponent in dest. Subtract from 30 to get
|
| + // how much to shift down.
|
| + __ rsb(dest, dest, Operand(30));
|
| + }
|
| __ bind(&right_exponent);
|
| - // Get the top bits of the mantissa.
|
| - __ and_(scratch2, scratch, Operand(HeapNumber::kMantissaMask));
|
| - // Put back the implicit 1.
|
| - __ orr(scratch2, scratch2, Operand(1 << HeapNumber::kExponentShift));
|
| - // Shift up the mantissa bits to take up the space the exponent used to take.
|
| - // We just orred in the implicit bit so that took care of one and we want to
|
| - // leave the sign bit 0 so we subtract 2 bits from the shift distance.
|
| - const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2;
|
| - __ mov(scratch2, Operand(scratch2, LSL, shift_distance));
|
| - // Put sign in zero flag.
|
| - __ tst(scratch, Operand(HeapNumber::kSignMask));
|
| - // Get the second half of the double. For some exponents we don't actually
|
| - // need this because the bits get shifted out again, but it's probably slower
|
| - // to test than just to do it.
|
| - __ ldr(scratch, FieldMemOperand(source, HeapNumber::kMantissaOffset));
|
| - // Shift down 22 bits to get the last 10 bits.
|
| - __ orr(scratch, scratch2, Operand(scratch, LSR, 32 - shift_distance));
|
| - // Move down according to the exponent.
|
| - __ mov(dest, Operand(scratch, LSR, dest));
|
| - // Fix sign if sign bit was set.
|
| - __ rsb(dest, dest, Operand(0), LeaveCC, ne);
|
| + if (CpuFeatures::IsSupported(CpuFeatures::VFP3)) {
|
| + // ARMv7 VFP3 instructions implementing double precision to integer
|
| + // conversion using round to zero.
|
| + // This VFP3 implementation is known to work on
|
| + // ARMv7-VFP3 Snapdragon processor.
|
| + __ ldr(scratch2, FieldMemOperand(source, HeapNumber::kMantissaOffset));
|
| + __ fmdrr(d7, scratch2, scratch);
|
| + __ ftosid(s15, d7);
|
| + __ fmrs(dest, s15);
|
| + } else {
|
| + // Get the top bits of the mantissa.
|
| + __ and_(scratch2, scratch, Operand(HeapNumber::kMantissaMask));
|
| + // Put back the implicit 1.
|
| + __ orr(scratch2, scratch2, Operand(1 << HeapNumber::kExponentShift));
|
| + // Shift up the mantissa bits to take up the space the exponent used to
|
| + // take. We just orred in the implicit bit so that took care of one and
|
| + // we want to leave the sign bit 0 so we subtract 2 bits from the shift
|
| + // distance.
|
| + const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2;
|
| + __ mov(scratch2, Operand(scratch2, LSL, shift_distance));
|
| + // Put sign in zero flag.
|
| + __ tst(scratch, Operand(HeapNumber::kSignMask));
|
| + // Get the second half of the double. For some exponents we don't
|
| + // actually need this because the bits get shifted out again, but
|
| + // it's probably slower to test than just to do it.
|
| + __ ldr(scratch, FieldMemOperand(source, HeapNumber::kMantissaOffset));
|
| + // Shift down 22 bits to get the last 10 bits.
|
| + __ orr(scratch, scratch2, Operand(scratch, LSR, 32 - shift_distance));
|
| + // Move down according to the exponent.
|
| + __ mov(dest, Operand(scratch, LSR, dest));
|
| + // Fix sign if sign bit was set.
|
| + __ rsb(dest, dest, Operand(0), LeaveCC, ne);
|
| + }
|
| __ bind(&done);
|
| }
|
|
|
| -
|
| // For bitwise ops where the inputs are not both Smis we here try to determine
|
| // whether both inputs are either Smis or at least heap numbers that can be
|
| // represented by a 32 bit signed value. We truncate towards zero as required
|
| @@ -5162,7 +5265,7 @@
|
| __ b(eq, &r1_is_smi); // It's a Smi so don't check it's a heap number.
|
| __ CompareObjectType(r1, r4, r4, HEAP_NUMBER_TYPE);
|
| __ b(ne, &slow);
|
| - GetInt32(masm, r1, r3, r4, r5, &slow);
|
| + GetInt32(masm, r1, r3, r5, r4, &slow);
|
| __ jmp(&done_checking_r1);
|
| __ bind(&r1_is_smi);
|
| __ mov(r3, Operand(r1, ASR, 1));
|
| @@ -5172,7 +5275,7 @@
|
| __ b(eq, &r0_is_smi); // It's a Smi so don't check it's a heap number.
|
| __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE);
|
| __ b(ne, &slow);
|
| - GetInt32(masm, r0, r2, r4, r5, &slow);
|
| + GetInt32(masm, r0, r2, r5, r4, &slow);
|
| __ jmp(&done_checking_r0);
|
| __ bind(&r0_is_smi);
|
| __ mov(r2, Operand(r0, ASR, 1));
|
|
|