Index: src/arm/lithium-codegen-arm.cc |
=================================================================== |
--- src/arm/lithium-codegen-arm.cc (revision 12559) |
+++ src/arm/lithium-codegen-arm.cc (working copy) |
@@ -979,109 +979,132 @@ |
Register left = ToRegister(instr->left()); |
Register right = ToRegister(instr->right()); |
Register result = ToRegister(instr->result()); |
+ Label done; |
- Register scratch = scratch0(); |
- Register scratch2 = ToRegister(instr->temp()); |
- DwVfpRegister dividend = ToDoubleRegister(instr->temp2()); |
- DwVfpRegister divisor = ToDoubleRegister(instr->temp3()); |
- DwVfpRegister quotient = double_scratch0(); |
+ 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()); |
+ } |
- ASSERT(!dividend.is(divisor)); |
- ASSERT(!dividend.is(quotient)); |
- ASSERT(!divisor.is(quotient)); |
- ASSERT(!scratch.is(left)); |
- ASSERT(!scratch.is(right)); |
- ASSERT(!scratch.is(result)); |
+ // For r3 = r1 % r2; we can have the following ARM code |
+ // sdiv r3, r1, r2 |
+ // mls r3, r3, r2, r1 |
- Label done, vfp_modulo, both_positive, right_negative; |
+ __ sdiv(result, left, right); |
+ __ mls(result, result, right, left); |
+ __ cmp(result, Operand(0)); |
+ __ b(ne, &done); |
- // Check for x % 0. |
- if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
- __ cmp(right, Operand(0)); |
- DeoptimizeIf(eq, instr->environment()); |
- } |
+ 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(); |
- __ Move(result, left); |
+ ASSERT(!dividend.is(divisor)); |
+ ASSERT(!dividend.is(quotient)); |
+ ASSERT(!divisor.is(quotient)); |
+ ASSERT(!scratch.is(left)); |
+ ASSERT(!scratch.is(right)); |
+ ASSERT(!scratch.is(result)); |
- // (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); |
+ Label done, vfp_modulo, both_positive, right_negative; |
- __ cmp(left, Operand(right)); |
- __ b(lt, &done); |
+ // Check for x % 0. |
+ if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
+ __ cmp(right, Operand(0)); |
+ DeoptimizeIf(eq, instr->environment()); |
+ } |
- // 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); |
+ __ Move(result, left); |
- __ bind(&right_negative); |
- // Negate right. The sign of the divisor does not matter. |
- __ rsb(right, right, Operand(0)); |
+ // (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(&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); |
+ __ cmp(left, Operand(right)); |
__ 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; |
+ // 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); |
- __ vcvt_f64_s32(dividend, dividend.low()); |
- __ vcvt_f64_s32(divisor, divisor.low()); |
+ __ bind(&right_negative); |
+ // Negate right. The sign of the divisor does not matter. |
+ __ rsb(right, right, Operand(0)); |
- // 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()); |
+ __ 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); |
+ } |
- // 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()); |
+ __ 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; |
- 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); |
+ __ 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); |
} |