| Index: src/arm/codegen-arm.cc
|
| ===================================================================
|
| --- src/arm/codegen-arm.cc (revision 4973)
|
| +++ src/arm/codegen-arm.cc (working copy)
|
| @@ -4279,22 +4279,147 @@
|
| }
|
|
|
|
|
| -// Generates the Math.pow method - currently just calls runtime.
|
| +// Generates the Math.pow method.
|
| void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
|
| ASSERT(args->length() == 2);
|
| Load(args->at(0));
|
| Load(args->at(1));
|
| - frame_->CallRuntime(Runtime::kMath_pow, 2);
|
| - frame_->EmitPush(r0);
|
| +
|
| + if (!CpuFeatures::IsSupported(VFP3)) {
|
| + frame_->CallRuntime(Runtime::kMath_pow, 2);
|
| + frame_->EmitPush(r0);
|
| + } else {
|
| + CpuFeatures::Scope scope(VFP3);
|
| + JumpTarget runtime, done;
|
| + Label not_minus_half, allocate_return;
|
| +
|
| + Register scratch1 = VirtualFrame::scratch0();
|
| + Register scratch2 = VirtualFrame::scratch1();
|
| +
|
| + // Get base and exponent to registers.
|
| + Register exponent = frame_->PopToRegister();
|
| + Register base = frame_->PopToRegister(exponent);
|
| +
|
| + // Set the frame for the runtime jump target. The code below jumps to the
|
| + // jump target label so the frame needs to be established before that.
|
| + ASSERT(runtime.entry_frame() == NULL);
|
| + runtime.set_entry_frame(frame_);
|
| +
|
| + __ BranchOnSmi(exponent, runtime.entry_label());
|
| +
|
| + // Special handling of raising to the power of -0.5 and 0.5. First check
|
| + // that the value is a heap number and that the lower bits (which for both
|
| + // values are zero).
|
| + Register heap_number_map = r6;
|
| + __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
|
| + __ ldr(scratch1, FieldMemOperand(exponent, HeapObject::kMapOffset));
|
| + __ ldr(scratch2, FieldMemOperand(exponent, HeapNumber::kMantissaOffset));
|
| + __ cmp(scratch1, heap_number_map);
|
| + runtime.Branch(ne);
|
| + __ tst(scratch2, scratch2);
|
| + runtime.Branch(ne);
|
| +
|
| + // Load the e
|
| + __ ldr(scratch1, FieldMemOperand(exponent, HeapNumber::kExponentOffset));
|
| +
|
| + // Compare exponent with -0.5.
|
| + __ cmp(scratch1, Operand(0xbfe00000));
|
| + __ b(ne, ¬_minus_half);
|
| +
|
| + // Get the double value from the base into vfp register d0.
|
| + __ ObjectToDoubleVFPRegister(base, d0,
|
| + scratch1, scratch2, heap_number_map, s0,
|
| + runtime.entry_label(),
|
| + AVOID_NANS_AND_INFINITIES);
|
| +
|
| + // Load 1.0 into d2.
|
| + __ mov(scratch2, Operand(0x3ff00000));
|
| + __ mov(scratch1, Operand(0));
|
| + __ vmov(d2, scratch1, scratch2);
|
| +
|
| + // Calculate the reciprocal of the square root. 1/sqrt(x) = sqrt(1/x).
|
| + __ vdiv(d0, d2, d0);
|
| + __ vsqrt(d0, d0);
|
| +
|
| + __ b(&allocate_return);
|
| +
|
| + __ bind(¬_minus_half);
|
| + // Compare exponent with 0.5.
|
| + __ cmp(scratch1, Operand(0x3fe00000));
|
| + runtime.Branch(ne);
|
| +
|
| + // Get the double value from the base into vfp register d0.
|
| + __ ObjectToDoubleVFPRegister(base, d0,
|
| + scratch1, scratch2, heap_number_map, s0,
|
| + runtime.entry_label(),
|
| + AVOID_NANS_AND_INFINITIES);
|
| + __ vsqrt(d0, d0);
|
| +
|
| + __ bind(&allocate_return);
|
| + __ AllocateHeapNumberWithValue(
|
| + base, d0, scratch1, scratch2, heap_number_map, runtime.entry_label());
|
| + done.Jump();
|
| +
|
| + runtime.Bind();
|
| +
|
| + // Push back the arguments again for the runtime call.
|
| + frame_->EmitPush(base);
|
| + frame_->EmitPush(exponent);
|
| + frame_->CallRuntime(Runtime::kMath_pow, 2);
|
| + __ Move(base, r0);
|
| +
|
| + done.Bind();
|
| + frame_->EmitPush(base);
|
| + }
|
| }
|
|
|
|
|
| -// Generates the Math.sqrt method - currently just calls runtime.
|
| +// Generates the Math.sqrt method.
|
| void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) {
|
| ASSERT(args->length() == 1);
|
| Load(args->at(0));
|
| - frame_->CallRuntime(Runtime::kMath_sqrt, 1);
|
| - frame_->EmitPush(r0);
|
| +
|
| + if (!CpuFeatures::IsSupported(VFP3)) {
|
| + frame_->CallRuntime(Runtime::kMath_sqrt, 1);
|
| + frame_->EmitPush(r0);
|
| + } else {
|
| + CpuFeatures::Scope scope(VFP3);
|
| + JumpTarget runtime, done;
|
| +
|
| + Register scratch1 = VirtualFrame::scratch0();
|
| + Register scratch2 = VirtualFrame::scratch1();
|
| +
|
| + // Get the value from the frame.
|
| + Register tos = frame_->PopToRegister();
|
| +
|
| + // Set the frame for the runtime jump target. The code below jumps to the
|
| + // jump target label so the frame needs to be established before that.
|
| + ASSERT(runtime.entry_frame() == NULL);
|
| + runtime.set_entry_frame(frame_);
|
| +
|
| + Register heap_number_map = r6;
|
| + __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
|
| +
|
| + // Get the double value from the heap number into vfp register d0.
|
| + __ ObjectToDoubleVFPRegister(tos, d0,
|
| + scratch1, scratch2, heap_number_map, s0,
|
| + runtime.entry_label());
|
| +
|
| + // Calculate the square root of d0 and place result in a heap number object.
|
| + __ vsqrt(d0, d0);
|
| + __ AllocateHeapNumberWithValue(
|
| + tos, d0, scratch1, scratch2, heap_number_map, runtime.entry_label());
|
| + done.Jump();
|
| +
|
| + runtime.Bind();
|
| + // Push back the argument again for the runtime call.
|
| + frame_->EmitPush(tos);
|
| + frame_->CallRuntime(Runtime::kMath_sqrt, 1);
|
| + __ Move(tos, r0);
|
| +
|
| + done.Bind();
|
| + frame_->EmitPush(tos);
|
| + }
|
| }
|
|
|
|
|
|
|