Index: src/arm/codegen-arm.cc |
=================================================================== |
--- src/arm/codegen-arm.cc (revision 4989) |
+++ src/arm/codegen-arm.cc (working copy) |
@@ -4291,7 +4291,7 @@ |
} else { |
CpuFeatures::Scope scope(VFP3); |
JumpTarget runtime, done; |
- Label not_minus_half, allocate_return; |
+ Label exponent_nonsmi, base_nonsmi, powi, not_minus_half, allocate_return; |
Register scratch1 = VirtualFrame::scratch0(); |
Register scratch2 = VirtualFrame::scratch1(); |
@@ -4299,18 +4299,64 @@ |
// Get base and exponent to registers. |
Register exponent = frame_->PopToRegister(); |
Register base = frame_->PopToRegister(exponent); |
+ Register heap_number_map = no_reg; |
// 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()); |
+ __ BranchOnNotSmi(exponent, &exponent_nonsmi); |
+ __ BranchOnNotSmi(base, &base_nonsmi); |
+ heap_number_map = r6; |
+ __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
+ |
+ // Exponent is a smi and base is a smi. Get the smi value into vfp register |
+ // d1. |
+ __ SmiToDoubleVFPRegister(base, d1, scratch1, s0); |
+ __ b(&powi); |
+ |
+ __ bind(&base_nonsmi); |
+ // Exponent is smi and base is non smi. Get the double value from the base |
+ // into vfp register d1. |
+ __ ObjectToDoubleVFPRegister(base, d1, |
+ scratch1, scratch2, heap_number_map, s0, |
+ runtime.entry_label()); |
+ |
+ __ bind(&powi); |
+ |
+ // Load 1.0 into d0. |
+ __ mov(scratch2, Operand(0x3ff00000)); |
+ __ mov(scratch1, Operand(0)); |
+ __ vmov(d0, scratch1, scratch2); |
+ |
+ // Get the absolute untagged value of the exponent and use that for the |
+ // calculation. |
+ __ mov(scratch1, Operand(exponent, ASR, kSmiTagSize), SetCC); |
+ __ rsb(scratch1, scratch1, Operand(0), LeaveCC, mi); // Negate if negative. |
+ __ vmov(d2, d0, mi); // 1.0 needed in d2 later if exponent is negative. |
+ |
+ // Run through all the bits in the exponent. The result is calculated in d0 |
+ // and d1 holds base^(bit^2). |
+ Label more_bits; |
+ __ bind(&more_bits); |
+ __ mov(scratch1, Operand(scratch1, LSR, 1), SetCC); |
+ __ vmul(d0, d0, d1, cs); // Multiply with base^(bit^2) if bit is set. |
+ __ vmul(d1, d1, d1, ne); // Don't bother calculating next d1 if done. |
+ __ b(ne, &more_bits); |
+ |
+ // If exponent is negative result is 1/result (d2 already holds 1.0 in that |
+ // case). |
+ __ cmp(exponent, Operand(0)); |
+ __ vdiv(d0, d2, d0, mi); |
+ __ b(&allocate_return); |
+ |
+ __ bind(&exponent_nonsmi); |
// 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; |
+ heap_number_map = r6; |
__ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
__ ldr(scratch1, FieldMemOperand(exponent, HeapObject::kMapOffset)); |
__ ldr(scratch2, FieldMemOperand(exponent, HeapNumber::kMantissaOffset)); |
@@ -4319,7 +4365,7 @@ |
__ tst(scratch2, scratch2); |
runtime.Branch(ne); |
- // Load the e |
+ // Load the higher bits (which contains the floating point exponent). |
__ ldr(scratch1, FieldMemOperand(exponent, HeapNumber::kExponentOffset)); |
// Compare exponent with -0.5. |