| Index: src/arm/codegen-arm.cc
 | 
| diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
 | 
| index 52a62959ef1ebd195cd5cb7725f2fafbb2f6b6e1..689de9f4c64c34e50399de8fb6bb75e921d24672 100644
 | 
| --- a/src/arm/codegen-arm.cc
 | 
| +++ b/src/arm/codegen-arm.cc
 | 
| @@ -31,11 +31,11 @@
 | 
|  
 | 
|  #include "codegen.h"
 | 
|  #include "macro-assembler.h"
 | 
| +#include "simulator-arm.h"
 | 
|  
 | 
|  namespace v8 {
 | 
|  namespace internal {
 | 
|  
 | 
| -#define __ ACCESS_MASM(masm)
 | 
|  
 | 
|  UnaryMathFunction CreateTranscendentalFunction(TranscendentalCache::Type type) {
 | 
|    switch (type) {
 | 
| @@ -49,6 +49,74 @@ UnaryMathFunction CreateTranscendentalFunction(TranscendentalCache::Type type) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| +#define __ masm.
 | 
| +
 | 
| +
 | 
| +#if defined(USE_SIMULATOR)
 | 
| +byte* fast_exp_arm_machine_code = NULL;
 | 
| +double fast_exp_simulator(double x) {
 | 
| +  return Simulator::current(Isolate::Current())->CallFP(
 | 
| +      fast_exp_arm_machine_code, x, 0);
 | 
| +}
 | 
| +#endif
 | 
| +
 | 
| +
 | 
| +UnaryMathFunction CreateExpFunction() {
 | 
| +  if (!CpuFeatures::IsSupported(VFP2)) return &exp;
 | 
| +  if (!FLAG_fast_math) return &exp;
 | 
| +  size_t actual_size;
 | 
| +  byte* buffer = static_cast<byte*>(OS::Allocate(1 * KB, &actual_size, true));
 | 
| +  if (buffer == NULL) return &exp;
 | 
| +  ExternalReference::InitializeMathExpData();
 | 
| +
 | 
| +  MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
 | 
| +
 | 
| +  {
 | 
| +    CpuFeatures::Scope use_vfp(VFP2);
 | 
| +    DoubleRegister input = d0;
 | 
| +    DoubleRegister result = d1;
 | 
| +    DoubleRegister double_scratch1 = d2;
 | 
| +    DoubleRegister double_scratch2 = d3;
 | 
| +    Register temp1 = r4;
 | 
| +    Register temp2 = r5;
 | 
| +    Register temp3 = r6;
 | 
| +
 | 
| +    if (masm.use_eabi_hardfloat()) {
 | 
| +      // Input value is in d0 anyway, nothing to do.
 | 
| +    } else {
 | 
| +      __ vmov(input, r0, r1);
 | 
| +    }
 | 
| +    __ Push(temp3, temp2, temp1);
 | 
| +    MathExpGenerator::EmitMathExp(
 | 
| +        &masm, input, result, double_scratch1, double_scratch2,
 | 
| +        temp1, temp2, temp3);
 | 
| +    __ Pop(temp3, temp2, temp1);
 | 
| +    if (masm.use_eabi_hardfloat()) {
 | 
| +      __ vmov(d0, result);
 | 
| +    } else {
 | 
| +      __ vmov(r0, r1, result);
 | 
| +    }
 | 
| +    __ Ret();
 | 
| +  }
 | 
| +
 | 
| +  CodeDesc desc;
 | 
| +  masm.GetCode(&desc);
 | 
| +
 | 
| +  CPU::FlushICache(buffer, actual_size);
 | 
| +  OS::ProtectCode(buffer, actual_size);
 | 
| +
 | 
| +#if !defined(USE_SIMULATOR)
 | 
| +  return FUNCTION_CAST<UnaryMathFunction>(buffer);
 | 
| +#else
 | 
| +  fast_exp_arm_machine_code = buffer;
 | 
| +  return &fast_exp_simulator;
 | 
| +#endif
 | 
| +}
 | 
| +
 | 
| +
 | 
| +#undef __
 | 
| +
 | 
| +
 | 
|  UnaryMathFunction CreateSqrtFunction() {
 | 
|    return &sqrt;
 | 
|  }
 | 
| @@ -73,6 +141,8 @@ void StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const {
 | 
|  // -------------------------------------------------------------------------
 | 
|  // Code generators
 | 
|  
 | 
| +#define __ ACCESS_MASM(masm)
 | 
| +
 | 
|  void ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
 | 
|      MacroAssembler* masm) {
 | 
|    // ----------- S t a t e -------------
 | 
| @@ -450,6 +520,78 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
 | 
|    __ bind(&done);
 | 
|  }
 | 
|  
 | 
| +
 | 
| +static MemOperand ExpConstant(int index, Register base) {
 | 
| +  return MemOperand(base, index * kDoubleSize);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void MathExpGenerator::EmitMathExp(MacroAssembler* masm,
 | 
| +                                   DoubleRegister input,
 | 
| +                                   DoubleRegister result,
 | 
| +                                   DoubleRegister double_scratch1,
 | 
| +                                   DoubleRegister double_scratch2,
 | 
| +                                   Register temp1,
 | 
| +                                   Register temp2,
 | 
| +                                   Register temp3) {
 | 
| +  ASSERT(!input.is(result));
 | 
| +  ASSERT(!input.is(double_scratch1));
 | 
| +  ASSERT(!input.is(double_scratch2));
 | 
| +  ASSERT(!result.is(double_scratch1));
 | 
| +  ASSERT(!result.is(double_scratch2));
 | 
| +  ASSERT(!double_scratch1.is(double_scratch2));
 | 
| +  ASSERT(!temp1.is(temp2));
 | 
| +  ASSERT(!temp1.is(temp3));
 | 
| +  ASSERT(!temp2.is(temp3));
 | 
| +  ASSERT(ExternalReference::math_exp_constants(0).address() != NULL);
 | 
| +
 | 
| +  Label done;
 | 
| +
 | 
| +  __ mov(temp3, Operand(ExternalReference::math_exp_constants(0)));
 | 
| +
 | 
| +  __ vldr(double_scratch1, ExpConstant(0, temp3));
 | 
| +  __ vmov(result, kDoubleRegZero);
 | 
| +  __ VFPCompareAndSetFlags(double_scratch1, input);
 | 
| +  __ b(ge, &done);
 | 
| +  __ vldr(double_scratch2, ExpConstant(1, temp3));
 | 
| +  __ VFPCompareAndSetFlags(input, double_scratch2);
 | 
| +  __ vldr(result, ExpConstant(2, temp3));
 | 
| +  __ b(ge, &done);
 | 
| +  __ vldr(double_scratch1, ExpConstant(3, temp3));
 | 
| +  __ vldr(result, ExpConstant(4, temp3));
 | 
| +  __ vmul(double_scratch1, double_scratch1, input);
 | 
| +  __ vadd(double_scratch1, double_scratch1, result);
 | 
| +  __ vmov(temp2, temp1, double_scratch1);
 | 
| +  __ vsub(double_scratch1, double_scratch1, result);
 | 
| +  __ vldr(result, ExpConstant(6, temp3));
 | 
| +  __ vldr(double_scratch2, ExpConstant(5, temp3));
 | 
| +  __ vmul(double_scratch1, double_scratch1, double_scratch2);
 | 
| +  __ vsub(double_scratch1, double_scratch1, input);
 | 
| +  __ vsub(result, result, double_scratch1);
 | 
| +  __ vmul(input, double_scratch1, double_scratch1);
 | 
| +  __ vmul(result, result, input);
 | 
| +  __ mov(temp1, Operand(temp2, LSR, 11));
 | 
| +  __ vldr(double_scratch2, ExpConstant(7, temp3));
 | 
| +  __ vmul(result, result, double_scratch2);
 | 
| +  __ vsub(result, result, double_scratch1);
 | 
| +  __ vldr(double_scratch2, ExpConstant(8, temp3));
 | 
| +  __ vadd(result, result, double_scratch2);
 | 
| +  __ movw(ip, 0x7ff);
 | 
| +  __ and_(temp2, temp2, Operand(ip));
 | 
| +  __ add(temp1, temp1, Operand(0x3ff));
 | 
| +  __ mov(temp1, Operand(temp1, LSL, 20));
 | 
| +
 | 
| +  // Must not call ExpConstant() after overwriting temp3!
 | 
| +  __ mov(temp3, Operand(ExternalReference::math_exp_log_table()));
 | 
| +  __ ldr(ip, MemOperand(temp3, temp2, LSL, 3));
 | 
| +  __ add(temp3, temp3, Operand(kPointerSize));
 | 
| +  __ ldr(temp2, MemOperand(temp3, temp2, LSL, 3));
 | 
| +  __ orr(temp1, temp1, temp2);
 | 
| +  __ vmov(input, ip, temp1);
 | 
| +  __ vmul(result, result, input);
 | 
| +  __ bind(&done);
 | 
| +}
 | 
| +
 | 
|  #undef __
 | 
|  
 | 
|  // add(r0, pc, Operand(-8))
 | 
| 
 |