Index: src/x64/codegen-x64.cc |
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc |
index aa777baf50ecf36e194474c9c79fa7ca96abcc58..e2471e69cc726d69c1eed338ac333558a8be6b9f 100644 |
--- a/src/x64/codegen-x64.cc |
+++ b/src/x64/codegen-x64.cc |
@@ -99,6 +99,36 @@ UnaryMathFunction CreateTranscendentalFunction(TranscendentalCache::Type type) { |
} |
+UnaryMathFunction CreateExpFunction() { |
+ 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)); |
+ // xmm0: raw double input. |
+ XMMRegister input = xmm0; |
+ XMMRegister result = xmm1; |
+ __ push(rax); |
+ __ push(rbx); |
+ |
+ MathExpGenerator::EmitMathExp(&masm, input, result, xmm2, rax, rbx); |
+ |
+ __ pop(rbx); |
+ __ pop(rax); |
+ __ movsd(xmm0, result); |
+ __ Ret(); |
+ |
+ CodeDesc desc; |
+ masm.GetCode(&desc); |
+ |
+ CPU::FlushICache(buffer, actual_size); |
+ OS::ProtectCode(buffer, actual_size); |
+ return FUNCTION_CAST<UnaryMathFunction>(buffer); |
+} |
+ |
+ |
UnaryMathFunction CreateSqrtFunction() { |
size_t actual_size; |
// Allocate buffer in executable space. |
@@ -575,6 +605,58 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm, |
__ bind(&done); |
} |
+ |
+void MathExpGenerator::EmitMathExp(MacroAssembler* masm, |
+ XMMRegister input, |
+ XMMRegister result, |
+ XMMRegister double_scratch, |
+ Register temp1, |
+ Register temp2) { |
+ ASSERT(!input.is(result)); |
+ ASSERT(!input.is(double_scratch)); |
+ ASSERT(!result.is(double_scratch)); |
+ ASSERT(!temp1.is(temp2)); |
+ ASSERT(ExternalReference::math_exp_constants(0).address() != NULL); |
+ |
+ Label done; |
+ |
+ __ movq(kScratchRegister, ExternalReference::math_exp_constants(0)); |
+ __ movsd(double_scratch, Operand(kScratchRegister, 0 * kDoubleSize)); |
+ __ xorpd(result, result); |
+ __ ucomisd(double_scratch, input); |
+ __ j(above_equal, &done); |
+ __ ucomisd(input, Operand(kScratchRegister, 1 * kDoubleSize)); |
+ __ movsd(result, Operand(kScratchRegister, 2 * kDoubleSize)); |
+ __ j(above_equal, &done); |
+ __ movsd(double_scratch, Operand(kScratchRegister, 3 * kDoubleSize)); |
+ __ movsd(result, Operand(kScratchRegister, 4 * kDoubleSize)); |
+ __ mulsd(double_scratch, input); |
+ __ addsd(double_scratch, result); |
+ __ movq(temp2, double_scratch); |
+ __ subsd(double_scratch, result); |
+ __ movsd(result, Operand(kScratchRegister, 6 * kDoubleSize)); |
+ __ lea(temp1, Operand(temp2, 0x1ff800)); |
+ __ and_(temp2, Immediate(0x7ff)); |
+ __ shr(temp1, Immediate(11)); |
+ __ mulsd(double_scratch, Operand(kScratchRegister, 5 * kDoubleSize)); |
+ __ movq(kScratchRegister, ExternalReference::math_exp_log_table()); |
+ __ shl(temp1, Immediate(52)); |
+ __ or_(temp1, Operand(kScratchRegister, temp2, times_8, 0)); |
+ __ movq(kScratchRegister, ExternalReference::math_exp_constants(0)); |
+ __ subsd(double_scratch, input); |
+ __ movsd(input, double_scratch); |
+ __ subsd(result, double_scratch); |
+ __ mulsd(input, double_scratch); |
+ __ mulsd(result, input); |
+ __ movq(input, temp1); |
+ __ mulsd(result, Operand(kScratchRegister, 7 * kDoubleSize)); |
+ __ subsd(result, double_scratch); |
+ __ addsd(result, Operand(kScratchRegister, 8 * kDoubleSize)); |
+ __ mulsd(result, input); |
+ |
+ __ bind(&done); |
+} |
+ |
#undef __ |