Index: src/mips/codegen-mips.cc |
diff --git a/src/mips/codegen-mips.cc b/src/mips/codegen-mips.cc |
index 51ad4743de1ee0feada8f6aabeb8a7226a3fd631..963778ef113f50652edcb381a12cd24610924ee2 100644 |
--- a/src/mips/codegen-mips.cc |
+++ b/src/mips/codegen-mips.cc |
@@ -31,11 +31,11 @@ |
#include "codegen.h" |
#include "macro-assembler.h" |
+#include "simulator-mips.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_mips_machine_code = NULL; |
+double fast_exp_simulator(double x) { |
+ return Simulator::current(Isolate::Current())->CallFP( |
+ fast_exp_mips_machine_code, x, 0); |
+} |
+#endif |
+ |
+ |
+UnaryMathFunction CreateExpFunction() { |
+ if (!CpuFeatures::IsSupported(FPU)) 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_fpu(FPU); |
+ DoubleRegister input = f12; |
+ DoubleRegister result = f0; |
+ DoubleRegister double_scratch1 = f4; |
+ DoubleRegister double_scratch2 = f6; |
+ Register temp1 = t0; |
+ Register temp2 = t1; |
+ Register temp3 = t2; |
+ |
+ if (!IsMipsSoftFloatABI) { |
+ // Input value is in f12 anyway, nothing to do. |
+ } else { |
+ __ Move(input, a0, a1); |
+ } |
+ __ Push(temp3, temp2, temp1); |
+ MathExpGenerator::EmitMathExp( |
+ &masm, input, result, double_scratch1, double_scratch2, |
+ temp1, temp2, temp3); |
+ __ Pop(temp3, temp2, temp1); |
+ if (!IsMipsSoftFloatABI) { |
+ // Result is already in f0, nothing to do. |
+ } else { |
+ __ Move(a0, a1, 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_mips_machine_code = buffer; |
+ return &fast_exp_simulator; |
+#endif |
+} |
+ |
+ |
+#undef __ |
+ |
+ |
UnaryMathFunction CreateSqrtFunction() { |
return &sqrt; |
} |
@@ -72,6 +140,8 @@ void StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const { |
// ------------------------------------------------------------------------- |
// Code generators |
+#define __ ACCESS_MASM(masm) |
+ |
void ElementsTransitionGenerator::GenerateMapChangeElementsTransition( |
MacroAssembler* masm) { |
// ----------- S t a t e ------------- |
@@ -446,6 +516,81 @@ 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; |
+ |
+ __ li(temp3, Operand(ExternalReference::math_exp_constants(0))); |
+ |
+ __ ldc1(double_scratch1, ExpConstant(0, temp3)); |
+ __ Move(result, kDoubleRegZero); |
+ __ BranchF(&done, NULL, ge, double_scratch1, input); |
+ __ ldc1(double_scratch2, ExpConstant(1, temp3)); |
+ __ ldc1(result, ExpConstant(2, temp3)); |
+ __ BranchF(&done, NULL, ge, input, double_scratch2); |
+ __ ldc1(double_scratch1, ExpConstant(3, temp3)); |
+ __ ldc1(result, ExpConstant(4, temp3)); |
+ __ mul_d(double_scratch1, double_scratch1, input); |
+ __ add_d(double_scratch1, double_scratch1, result); |
+ __ Move(temp2, temp1, double_scratch1); |
+ __ sub_d(double_scratch1, double_scratch1, result); |
+ __ ldc1(result, ExpConstant(6, temp3)); |
+ __ ldc1(double_scratch2, ExpConstant(5, temp3)); |
+ __ mul_d(double_scratch1, double_scratch1, double_scratch2); |
+ __ sub_d(double_scratch1, double_scratch1, input); |
+ __ sub_d(result, result, double_scratch1); |
+ __ mul_d(input, double_scratch1, double_scratch1); |
+ __ mul_d(result, result, input); |
+ __ srl(temp1, temp2, 11); |
+ __ ldc1(double_scratch2, ExpConstant(7, temp3)); |
+ __ mul_d(result, result, double_scratch2); |
+ __ sub_d(result, result, double_scratch1); |
+ __ ldc1(double_scratch2, ExpConstant(8, temp3)); |
+ __ add_d(result, result, double_scratch2); |
+ __ li(at, 0x7ff); |
+ __ And(temp2, temp2, at); |
+ __ Addu(temp1, temp1, Operand(0x3ff)); |
+ __ sll(temp1, temp1, 20); |
+ |
+ // Must not call ExpConstant() after overwriting temp3! |
+ __ li(temp3, Operand(ExternalReference::math_exp_log_table())); |
+ __ sll(at, temp2, 3); |
+ __ addu(at, at, temp3); |
+ __ lw(at, MemOperand(at)); |
+ __ Addu(temp3, temp3, Operand(kPointerSize)); |
+ __ sll(temp2, temp2, 3); |
+ __ addu(temp2, temp2, temp3); |
+ __ lw(temp2, MemOperand(temp2)); |
+ __ Or(temp1, temp1, temp2); |
+ __ Move(input, at, temp1); |
+ __ mul_d(result, result, input); |
+ __ bind(&done); |
+} |
+ |
+ |
// nop(CODE_AGE_MARKER_NOP) |
static const uint32_t kCodeAgePatchFirstInstruction = 0x00010180; |