Chromium Code Reviews| Index: src/x64/lithium-codegen-x64.cc |
| =================================================================== |
| --- src/x64/lithium-codegen-x64.cc (revision 6962) |
| +++ src/x64/lithium-codegen-x64.cc (working copy) |
| @@ -2462,7 +2462,57 @@ |
| void LCodeGen::DoPower(LPower* instr) { |
| - Abort("Unimplemented: %s", "DoPower"); |
| + LOperand* left = instr->InputAt(0); |
| + DoubleRegister left_reg = ToDoubleRegister(left); |
|
Rico
2011/02/28 19:18:34
I don't think we use DoubleRegister anywhere else
|
| + LOperand* right = instr->InputAt(1); |
| + DoubleRegister result_reg = ToDoubleRegister(instr->result()); |
| + Representation exponent_type = instr->hydrogen()->right()->representation(); |
| + if (exponent_type.IsDouble()) { |
| + DoubleRegister right_reg = ToDoubleRegister(right); |
| + __ PrepareCallCFunction(2); |
| + // Move arguments to correct registers |
| + __ movsd(xmm0, left_reg); |
| + if (!right_reg.is(xmm1)) { |
|
Rico
2011/02/28 19:18:34
We know that right is in xmm2, you explicitly requ
|
| + __ movsd(xmm1, right_reg); |
| + } |
| + __ CallCFunction(ExternalReference::power_double_double_function(), 4); |
| + } else if (exponent_type.IsInteger32()) { |
| + Register right_reg = ToRegister(right); |
| + __ PrepareCallCFunction(2); |
| + // Move arguments to correct registers: xmm0 and edi (not rdi). |
| + __ movsd(xmm0, left_reg); |
| + if (!right_reg.is(rdi)) { |
|
Rico
2011/02/28 19:18:34
We know that right is in rax, you explicitly reque
|
| + __ movl(rdi, right_reg); |
| + } |
| + __ CallCFunction(ExternalReference::power_double_int_function(), 4); |
| + } else { |
| + ASSERT(exponent_type.IsTagged()); |
| + CpuFeatures::Scope scope(SSE2); |
| + Register right_reg = ToRegister(right); |
| + |
| + Label non_smi, call; |
| + __ JumpIfNotSmi(right_reg, &non_smi); |
| + __ SmiToInteger32(right_reg, right_reg); |
| + __ cvtlsi2sd(result_reg, right_reg); |
| + __ jmp(&call); |
| + |
| + __ bind(&non_smi); |
| + __ CmpObjectType(right_reg, HEAP_NUMBER_TYPE , kScratchRegister); |
| + DeoptimizeIf(not_equal, instr->environment()); |
| + __ movsd(result_reg, FieldOperand(right_reg, HeapNumber::kValueOffset)); |
| + |
| + __ bind(&call); |
| + __ PrepareCallCFunction(2); |
| + // Move arguments to correct registers xmm0 and xmm1. |
| + __ movsd(xmm0, left_reg); |
| + if (!result_reg.is(xmm1)) { |
| + __ movsd(xmm1, result_reg); |
| + } |
| + // Right argument is already in xmm1. |
| + __ CallCFunction(ExternalReference::power_double_double_function(), 4); |
| + } |
| + // Return value is in xmm0. |
| + __ movsd(result_reg, xmm0); |
| } |