Index: src/ia32/lithium-codegen-ia32.cc |
=================================================================== |
--- src/ia32/lithium-codegen-ia32.cc (revision 5948) |
+++ src/ia32/lithium-codegen-ia32.cc (working copy) |
@@ -2174,6 +2174,67 @@ |
} |
+void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { |
+ XMMRegister xmm_scratch = xmm0; |
+ XMMRegister input_reg = ToDoubleRegister(instr->input()); |
+ ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
+ ExternalReference negative_infinity = |
+ ExternalReference::address_of_negative_infinity(); |
+ __ movdbl(xmm_scratch, Operand::StaticVariable(negative_infinity)); |
+ __ ucomisd(xmm_scratch, input_reg); |
+ DeoptimizeIf(equal, instr->environment()); |
+ __ sqrtsd(input_reg, input_reg); |
+} |
+ |
+ |
+void LCodeGen::DoPower(LPower* instr) { |
+ LOperand* left = instr->left(); |
+ LOperand* right = instr->right(); |
+ Representation exponent_type = instr->hydrogen()->right()->representation(); |
+ if (exponent_type.IsDouble()) { |
+ // Pass two doubles as arguments on the stack. |
+ __ PrepareCallCFunction(4, eax); |
+ __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); |
+ __ movdbl(Operand(esp, 1 * kDoubleSize), ToDoubleRegister(right)); |
+ __ CallCFunction(ExternalReference::power_double_double_function(), 4); |
+ } else if (exponent_type.IsInteger32()) { |
+ __ PrepareCallCFunction(4, ebx); |
+ __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); |
+ __ mov(Operand(esp, 1 * kDoubleSize), ToRegister(right)); |
+ __ CallCFunction(ExternalReference::power_double_int_function(), 4); |
+ } else { |
+ ASSERT(exponent_type.IsTagged()); |
+ __ PrepareCallCFunction(4, ebx); |
+ __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); |
+ Register right_reg = ToRegister(right); |
+ Label non_smi; |
+ Label done; |
+ __ test(right_reg, Immediate(kSmiTagMask)); |
+ __ j(not_zero, &non_smi); |
+ __ SmiUntag(right_reg); |
+ __ mov(Operand(esp, 1 * kDoubleSize), ToRegister(right)); |
+ __ CallCFunction(ExternalReference::power_double_int_function(), 4); |
+ __ jmp(&done); |
+ |
+ __ bind(&non_smi); |
+ __ CmpObjectType(right_reg, HEAP_NUMBER_TYPE , ebx); |
+ DeoptimizeIf(not_equal, instr->environment()); |
+ __ movdbl(xmm1, FieldOperand(right_reg, HeapNumber::kValueOffset)); |
+ __ movdbl(Operand(esp, 1 * kDoubleSize), xmm1); |
+ __ CallCFunction(ExternalReference::power_double_double_function(), 4); |
+ |
+ __ bind(&done); |
+ } |
+ |
+ // Return value is in st(0) on ia32. |
+ // Store it into the (fixed) result register. |
+ __ sub(Operand(esp), Immediate(kDoubleSize)); |
+ __ fstp_d(Operand(esp, 0)); |
+ __ movdbl(ToDoubleRegister(instr->result()), Operand(esp, 0)); |
+ __ add(Operand(esp), Immediate(kDoubleSize)); |
+} |
+ |
+ |
void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { |
switch (instr->op()) { |
case kMathAbs: |
@@ -2188,6 +2249,9 @@ |
case kMathSqrt: |
DoMathSqrt(instr); |
break; |
+ case kMathPowHalf: |
+ DoMathPowHalf(instr); |
+ break; |
default: |
UNREACHABLE(); |
} |