Chromium Code Reviews| Index: src/arm/code-stubs-arm.cc |
| diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc |
| index 1c6d709f12564d00581fcd4648dea5ae1b9b1cfb..08713f391125beb7a47dbd7700761286ba7ece8a 100644 |
| --- a/src/arm/code-stubs-arm.cc |
| +++ b/src/arm/code-stubs-arm.cc |
| @@ -4056,6 +4056,107 @@ void GenericUnaryOpStub::Generate(MacroAssembler* masm) { |
| } |
| +void MathPowStub::Generate(MacroAssembler* masm) { |
| + Label call_runtime; |
| + |
| + if (CpuFeatures::IsSupported(VFP3)) { |
| + CpuFeatures::Scope scope(VFP3); |
| + |
| + Label base_not_smi; |
| + Label exponent_not_smi; |
| + Label convert_exponent; |
| + |
| + const Register base = r0; |
| + const Register exponent = r1; |
| + const Register result = r0; |
| + const Register heapnumbermap = r5; |
| + const Register heapnumber = r6; |
| + const DoubleRegister double_base = d0; |
| + const DoubleRegister double_exponent = d1; |
| + const DoubleRegister double_result = d2; |
| + const SwVfpRegister single_scratch = s0; |
| + const Register scratch = r9; |
| + const Register scratch2 = r7; |
| + |
| + ASSERT(result.is(r0)); |
| + |
| + __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); |
| + __ ldr(base, MemOperand(sp, 1 * kPointerSize)); |
| + __ ldr(exponent, MemOperand(sp, 0 * kPointerSize)); |
| + |
| + // Convert base to double value and store it in d0. |
| + __ JumpIfNotSmi(base, &base_not_smi); |
| + // Base is a Smi. Untag and convert it. |
| + __ SmiUntag(base); |
| + __ vmov(single_scratch, base); |
| + __ vcvt_f64_s32(double_base, single_scratch); |
| + __ b(&convert_exponent); |
| + |
| + __ bind(&base_not_smi); |
| + __ ldr(scratch, FieldMemOperand(base, JSObject::kMapOffset)); |
| + __ cmp(scratch, heapnumbermap); |
| + __ b(ne, &call_runtime); |
| + // Base is a heapnumber. Load it into double register. |
| + __ vldr(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); |
| + |
| + __ bind(&convert_exponent); |
| + __ JumpIfNotSmi(exponent, &exponent_not_smi); |
| + __ SmiUntag(exponent); |
| + |
| + // The base is in a double register and the exponent is |
| + // an untagged smi. Allocate a heap number and call a |
| + // C function for integer exponents. |
|
Søren Thygesen Gjesse
2011/03/08 10:05:12
Maybe add a comment that heapnumber is callee save
Karl Klose
2011/03/08 10:29:00
Done.
|
| + __ AllocateHeapNumber(heapnumber, |
| + scratch, |
| + scratch2, |
| + heapnumbermap, |
| + &call_runtime); |
| + __ push(lr); |
| + __ PrepareCallCFunction(3, scratch); |
| + __ mov(r2, exponent); |
| + __ vmov(r0, r1, double_base); |
| + __ CallCFunction(ExternalReference::power_double_int_function(), 3); |
| + __ pop(lr); |
| + __ GetCFunctionDoubleResult(double_result); |
| + __ vstr(double_result, |
| + FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); |
| + __ mov(result, heapnumber); |
|
Søren Thygesen Gjesse
2011/03/08 10:05:12
I think it would be fine to just use r0 here and d
Karl Klose
2011/03/08 10:29:00
Done.
|
| + __ Ret(2 * kPointerSize); |
| + |
| + __ bind(&exponent_not_smi); |
| + __ ldr(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); |
| + __ cmp(scratch, heapnumbermap); |
| + __ b(ne, &call_runtime); |
| + // Exponent is a heapnumber. Load it into double register. |
| + __ vldr(double_exponent, |
| + FieldMemOperand(exponent, HeapNumber::kValueOffset)); |
| + |
| + // The base and the exponent are in double registers. |
| + // Allocate a heap number and call a C function for |
| + // double exponents. |
|
Søren Thygesen Gjesse
2011/03/08 10:05:12
Ditto.
Karl Klose
2011/03/08 10:29:00
Done.
|
| + __ AllocateHeapNumber(heapnumber, |
| + scratch, |
| + scratch2, |
| + heapnumbermap, |
| + &call_runtime); |
| + __ push(lr); |
| + __ PrepareCallCFunction(4, scratch); |
| + __ vmov(r0, r1, double_base); |
| + __ vmov(r2, r3, double_exponent); |
| + __ CallCFunction(ExternalReference::power_double_double_function(), 4); |
| + __ pop(lr); |
| + __ GetCFunctionDoubleResult(double_result); |
| + __ vstr(double_result, |
| + FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); |
| + __ mov(result, heapnumber); |
|
Søren Thygesen Gjesse
2011/03/08 10:05:12
Ditto.
Karl Klose
2011/03/08 10:29:00
Done.
|
| + __ Ret(2 * kPointerSize); |
| + } |
| + |
| + __ bind(&call_runtime); |
| + __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); |
| +} |
| + |
| + |
| void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { |
| __ Throw(r0); |
| } |