| Index: src/arm/lithium-codegen-arm.cc
|
| diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
|
| index 1216486e68993d68cc5aa49085b37df778e69d34..e07118317c464ba1041fc36814dfcfda6b56fb16 100644
|
| --- a/src/arm/lithium-codegen-arm.cc
|
| +++ b/src/arm/lithium-codegen-arm.cc
|
| @@ -979,132 +979,109 @@ void LCodeGen::DoModI(LModI* instr) {
|
| Register left = ToRegister(instr->left());
|
| Register right = ToRegister(instr->right());
|
| Register result = ToRegister(instr->result());
|
| - Label done;
|
|
|
| - if (CpuFeatures::IsSupported(SUDIV)) {
|
| - CpuFeatures::Scope scope(SUDIV);
|
| - // Check for x % 0.
|
| - if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
|
| - __ cmp(right, Operand(0));
|
| - DeoptimizeIf(eq, instr->environment());
|
| - }
|
| + Register scratch = scratch0();
|
| + Register scratch2 = ToRegister(instr->temp());
|
| + DwVfpRegister dividend = ToDoubleRegister(instr->temp2());
|
| + DwVfpRegister divisor = ToDoubleRegister(instr->temp3());
|
| + DwVfpRegister quotient = double_scratch0();
|
|
|
| - // For r3 = r1 % r2; we can have the following ARM code
|
| - // sdiv r3, r1, r2
|
| - // mls r3, r3, r2, r1
|
| + ASSERT(!dividend.is(divisor));
|
| + ASSERT(!dividend.is(quotient));
|
| + ASSERT(!divisor.is(quotient));
|
| + ASSERT(!scratch.is(left));
|
| + ASSERT(!scratch.is(right));
|
| + ASSERT(!scratch.is(result));
|
|
|
| - __ sdiv(result, left, right);
|
| - __ mls(result, result, right, left);
|
| - __ cmp(result, Operand(0));
|
| - __ b(ne, &done);
|
| + Label done, vfp_modulo, both_positive, right_negative;
|
|
|
| - if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| - __ cmp(left, Operand(0));
|
| - DeoptimizeIf(lt, instr->environment());
|
| - }
|
| - } else {
|
| - Register scratch = scratch0();
|
| - Register scratch2 = ToRegister(instr->temp());
|
| - DwVfpRegister dividend = ToDoubleRegister(instr->temp2());
|
| - DwVfpRegister divisor = ToDoubleRegister(instr->temp3());
|
| - DwVfpRegister quotient = double_scratch0();
|
| -
|
| - ASSERT(!dividend.is(divisor));
|
| - ASSERT(!dividend.is(quotient));
|
| - ASSERT(!divisor.is(quotient));
|
| - ASSERT(!scratch.is(left));
|
| - ASSERT(!scratch.is(right));
|
| - ASSERT(!scratch.is(result));
|
| -
|
| - Label done, vfp_modulo, both_positive, right_negative;
|
| -
|
| - // Check for x % 0.
|
| - if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
|
| - __ cmp(right, Operand(0));
|
| - DeoptimizeIf(eq, instr->environment());
|
| - }
|
| -
|
| - __ Move(result, left);
|
| -
|
| - // (0 % x) must yield 0 (if x is finite, which is the case here).
|
| - __ cmp(left, Operand(0));
|
| - __ b(eq, &done);
|
| - // Preload right in a vfp register.
|
| - __ vmov(divisor.low(), right);
|
| - __ b(lt, &vfp_modulo);
|
| + // Check for x % 0.
|
| + if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
|
| + __ cmp(right, Operand(0));
|
| + DeoptimizeIf(eq, instr->environment());
|
| + }
|
|
|
| - __ cmp(left, Operand(right));
|
| - __ b(lt, &done);
|
| + __ Move(result, left);
|
|
|
| - // Check for (positive) power of two on the right hand side.
|
| - __ JumpIfNotPowerOfTwoOrZeroAndNeg(right,
|
| - scratch,
|
| - &right_negative,
|
| - &both_positive);
|
| - // Perform modulo operation (scratch contains right - 1).
|
| - __ and_(result, scratch, Operand(left));
|
| - __ b(&done);
|
| + // (0 % x) must yield 0 (if x is finite, which is the case here).
|
| + __ cmp(left, Operand(0));
|
| + __ b(eq, &done);
|
| + // Preload right in a vfp register.
|
| + __ vmov(divisor.low(), right);
|
| + __ b(lt, &vfp_modulo);
|
|
|
| - __ bind(&right_negative);
|
| - // Negate right. The sign of the divisor does not matter.
|
| - __ rsb(right, right, Operand(0));
|
| -
|
| - __ 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);
|
| - }
|
| + __ cmp(left, Operand(right));
|
| + __ b(lt, &done);
|
| +
|
| + // Check for (positive) power of two on the right hand side.
|
| + __ JumpIfNotPowerOfTwoOrZeroAndNeg(right,
|
| + scratch,
|
| + &right_negative,
|
| + &both_positive);
|
| + // Perform modulo operation (scratch contains right - 1).
|
| + __ and_(result, scratch, Operand(left));
|
| + __ b(&done);
|
|
|
| - __ bind(&vfp_modulo);
|
| - // Load the arguments in VFP registers.
|
| - // The divisor value is preloaded before. Be careful that 'right'
|
| - // is only live on entry.
|
| - __ vmov(dividend.low(), left);
|
| - // From here on don't use right as it may have been reallocated
|
| - // (for example to scratch2).
|
| - right = no_reg;
|
| -
|
| - __ vcvt_f64_s32(dividend, dividend.low());
|
| - __ vcvt_f64_s32(divisor, divisor.low());
|
| -
|
| - // We do not care about the sign of the divisor.
|
| - __ vabs(divisor, divisor);
|
| - // Compute the quotient and round it to a 32bit integer.
|
| - __ vdiv(quotient, dividend, divisor);
|
| - __ vcvt_s32_f64(quotient.low(), quotient);
|
| - __ vcvt_f64_s32(quotient, quotient.low());
|
| -
|
| - // Compute the remainder in result.
|
| - DwVfpRegister double_scratch = dividend;
|
| - __ vmul(double_scratch, divisor, quotient);
|
| - __ vcvt_s32_f64(double_scratch.low(), double_scratch);
|
| - __ vmov(scratch, double_scratch.low());
|
| -
|
| - if (!instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| - __ sub(result, left, scratch);
|
| - } else {
|
| - Label ok;
|
| - // Check for -0.
|
| - __ sub(scratch2, left, scratch, SetCC);
|
| - __ b(ne, &ok);
|
| - __ cmp(left, Operand(0));
|
| - DeoptimizeIf(mi, instr->environment());
|
| - __ bind(&ok);
|
| - // Load the result and we are done.
|
| - __ mov(result, scratch2);
|
| - }
|
| + __ bind(&right_negative);
|
| + // Negate right. The sign of the divisor does not matter.
|
| + __ rsb(right, right, Operand(0));
|
| +
|
| + __ 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' is only live
|
| + // on entry.
|
| + __ vmov(dividend.low(), left);
|
| + // From here on don't use right as it may have been reallocated (for example
|
| + // to scratch2).
|
| + right = no_reg;
|
| +
|
| + __ vcvt_f64_s32(dividend, dividend.low());
|
| + __ vcvt_f64_s32(divisor, divisor.low());
|
| +
|
| + // We do not care about the sign of the divisor.
|
| + __ vabs(divisor, divisor);
|
| + // Compute the quotient and round it to a 32bit integer.
|
| + __ vdiv(quotient, dividend, divisor);
|
| + __ vcvt_s32_f64(quotient.low(), quotient);
|
| + __ vcvt_f64_s32(quotient, quotient.low());
|
| +
|
| + // Compute the remainder in result.
|
| + DwVfpRegister double_scratch = dividend;
|
| + __ vmul(double_scratch, divisor, quotient);
|
| + __ vcvt_s32_f64(double_scratch.low(), double_scratch);
|
| + __ vmov(scratch, double_scratch.low());
|
| +
|
| + if (!instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| + __ sub(result, left, scratch);
|
| + } else {
|
| + Label ok;
|
| + // Check for -0.
|
| + __ sub(scratch2, left, scratch, SetCC);
|
| + __ b(ne, &ok);
|
| + __ cmp(left, Operand(0));
|
| + DeoptimizeIf(mi, instr->environment());
|
| + __ bind(&ok);
|
| + // Load the result and we are done.
|
| + __ mov(result, scratch2);
|
| }
|
| +
|
| __ bind(&done);
|
| }
|
|
|
|
|