Index: src/arm/macro-assembler-arm.cc |
=================================================================== |
--- src/arm/macro-assembler-arm.cc (revision 13783) |
+++ src/arm/macro-assembler-arm.cc (working copy) |
@@ -2525,74 +2525,76 @@ |
} |
-void MacroAssembler::TryFastDoubleToInt32(Register result, |
- DwVfpRegister double_input, |
- DwVfpRegister double_scratch, |
- Label* done) { |
+void MacroAssembler::TestDoubleIsInt32(DwVfpRegister double_input, |
+ DwVfpRegister double_scratch) { |
ASSERT(!double_input.is(double_scratch)); |
+ ASSERT(CpuFeatures::IsSupported(VFP2)); |
+ CpuFeatures::Scope scope(VFP2); |
vcvt_s32_f64(double_scratch.low(), double_input); |
- vmov(result, double_scratch.low()); |
vcvt_f64_s32(double_scratch, double_scratch.low()); |
VFPCompareAndSetFlags(double_input, double_scratch); |
- b(eq, done); |
} |
-void MacroAssembler::EmitVFPTruncate(VFPRoundingMode rounding_mode, |
- Register result, |
- DwVfpRegister double_input, |
- Register scratch, |
- DwVfpRegister double_scratch, |
- CheckForInexactConversion check_inexact) { |
- ASSERT(!result.is(scratch)); |
+void MacroAssembler::TryDoubleToInt32Exact(Register result, |
+ DwVfpRegister double_input, |
+ DwVfpRegister double_scratch) { |
ASSERT(!double_input.is(double_scratch)); |
- |
ASSERT(CpuFeatures::IsSupported(VFP2)); |
CpuFeatures::Scope scope(VFP2); |
- Register prev_fpscr = result; |
- Label done; |
- // Test for values that can be exactly represented as a signed 32-bit integer. |
- TryFastDoubleToInt32(result, double_input, double_scratch, &done); |
+ vcvt_s32_f64(double_scratch.low(), double_input); |
+ vmov(result, double_scratch.low()); |
+ vcvt_f64_s32(double_scratch, double_scratch.low()); |
+ VFPCompareAndSetFlags(double_input, double_scratch); |
+} |
- // Convert to integer, respecting rounding mode. |
- int32_t check_inexact_conversion = |
- (check_inexact == kCheckForInexactConversion) ? kVFPInexactExceptionBit : 0; |
- // Set custom FPCSR: |
- // - Set rounding mode. |
- // - Clear vfp cumulative exception flags. |
- // - Make sure Flush-to-zero mode control bit is unset. |
- vmrs(prev_fpscr); |
- bic(scratch, |
- prev_fpscr, |
- Operand(kVFPExceptionMask | |
- check_inexact_conversion | |
- kVFPRoundingModeMask | |
- kVFPFlushToZeroMask)); |
- // 'Round To Nearest' is encoded by 0b00 so no bits need to be set. |
- if (rounding_mode != kRoundToNearest) { |
- orr(scratch, scratch, Operand(rounding_mode)); |
- } |
- vmsr(scratch); |
+void MacroAssembler::TryInt32Floor(Register result, |
+ DwVfpRegister double_input, |
+ Register input_high, |
+ DwVfpRegister double_scratch, |
+ Label* done, |
+ Label* exact) { |
+ ASSERT(!result.is(input_high)); |
+ ASSERT(!double_input.is(double_scratch)); |
+ ASSERT(CpuFeatures::IsSupported(VFP2)); |
+ CpuFeatures::Scope scope(VFP2); |
+ Label negative, exception; |
- // Convert the argument to an integer. |
- vcvt_s32_f64(double_scratch.low(), |
- double_input, |
- (rounding_mode == kRoundToZero) ? kDefaultRoundToZero |
- : kFPSCRRounding); |
+ // Test for NaN and infinities. |
+ Sbfx(result, input_high, |
+ HeapNumber::kExponentShift, HeapNumber::kExponentBits); |
+ cmp(result, Operand(-1)); |
+ b(eq, &exception); |
+ // Test for values that can be exactly represented as a |
+ // signed 32-bit integer. |
+ TryDoubleToInt32Exact(result, double_input, double_scratch); |
+ // If exact, return (result already fetched). |
+ b(eq, exact); |
+ cmp(input_high, Operand::Zero()); |
+ b(mi, &negative); |
- // Retrieve FPSCR. |
- vmrs(scratch); |
- // Restore FPSCR. |
- vmsr(prev_fpscr); |
- // Move the converted value into the result register. |
- vmov(result, double_scratch.low()); |
- // Check for vfp exceptions. |
- tst(scratch, Operand(kVFPExceptionMask | check_inexact_conversion)); |
+ // Input is in ]+0, +inf[. |
+ // If result equals 0x7fffffff input was out of range or |
+ // in ]0x7fffffff, 0x80000000[. We ignore this last case which |
+ // could fits into an int32, that means we always think input was |
+ // out of range and always go to exception. |
+ // If result < 0x7fffffff, go to done, result fetched. |
+ cmn(result, Operand(1)); |
+ b(mi, &exception); |
+ b(done); |
- bind(&done); |
+ // Input is in ]-inf, -0[. |
+ // If x is a non integer negative number, |
+ // floor(x) <=> round_to_zero(x) - 1. |
+ bind(&negative); |
+ sub(result, result, Operand(1), SetCC); |
+ // If result is still negative, go to done, result fetched. |
+ // Else, we had an overflow and we fall through exception. |
+ b(mi, done); |
+ bind(&exception); |
} |
@@ -2687,33 +2689,25 @@ |
Label done; |
// Test if the value can be exactly represented as a signed integer. |
- vcvt_s32_f64(double_scratch.low(), double_input); |
- vmov(result, double_scratch.low()); |
- vcvt_f64_s32(double_scratch, double_scratch.low()); |
- // Note: this comparison is cheaper than reading the FPSCR exception bits. |
- VFPCompareAndSetFlags(double_input, double_scratch); |
+ TryDoubleToInt32Exact(result, double_input, double_scratch); |
b(eq, &done); |
// Check the exception flags. If they are not set, we are done. |
// If they are set, it could be because of the conversion above, or because |
// they were set before this code. |
vmrs(scratch); |
- tst(scratch, Operand(kVFPOverflowExceptionBit | |
- kVFPUnderflowExceptionBit | |
- kVFPInvalidOpExceptionBit)); |
+ tst(scratch, Operand(kVFPInvalidOpExceptionBit)); |
b(eq, &done); |
// Clear cumulative exception flags. |
- bic(scratch, scratch, Operand(kVFPExceptionMask)); |
+ bic(scratch, scratch, Operand(kVFPInvalidOpExceptionBit)); |
vmsr(scratch); |
// Try a conversion to a signed integer. |
vcvt_s32_f64(double_scratch.low(), double_input); |
// Retrieve the FPSCR. |
vmrs(scratch); |
- // Check for overflow and NaNs. |
- tst(scratch, Operand(kVFPOverflowExceptionBit | |
- kVFPUnderflowExceptionBit | |
- kVFPInvalidOpExceptionBit)); |
+ // Check for invalid conversions (out of range and NaNs). |
+ tst(scratch, Operand(kVFPInvalidOpExceptionBit)); |
// If we had no exceptions we are done. |
b(eq, &done); |