| Index: src/ia32/lithium-codegen-ia32.cc
|
| ===================================================================
|
| --- src/ia32/lithium-codegen-ia32.cc (revision 7695)
|
| +++ src/ia32/lithium-codegen-ia32.cc (working copy)
|
| @@ -799,20 +799,61 @@
|
| __ and_(dividend, divisor - 1);
|
| __ bind(&done);
|
| } else {
|
| - LOperand* right = instr->InputAt(1);
|
| - ASSERT(ToRegister(instr->InputAt(0)).is(eax));
|
| - ASSERT(ToRegister(instr->result()).is(edx));
|
| + NearLabel done, remainder_eq_dividend, slow, do_subtraction, both_positive;
|
| + Register left_reg = ToRegister(instr->InputAt(0));
|
| + Register right_reg = ToRegister(instr->InputAt(1));
|
| + Register result_reg = ToRegister(instr->result());
|
|
|
| - Register right_reg = ToRegister(right);
|
| + ASSERT(left_reg.is(eax));
|
| + ASSERT(result_reg.is(edx));
|
| ASSERT(!right_reg.is(eax));
|
| ASSERT(!right_reg.is(edx));
|
|
|
| // Check for x % 0.
|
| if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
|
| - __ test(right_reg, ToOperand(right));
|
| + __ test(right_reg, Operand(right_reg));
|
| DeoptimizeIf(zero, instr->environment());
|
| }
|
|
|
| + __ test(left_reg, Operand(left_reg));
|
| + __ j(zero, &remainder_eq_dividend);
|
| + __ j(sign, &slow);
|
| +
|
| + __ test(right_reg, Operand(right_reg));
|
| + __ j(not_sign, &both_positive);
|
| + // The sign of the divisor doesn't matter.
|
| + __ neg(right_reg);
|
| +
|
| + __ bind(&both_positive);
|
| + // If the dividend is smaller than the nonnegative
|
| + // divisor, the dividend is the result.
|
| + __ cmp(left_reg, Operand(right_reg));
|
| + __ j(less, &remainder_eq_dividend);
|
| +
|
| + // Check if the divisor is a PowerOfTwo integer.
|
| + Register scratch = ToRegister(instr->TempAt(0));
|
| + __ mov(scratch, right_reg);
|
| + __ sub(Operand(scratch), Immediate(1));
|
| + __ test(scratch, Operand(right_reg));
|
| + __ j(not_zero, &do_subtraction);
|
| + __ and_(left_reg, Operand(scratch));
|
| + __ jmp(&remainder_eq_dividend);
|
| +
|
| + __ bind(&do_subtraction);
|
| + const int kUnfolds = 3;
|
| + // Try a few subtractions of the dividend.
|
| + __ mov(scratch, left_reg);
|
| + for (int i = 0; i < kUnfolds; i++) {
|
| + // Reduce the dividend by the divisor.
|
| + __ sub(left_reg, Operand(right_reg));
|
| + // Check if the dividend is less than the divisor.
|
| + __ cmp(left_reg, Operand(right_reg));
|
| + __ j(less, &remainder_eq_dividend);
|
| + }
|
| + __ mov(left_reg, scratch);
|
| +
|
| + // Slow case, using idiv instruction.
|
| + __ bind(&slow);
|
| // Sign extend to edx.
|
| __ cdq();
|
|
|
| @@ -820,12 +861,12 @@
|
| if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| NearLabel positive_left;
|
| NearLabel done;
|
| - __ test(eax, Operand(eax));
|
| + __ test(left_reg, Operand(left_reg));
|
| __ j(not_sign, &positive_left);
|
| __ idiv(right_reg);
|
|
|
| // Test the remainder for 0, because then the result would be -0.
|
| - __ test(edx, Operand(edx));
|
| + __ test(result_reg, Operand(result_reg));
|
| __ j(not_zero, &done);
|
|
|
| DeoptimizeIf(no_condition, instr->environment());
|
| @@ -835,6 +876,12 @@
|
| } else {
|
| __ idiv(right_reg);
|
| }
|
| + __ jmp(&done);
|
| +
|
| + __ bind(&remainder_eq_dividend);
|
| + __ mov(result_reg, left_reg);
|
| +
|
| + __ bind(&done);
|
| }
|
| }
|
|
|
|
|