Register result = ToRegister(instr->result());
Label done;
- if (CpuFeatures::IsSupported(SUDIV)) {
- CpuFeatureScope scope(masm(), SUDIV);
// Check for x % 0.
- if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
- __ cmp(right, Operand::Zero());
- DeoptimizeIf(eq, instr->environment());
- }
+ if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
+ __ cmp(right, Operand::Zero());
+ DeoptimizeIf(eq, instr->environment());
+ }
+ if (CpuFeatures::IsSupported(SUDIV)) {
+ CpuFeatureScope scope(masm(), SUDIV);
// Check for (kMinInt % -1).
if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
Label left_not_min_int;
__ sdiv(result, left, right);
__ mls(result, result, right, left);
- __ cmp(result, Operand::Zero());
- __ b(ne, &done);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
- __ cmp(left, Operand::Zero());
- DeoptimizeIf(lt, instr->environment());
+ __ cmp(result, Operand::Zero());
+ __ b(ne, &done);
+ __ cmp(left, Operand::Zero());
+ DeoptimizeIf(lt, instr->environment());
}
} else {
Register scratch = scratch0();
ASSERT(!scratch.is(right));
ASSERT(!scratch.is(result));
- Label vfp_modulo, both_positive, right_negative;
-
- // Check for x % 0.
- if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
- __ cmp(right, Operand::Zero());
- DeoptimizeIf(eq, instr->environment());
- }
+ Label vfp_modulo, right_negative;
__ Move(result, left);
__ JumpIfNotPowerOfTwoOrZeroAndNeg(right,
scratch,
&right_negative,
- &both_positive);
+ &vfp_modulo);
// Perform modulo operation (scratch contains right - 1).
__ and_(result, scratch, Operand(left));
__ b(&done);
// Negate right. The sign of the divisor does not matter.
__ rsb(right, right, Operand::Zero());
- __ bind(&both_positive);
- const int kUnfolds = 3;
- // If the right hand side is smaller than the (nonnegative)
- // left hand side, the left hand side is the result.
- // Else try a few subtractions of the left hand side.
- __ mov(scratch, left);
- for (int i = 0; i < kUnfolds; i++) {
- // Check if the left hand side is less or equal than the
- // the right hand side.
- __ cmp(scratch, Operand(right));
- __ mov(result, scratch, LeaveCC, lt);
- __ b(lt, &done);
- // If not, reduce the left hand side by the right hand
- // side and check again.
- if (i < kUnfolds - 1) __ sub(scratch, scratch, right);
- }
-
__ bind(&vfp_modulo);
// Load the arguments in VFP registers.
// The divisor value is preloaded before. Be careful that 'right'
__ and_(dividend, divisor - 1);
__ bind(&done);
} else {
- Label done, remainder_eq_dividend, slow, do_subtraction, both_positive;
+ Label done, remainder_eq_dividend, slow, both_positive;
Register left_reg = ToRegister(instr->left());
Register right_reg = ToRegister(instr->right());
Register result_reg = ToRegister(instr->result());
__ mov(scratch, right_reg);
__ sub(Operand(scratch), Immediate(1));
__ test(scratch, Operand(right_reg));
- __ j(not_zero, &do_subtraction, Label::kNear);
+ __ j(not_zero, &slow, Label::kNear);
__ and_(left_reg, Operand(scratch));
__ jmp(&remainder_eq_dividend, Label::kNear);
- __ 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, Label::kNear);
- }
- __ mov(left_reg, scratch);
-
// Slow case, using idiv instruction.
__ bind(&slow);
__ andl(dividend, Immediate(divisor - 1));
__ bind(&done);
} else {
- Label done, remainder_eq_dividend, slow, do_subtraction, both_positive;
+ Label done, remainder_eq_dividend, slow, both_positive;
Register left_reg = ToRegister(instr->left());
Register right_reg = ToRegister(instr->right());
Register result_reg = ToRegister(instr->result());
__ movl(scratch, right_reg);
__ subl(scratch, Immediate(1));
__ testl(scratch, right_reg);
- __ j(not_zero, &do_subtraction, Label::kNear);
+ __ j(not_zero, &slow, Label::kNear);
__ andl(left_reg, scratch);
__ jmp(&remainder_eq_dividend, Label::kNear);
- __ bind(&do_subtraction);
- const int kUnfolds = 3;
- // Try a few subtractions of the dividend.
- __ movl(scratch, left_reg);
- for (int i = 0; i < kUnfolds; i++) {
- // Reduce the dividend by the divisor.
- __ subl(left_reg, right_reg);
- // Check if the dividend is less than the divisor.
- __ cmpl(left_reg, right_reg);
- __ j(less, &remainder_eq_dividend, Label::kNear);
- }
- __ movl(left_reg, scratch);
-
// Slow case, using idiv instruction.
__ bind(&slow);