| Index: src/arm/macro-assembler-arm.cc
|
| ===================================================================
|
| --- src/arm/macro-assembler-arm.cc (revision 7157)
|
| +++ src/arm/macro-assembler-arm.cc (working copy)
|
| @@ -2032,6 +2032,121 @@
|
| }
|
|
|
|
|
| +void MacroAssembler::EmitOutOfInt32RangeTruncate(Register result,
|
| + Register input_high,
|
| + Register input_low,
|
| + Register scratch) {
|
| + Label done, normal_exponent, restore_sign;
|
| +
|
| + // Extract the biased exponent in result.
|
| + Ubfx(result,
|
| + input_high,
|
| + HeapNumber::kExponentShift,
|
| + HeapNumber::kExponentBits);
|
| +
|
| + // Check for Infinity and NaNs, which should return 0.
|
| + cmp(result, Operand(HeapNumber::kExponentMask));
|
| + mov(result, Operand(0), LeaveCC, eq);
|
| + b(eq, &done);
|
| +
|
| + // Express exponent as delta to (number of mantissa bits + 31).
|
| + sub(result,
|
| + result,
|
| + Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits + 31),
|
| + SetCC);
|
| +
|
| + // If the delta is strictly positive, all bits would be shifted away,
|
| + // which means that we can return 0.
|
| + b(le, &normal_exponent);
|
| + mov(result, Operand(0));
|
| + b(&done);
|
| +
|
| + bind(&normal_exponent);
|
| + const int kShiftBase = HeapNumber::kNonMantissaBitsInTopWord - 1;
|
| + // Calculate shift.
|
| + add(scratch, result, Operand(kShiftBase + HeapNumber::kMantissaBits), SetCC);
|
| +
|
| + // Save the sign.
|
| + Register sign = result;
|
| + result = no_reg;
|
| + and_(sign, input_high, Operand(HeapNumber::kSignMask));
|
| +
|
| + // Set the implicit 1 before the mantissa part in input_high.
|
| + orr(input_high,
|
| + input_high,
|
| + Operand(1 << HeapNumber::kMantissaBitsInTopWord));
|
| + // Shift the mantissa bits to the correct position.
|
| + // We don't need to clear non-mantissa bits as they will be shifted away.
|
| + // If they weren't, it would mean that the answer is in the 32bit range.
|
| + mov(input_high, Operand(input_high, LSL, scratch));
|
| +
|
| + // Replace the shifted bits with bits from the lower mantissa word.
|
| + Label pos_shift, shift_done;
|
| + rsb(scratch, scratch, Operand(32), SetCC);
|
| + b(&pos_shift, ge);
|
| +
|
| + // Negate scratch.
|
| + rsb(scratch, scratch, Operand(0));
|
| + mov(input_low, Operand(input_low, LSL, scratch));
|
| + b(&shift_done);
|
| +
|
| + bind(&pos_shift);
|
| + mov(input_low, Operand(input_low, LSR, scratch));
|
| +
|
| + bind(&shift_done);
|
| + orr(input_high, input_high, Operand(input_low));
|
| + // Restore sign if necessary.
|
| + cmp(sign, Operand(0));
|
| + result = sign;
|
| + sign = no_reg;
|
| + rsb(result, input_high, Operand(0), LeaveCC, ne);
|
| + mov(result, input_high, LeaveCC, eq);
|
| + bind(&done);
|
| +}
|
| +
|
| +
|
| +void MacroAssembler::EmitECMATruncate(Register result,
|
| + DwVfpRegister double_input,
|
| + SwVfpRegister single_scratch,
|
| + Register scratch,
|
| + Register input_high,
|
| + Register input_low) {
|
| + CpuFeatures::Scope scope(VFP3);
|
| + ASSERT(!input_high.is(result));
|
| + ASSERT(!input_low.is(result));
|
| + ASSERT(!input_low.is(input_high));
|
| + ASSERT(!scratch.is(result) &&
|
| + !scratch.is(input_high) &&
|
| + !scratch.is(input_low));
|
| + ASSERT(!single_scratch.is(double_input.low()) &&
|
| + !single_scratch.is(double_input.high()));
|
| +
|
| + Label done;
|
| +
|
| + // Clear cumulative exception flags.
|
| + ClearFPSCRBits(kVFPExceptionMask, scratch);
|
| + // Try a conversion to a signed integer.
|
| + vcvt_s32_f64(single_scratch, double_input);
|
| + vmov(result, single_scratch);
|
| + // Retrieve he FPSCR.
|
| + vmrs(scratch);
|
| + // Check for overflow and NaNs.
|
| + tst(scratch, Operand(kVFPOverflowExceptionBit |
|
| + kVFPUnderflowExceptionBit |
|
| + kVFPInvalidOpExceptionBit));
|
| + // If we had no exceptions we are done.
|
| + b(eq, &done);
|
| +
|
| + // Load the double value and perform a manual truncation.
|
| + vmov(input_low, input_high, double_input);
|
| + EmitOutOfInt32RangeTruncate(result,
|
| + input_high,
|
| + input_low,
|
| + scratch);
|
| + bind(&done);
|
| +}
|
| +
|
| +
|
| void MacroAssembler::GetLeastBitsFromSmi(Register dst,
|
| Register src,
|
| int num_least_bits) {
|
|
|