Chromium Code Reviews| Index: src/arm/code-stubs-arm.cc |
| =================================================================== |
| --- src/arm/code-stubs-arm.cc (revision 13153) |
| +++ src/arm/code-stubs-arm.cc (working copy) |
| @@ -2441,33 +2441,112 @@ |
| // We fall through here if we multiplied a negative number with 0, because |
| // that would mean we should produce -0. |
| break; |
| - case Token::DIV: |
| + case Token::DIV: { |
|
danno
2012/12/20 16:25:38
nit: indentation
|
| + Label div_with_sdiv; |
| + |
| + // Check for 0 divisor. |
| + __ cmp(right, Operand(0)); |
| + __ b(eq, ¬_smi_result); |
| + |
| // Check for power of two on the right hand side. |
| - __ JumpIfNotPowerOfTwoOrZero(right, scratch1, ¬_smi_result); |
| - // Check for positive and no remainder (scratch1 contains right - 1). |
| - __ orr(scratch2, scratch1, Operand(0x80000000u)); |
| - __ tst(left, scratch2); |
| - __ b(ne, ¬_smi_result); |
| + __ sub(scratch1, right, Operand(1)); |
| + __ tst(scratch1, right); |
| + if (CpuFeatures::IsSupported(SUDIV)) { |
| + __ b(ne, &div_with_sdiv); |
| + // Check for no remainder. |
| + __ tst(left, scratch1); |
| + __ b(ne, ¬_smi_result); |
| + // Check for positive left hand side. |
| + __ cmp(left, Operand(0)); |
| + __ b(mi, &div_with_sdiv); |
| + } else { |
| + __ b(ne, ¬_smi_result); |
| + // Check for positive and no remainder. |
| + __ orr(scratch2, scratch1, Operand(0x80000000u)); |
| + __ tst(left, scratch2); |
| + __ b(ne, ¬_smi_result); |
| + } |
| // Perform division by shifting. |
| __ CountLeadingZeros(scratch1, scratch1, scratch2); |
| __ rsb(scratch1, scratch1, Operand(31)); |
| __ mov(right, Operand(left, LSR, scratch1)); |
| __ Ret(); |
| + |
| + if (CpuFeatures::IsSupported(SUDIV)) { |
| + Label result_not_zero; |
| + |
| + __ bind(&div_with_sdiv); |
| + // Do division. |
| + __ sdiv(scratch1, left, right); |
| + // Check that the remainder is zero. |
| + __ mls(scratch2, scratch1, right, left); |
| + __ cmp(scratch2, Operand(0)); |
| + __ b(ne, ¬_smi_result); |
| + // Check for negative zero result. |
| + __ cmp(scratch1, Operand(0)); |
| + __ b(ne, &result_not_zero); |
| + __ cmp(right, Operand(0)); |
| + __ b(lt, ¬_smi_result); |
| + __ bind(&result_not_zero); |
| + // Check for the corner case of dividing the most negative smi by -1. |
| + __ cmp(scratch1, Operand(0x40000000)); |
| + __ b(eq, ¬_smi_result); |
| + // Tag and return the result. |
| + __ SmiTag(right, scratch1); |
| + __ Ret(); |
| + } |
| break; |
| - case Token::MOD: |
| - // Check for two positive smis. |
| - __ orr(scratch1, left, Operand(right)); |
| - __ tst(scratch1, Operand(0x80000000u | kSmiTagMask)); |
| - __ b(ne, ¬_smi_result); |
| + } |
| + case Token::MOD: { |
| + Label modulo_with_sdiv; |
| - // Check for power of two on the right hand side. |
| - __ JumpIfNotPowerOfTwoOrZero(right, scratch1, ¬_smi_result); |
| + if (CpuFeatures::IsSupported(SUDIV)) { |
| + // Check for x % 0. |
| + __ cmp(right, Operand(0)); |
| + __ b(eq, ¬_smi_result); |
| - // Perform modulus by masking. |
| + // Check for two positive smis. |
| + __ orr(scratch1, left, Operand(right)); |
| + __ tst(scratch1, Operand(0x80000000u)); |
| + __ b(ne, &modulo_with_sdiv); |
| + |
| + // Check for power of two on the right hand side. |
| + __ sub(scratch1, right, Operand(1)); |
| + __ tst(scratch1, right); |
| + __ b(ne, &modulo_with_sdiv); |
| + } else { |
| + // Check for two positive smis. |
| + __ orr(scratch1, left, Operand(right)); |
| + __ tst(scratch1, Operand(0x80000000u)); |
| + __ b(ne, ¬_smi_result); |
| + |
| + // Check for power of two on the right hand side. |
| + __ JumpIfNotPowerOfTwoOrZero(right, scratch1, ¬_smi_result); |
| + } |
| + |
| + // Perform modulus by masking (scratch1 contains right - 1). |
| __ and_(right, left, Operand(scratch1)); |
| __ Ret(); |
| + |
| + if (CpuFeatures::IsSupported(SUDIV)) { |
| + __ bind(&modulo_with_sdiv); |
| + __ mov(scratch2, right); |
| + // Perform modulus with sdiv and mls. |
| + __ sdiv(scratch1, left, right); |
| + __ mls(right, scratch1, right, left); |
| + // Return if the result is not 0. |
| + __ cmp(right, Operand(0)); |
| + __ Ret(ne); |
| + // The result is 0, check for -0 case. |
| + __ cmp(left, Operand(0)); |
| + __ Ret(pl); |
| + // This is a -0 case, restore the value of right. |
| + __ mov(right, scratch2); |
| + // We fall through here to not_smi_result to produce -0. |
| + } |
| break; |
| + } |
| case Token::BIT_OR: |
| __ orr(right, left, Operand(right)); |
| __ Ret(); |