Index: src/arm/lithium-codegen-arm.cc |
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc |
index a0da25c2b1d561a4203556d46f02b5be4d8e933c..698b6db2bdbd8222384f9612b0ec648f512de8cb 100644 |
--- a/src/arm/lithium-codegen-arm.cc |
+++ b/src/arm/lithium-codegen-arm.cc |
@@ -1649,6 +1649,68 @@ void LCodeGen::DoAddI(LAddI* instr) { |
} |
+void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
+ LOperand* left = instr->InputAt(0); |
+ LOperand* right = instr->InputAt(1); |
+ HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
+ Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; |
+ if (instr->hydrogen()->representation().IsInteger32()) { |
+ Register left_reg = ToRegister(left); |
+ Operand right_op = (right->IsRegister() || right->IsConstantOperand()) |
+ ? ToOperand(right) |
+ : Operand(EmitLoadRegister(right, ip)); |
+ Register result_reg = ToRegister(instr->result()); |
+ __ cmp(left_reg, right_op); |
+ if (!result_reg.is(left_reg)) { |
+ __ mov(result_reg, left_reg, LeaveCC, condition); |
+ } |
+ __ mov(result_reg, right_op, LeaveCC, NegateCondition(condition)); |
+ } else { |
+ ASSERT(instr->hydrogen()->representation().IsDouble()); |
+ DoubleRegister left_reg = ToDoubleRegister(left); |
+ DoubleRegister right_reg = ToDoubleRegister(right); |
+ DoubleRegister result_reg = ToDoubleRegister(instr->result()); |
+ Label check_nan_left, check_zero, return_left, return_right, done; |
+ __ VFPCompareAndSetFlags(left_reg, right_reg); |
+ __ b(vs, &check_nan_left); |
+ __ b(eq, &check_zero); |
+ __ b(condition, &return_left); |
+ __ b(al, &return_right); |
+ |
+ __ bind(&check_zero); |
+ __ VFPCompareAndSetFlags(left_reg, 0.0); |
+ __ b(ne, &return_left); // left == right != 0. |
+ // At this point, both left and right are either 0 or -0. |
+ if (operation == HMathMinMax::kMathMin) { |
+ // We could use a single 'vorr' instruction here if we had NEON support. |
+ __ vneg(left_reg, left_reg); |
+ __ vsub(result_reg, left_reg, right_reg); |
+ __ vneg(result_reg, result_reg); |
+ } else { |
+ // Since we operate on +0 and/or -0, vadd and vand have the same effect; |
+ // the decision for vadd is easy because vand is a NEON instruction. |
+ __ vadd(result_reg, left_reg, right_reg); |
+ } |
+ __ b(al, &done); |
+ |
+ __ bind(&check_nan_left); |
+ __ VFPCompareAndSetFlags(left_reg, left_reg); |
+ __ b(vs, &return_left); // left == NaN. |
+ __ bind(&return_right); |
+ if (!right_reg.is(result_reg)) { |
+ __ vmov(result_reg, right_reg); |
+ } |
+ __ b(al, &done); |
+ |
+ __ bind(&return_left); |
+ if (!left_reg.is(result_reg)) { |
+ __ vmov(result_reg, left_reg); |
+ } |
+ __ bind(&done); |
+ } |
+} |
+ |
+ |
void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
DoubleRegister left = ToDoubleRegister(instr->InputAt(0)); |
DoubleRegister right = ToDoubleRegister(instr->InputAt(1)); |