Index: src/x64/lithium-codegen-x64.cc |
=================================================================== |
--- src/x64/lithium-codegen-x64.cc (revision 6849) |
+++ src/x64/lithium-codegen-x64.cc (working copy) |
@@ -2081,22 +2081,77 @@ |
void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
- Abort("Unimplemented: %s", "DoMathFloor"); |
+ XMMRegister xmm_scratch = xmm0; |
+ Register output_reg = ToRegister(instr->result()); |
+ XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
+ __ xorpd(xmm_scratch, xmm_scratch); // Zero the register. |
+ __ ucomisd(input_reg, xmm_scratch); |
+ |
+ if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
+ DeoptimizeIf(below_equal, instr->environment()); |
+ } else { |
+ DeoptimizeIf(below, instr->environment()); |
+ } |
+ |
+ // Use truncating instruction (OK because input is positive). |
+ __ cvttsd2si(output_reg, input_reg); |
Lasse Reichstein
2011/02/18 14:13:47
Use the "q" version, so you can properly handle mi
William Hesse
2011/02/18 14:33:28
But then we have much more complicated tests, beca
|
+ |
+ // Overflow is signalled with minint. |
+ __ cmpl(output_reg, Immediate(0x80000000)); |
+ DeoptimizeIf(equal, instr->environment()); |
} |
void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
- Abort("Unimplemented: %s", "DoMathRound"); |
+ const XMMRegister xmm_scratch = xmm0; |
+ Register output_reg = ToRegister(instr->result()); |
+ XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
+ |
+ // xmm_scratch = 0.5 |
+ ExternalReference one_half = ExternalReference::address_of_one_half(); |
+ __ movq(kScratchRegister, one_half); |
+ __ movsd(xmm_scratch, Operand(kScratchRegister, 0)); |
Lasse Reichstein
2011/02/18 14:13:47
Why load from memory when we have 64-bit immediate
William Hesse
2011/02/18 14:33:28
Done.
|
+ |
+ // input = input + 0.5 |
+ __ addsd(input_reg, xmm_scratch); |
+ |
+ // We need to return -0 for the input range [-0.5, 0[, otherwise |
+ // compute Math.floor(value + 0.5). |
+ if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
+ __ ucomisd(input_reg, xmm_scratch); |
+ DeoptimizeIf(below_equal, instr->environment()); |
+ } else { |
+ // If we don't need to bailout on -0, we check only bailout |
+ // on negative inputs. |
+ __ xorpd(xmm_scratch, xmm_scratch); // Zero the register. |
+ __ ucomisd(input_reg, xmm_scratch); |
+ DeoptimizeIf(below, instr->environment()); |
+ } |
+ |
+ // Compute Math.floor(value + 0.5). |
+ // Use truncating instruction (OK because input is positive). |
+ __ cvttsd2si(output_reg, input_reg); |
+ |
+ // Overflow is signalled with minint. |
+ __ cmpl(output_reg, Immediate(0x80000000)); |
+ DeoptimizeIf(equal, instr->environment()); |
} |
void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
- Abort("Unimplemented: %s", "DoMathSqrt"); |
+ XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
+ ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
+ __ sqrtsd(input_reg, input_reg); |
} |
void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { |
- Abort("Unimplemented: %s", "DoMathPowHalf"); |
+ XMMRegister xmm_scratch = xmm0; |
+ XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
+ ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
+ __ xorpd(xmm_scratch, xmm_scratch); |
+ __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. |
+ __ sqrtsd(input_reg, input_reg); |
} |
@@ -2121,7 +2176,35 @@ |
void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { |
- Abort("Unimplemented: %s", "DoUnaryMathOperation"); |
+ switch (instr->op()) { |
+ case kMathAbs: |
+ DoMathAbs(instr); |
+ break; |
+ case kMathFloor: |
+ DoMathFloor(instr); |
+ break; |
+ case kMathRound: |
+ DoMathRound(instr); |
+ break; |
+ case kMathSqrt: |
+ DoMathSqrt(instr); |
+ break; |
+ case kMathPowHalf: |
+ DoMathPowHalf(instr); |
+ break; |
+ case kMathCos: |
+ DoMathCos(instr); |
+ break; |
+ case kMathSin: |
+ DoMathSin(instr); |
+ break; |
+ case kMathLog: |
+ DoMathLog(instr); |
+ break; |
+ |
+ default: |
+ UNREACHABLE(); |
+ } |
} |