| Index: src/ia32/macro-assembler-ia32.cc
|
| diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
|
| index be210aaef1fdd873362c4e8dff9932e98a8017db..df6b9b7ae4e4b4644759ef9e75145de0a70a7ec4 100644
|
| --- a/src/ia32/macro-assembler-ia32.cc
|
| +++ b/src/ia32/macro-assembler-ia32.cc
|
| @@ -581,12 +581,153 @@ void MacroAssembler::DebugBreak() {
|
| }
|
|
|
|
|
| +void MacroAssembler::Cvtsi2ss(XMMRegister dst, const Operand& src) {
|
| + xorps(dst, dst);
|
| + cvtsi2ss(dst, src);
|
| +}
|
| +
|
| +
|
| void MacroAssembler::Cvtsi2sd(XMMRegister dst, const Operand& src) {
|
| xorps(dst, dst);
|
| cvtsi2sd(dst, src);
|
| }
|
|
|
|
|
| +void MacroAssembler::Roundss(XMMRegister dst, XMMRegister src, Register tmp,
|
| + XMMRegister xtmp, RoundingMode mode) {
|
| + if (CpuFeatures::IsSupported(SSE4_1)) {
|
| + CpuFeatureScope sse_scope(this, SSE4_1);
|
| + roundss(dst, src, mode);
|
| + } else {
|
| + // We have to store the original rounding mode to restore it later.
|
| + {
|
| + sub(esp, Immediate(kPointerSize * 2));
|
| + stmxcsr(Operand(esp, 0));
|
| + mov(tmp, Operand(esp, 0));
|
| + and_(tmp, Immediate(0xffff9fff));
|
| + or_(tmp, Immediate(mode << 13));
|
| + mov(Operand(esp, kPointerSize), tmp);
|
| + ldmxcsr(Operand(esp, kPointerSize));
|
| + }
|
| +
|
| + // Do rounding by conversion to int.
|
| + cvtss2si(tmp, src);
|
| +
|
| + Label out_of_range;
|
| + Label done;
|
| + // Check whether the input is within int32 range.
|
| + cmp(tmp, Immediate(1));
|
| + j(overflow, &out_of_range);
|
| + // Saving the sign bit.
|
| + // Initialize xtmp with 0x80000000.
|
| + pcmpeqd(xtmp, xtmp);
|
| + pslld(xtmp, 31);
|
| + andps(xtmp, src);
|
| + // If the conversion results in INT_MIN, then the input is outside
|
| + // int range, and due to the limited precision of float32 this means
|
| + // that the input must have been an integer already. We are therefore
|
| + // done already.
|
| + cvtsi2ss(dst, tmp);
|
| + // Restore the sign bit.
|
| + orps(dst, xtmp);
|
| +
|
| + if (!dst.is(src)) {
|
| + jmp(&done);
|
| + }
|
| +
|
| + bind(&out_of_range);
|
| + if (!dst.is(src)) {
|
| + movss(dst, src);
|
| + }
|
| +
|
| + bind(&done);
|
| + // Restore the original rounding mode.
|
| + ldmxcsr(Operand(esp, 0));
|
| + add(esp, Immediate(kPointerSize * 2));
|
| + }
|
| +}
|
| +
|
| +
|
| +void MacroAssembler::Roundsd(XMMRegister dst, XMMRegister src, Register tmp,
|
| + XMMRegister xtmp, RoundingMode mode) {
|
| + if (CpuFeatures::IsSupported(SSE4_1)) {
|
| + CpuFeatureScope sse_scope(this, SSE4_1);
|
| + roundsd(dst, src, mode);
|
| + } else {
|
| + // We have to store the original rounding mode to restore it later.
|
| + {
|
| + sub(esp, Immediate(kPointerSize * 2));
|
| + stmxcsr(Operand(esp, 0));
|
| + mov(tmp, Operand(esp, 0));
|
| + and_(tmp, Immediate(0xffff9fff));
|
| + or_(tmp, Immediate(mode << 13));
|
| + mov(Operand(esp, kPointerSize), tmp);
|
| + ldmxcsr(Operand(esp, kPointerSize));
|
| + }
|
| +
|
| + // Convert the input to int32.
|
| + cvtsd2si(tmp, src);
|
| +
|
| + Label out_of_range;
|
| + Label done;
|
| + // Check whether the input is within int32 range.
|
| + cmp(tmp, Immediate(1));
|
| + j(overflow, &out_of_range);
|
| + // Saving the sign bit.
|
| + // Initialize xtmp with 0x8000000000000000.
|
| + pcmpeqd(xtmp, xtmp);
|
| + psllq(xtmp, 63);
|
| + andpd(xtmp, src);
|
| + // The input is within int32 range. We achieve rounding by converting
|
| + // back to float.
|
| + Cvtsi2sd(dst, tmp);
|
| + // Restore the sign bit.
|
| + orpd(dst, xtmp);
|
| +
|
| + jmp(&done);
|
| + bind(&out_of_range);
|
| + if (!dst.is(src)) {
|
| + movsd(dst, src);
|
| + }
|
| + // If the input is outside [-2^52, 2^52], then the result = input.
|
| + int64_t offset = 1;
|
| + offset <<= 52;
|
| + Move(xtmp, static_cast<double>(offset));
|
| +
|
| + ucomisd(xtmp, src);
|
| +
|
| + j(below_equal, &done);
|
| +
|
| + Move(xtmp, static_cast<double>(-offset));
|
| +
|
| + ucomisd(xtmp, src);
|
| + j(above_equal, &done);
|
| +
|
| + // Positive number have to be handled differently than negative numbers.
|
| + xorpd(xtmp, xtmp);
|
| + ucomisd(xtmp, src);
|
| +
|
| + Move(xtmp, static_cast<double>(offset));
|
| +
|
| + Label below_zero;
|
| + j(above, &below_zero);
|
| +
|
| + addsd(dst, xtmp);
|
| + subsd(dst, xtmp);
|
| + jmp(&done);
|
| +
|
| + bind(&below_zero);
|
| + subsd(dst, xtmp);
|
| + addsd(dst, xtmp);
|
| +
|
| + bind(&done);
|
| + // Restore the original rounding mode.
|
| + ldmxcsr(Operand(esp, 0));
|
| + add(esp, Immediate(kPointerSize * 2));
|
| + }
|
| +}
|
| +
|
| +
|
| bool MacroAssembler::IsUnsafeImmediate(const Immediate& x) {
|
| static const int kMaxImmediateBits = 17;
|
| if (!RelocInfo::IsNone(x.rmode_)) return false;
|
|
|