Chromium Code Reviews| Index: src/ia32/lithium-codegen-ia32.cc |
| =================================================================== |
| --- src/ia32/lithium-codegen-ia32.cc (revision 5940) |
| +++ src/ia32/lithium-codegen-ia32.cc (working copy) |
| @@ -2174,6 +2174,66 @@ |
| } |
| +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(); |
| + if (instr->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::double_fp_operation(Token::BIT_XOR), 4); |
|
fschneider
2010/12/08 11:27:07
I'd write this as ExternalReference::pow()
|
| + } else if (instr->exponent_type().IsInteger32()) { |
| + __ PrepareCallCFunction(4, ebx); |
| + __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); |
| + __ mov(Operand(esp, 1 * kDoubleSize), ToRegister(right)); |
| + __ CallCFunction(ExternalReference::double_fp_operation(Token::BIT_OR), 4); |
|
fschneider
2010/12/08 11:27:07
and here sth like ExternalReference::powi(), not n
|
| + } else { |
| + ASSERT(instr->exponent_type().IsTagged()); |
|
fschneider
2010/12/08 11:27:07
Maybe you can re-use the NumberUntagD instruction
William Hesse
2010/12/08 13:37:00
We call two different MathPow functions here, one
|
| + __ 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::double_fp_operation(Token::BIT_OR), 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::double_fp_operation(Token::BIT_XOR), 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 +2248,9 @@ |
| case kMathSqrt: |
| DoMathSqrt(instr); |
| break; |
| + case kMathPowHalf: |
| + DoMathPowHalf(instr); |
| + break; |
| default: |
| UNREACHABLE(); |
| } |