commit 5dbd7fb9849c51326867794fcf3bfd0bc55b8640
parent dae7db185717d82df2e2bc88f51516a521785bc3
Author: André Bargull <andre.bargull@gmail.com>
Date: Fri, 17 Oct 2025 11:25:45 +0000
Bug 1994190 - Part 4: Simplify rounding instructions for mips64. r=spidermonkey-reviewers,iain
Differential Revision: https://phabricator.services.mozilla.com/D268549
Diffstat:
4 files changed, 236 insertions(+), 220 deletions(-)
diff --git a/js/src/jit/mips-shared/Assembler-mips-shared.cpp b/js/src/jit/mips-shared/Assembler-mips-shared.cpp
@@ -1350,6 +1350,13 @@ BufferOffset AssemblerMIPSShared::as_ceilws(FloatRegister fd,
InstReg(op_cop1, rs_s, zero, fs, fd, ff_ceil_w_fmt).encode());
}
+BufferOffset AssemblerMIPSShared::as_ceills(FloatRegister fd,
+ FloatRegister fs) {
+ spew("ceil.l.s%3s,%3s", fd.name(), fs.name());
+ return writeInst(
+ InstReg(op_cop1, rs_s, zero, fs, fd, ff_ceil_l_fmt).encode());
+}
+
BufferOffset AssemblerMIPSShared::as_floorws(FloatRegister fd,
FloatRegister fs) {
spew("floor.w.s%3s,%3s", fd.name(), fs.name());
@@ -1357,6 +1364,13 @@ BufferOffset AssemblerMIPSShared::as_floorws(FloatRegister fd,
InstReg(op_cop1, rs_s, zero, fs, fd, ff_floor_w_fmt).encode());
}
+BufferOffset AssemblerMIPSShared::as_floorls(FloatRegister fd,
+ FloatRegister fs) {
+ spew("floor.l.s%3s,%3s", fd.name(), fs.name());
+ return writeInst(
+ InstReg(op_cop1, rs_s, zero, fs, fd, ff_floor_l_fmt).encode());
+}
+
BufferOffset AssemblerMIPSShared::as_roundws(FloatRegister fd,
FloatRegister fs) {
spew("round.w.s%3s,%3s", fd.name(), fs.name());
@@ -1364,6 +1378,13 @@ BufferOffset AssemblerMIPSShared::as_roundws(FloatRegister fd,
InstReg(op_cop1, rs_s, zero, fs, fd, ff_round_w_fmt).encode());
}
+BufferOffset AssemblerMIPSShared::as_roundls(FloatRegister fd,
+ FloatRegister fs) {
+ spew("round.l.s%3s,%3s", fd.name(), fs.name());
+ return writeInst(
+ InstReg(op_cop1, rs_s, zero, fs, fd, ff_round_l_fmt).encode());
+}
+
BufferOffset AssemblerMIPSShared::as_truncws(FloatRegister fd,
FloatRegister fs) {
spew("trunc.w.s%3s,%3s", fd.name(), fs.name());
@@ -1386,6 +1407,13 @@ BufferOffset AssemblerMIPSShared::as_ceilwd(FloatRegister fd,
InstReg(op_cop1, rs_d, zero, fs, fd, ff_ceil_w_fmt).encode());
}
+BufferOffset AssemblerMIPSShared::as_ceilld(FloatRegister fd,
+ FloatRegister fs) {
+ spew("ceil.l.d%3s,%3s", fd.name(), fs.name());
+ return writeInst(
+ InstReg(op_cop1, rs_d, zero, fs, fd, ff_ceil_l_fmt).encode());
+}
+
BufferOffset AssemblerMIPSShared::as_floorwd(FloatRegister fd,
FloatRegister fs) {
spew("floor.w.d%3s,%3s", fd.name(), fs.name());
@@ -1393,6 +1421,13 @@ BufferOffset AssemblerMIPSShared::as_floorwd(FloatRegister fd,
InstReg(op_cop1, rs_d, zero, fs, fd, ff_floor_w_fmt).encode());
}
+BufferOffset AssemblerMIPSShared::as_floorld(FloatRegister fd,
+ FloatRegister fs) {
+ spew("floor.l.d%3s,%3s", fd.name(), fs.name());
+ return writeInst(
+ InstReg(op_cop1, rs_d, zero, fs, fd, ff_floor_l_fmt).encode());
+}
+
BufferOffset AssemblerMIPSShared::as_roundwd(FloatRegister fd,
FloatRegister fs) {
spew("round.w.d%3s,%3s", fd.name(), fs.name());
@@ -1400,6 +1435,13 @@ BufferOffset AssemblerMIPSShared::as_roundwd(FloatRegister fd,
InstReg(op_cop1, rs_d, zero, fs, fd, ff_round_w_fmt).encode());
}
+BufferOffset AssemblerMIPSShared::as_roundld(FloatRegister fd,
+ FloatRegister fs) {
+ spew("round.l.d%3s,%3s", fd.name(), fs.name());
+ return writeInst(
+ InstReg(op_cop1, rs_d, zero, fs, fd, ff_round_l_fmt).encode());
+}
+
BufferOffset AssemblerMIPSShared::as_truncwd(FloatRegister fd,
FloatRegister fs) {
spew("trunc.w.d%3s,%3s", fd.name(), fs.name());
diff --git a/js/src/jit/mips-shared/Assembler-mips-shared.h b/js/src/jit/mips-shared/Assembler-mips-shared.h
@@ -1146,14 +1146,20 @@ class AssemblerMIPSShared : public AssemblerShared {
public:
// FP convert instructions
BufferOffset as_ceilws(FloatRegister fd, FloatRegister fs);
+ BufferOffset as_ceills(FloatRegister fd, FloatRegister fs);
BufferOffset as_floorws(FloatRegister fd, FloatRegister fs);
+ BufferOffset as_floorls(FloatRegister fd, FloatRegister fs);
BufferOffset as_roundws(FloatRegister fd, FloatRegister fs);
+ BufferOffset as_roundls(FloatRegister fd, FloatRegister fs);
BufferOffset as_truncws(FloatRegister fd, FloatRegister fs);
BufferOffset as_truncls(FloatRegister fd, FloatRegister fs);
BufferOffset as_ceilwd(FloatRegister fd, FloatRegister fs);
+ BufferOffset as_ceilld(FloatRegister fd, FloatRegister fs);
BufferOffset as_floorwd(FloatRegister fd, FloatRegister fs);
+ BufferOffset as_floorld(FloatRegister fd, FloatRegister fs);
BufferOffset as_roundwd(FloatRegister fd, FloatRegister fs);
+ BufferOffset as_roundld(FloatRegister fd, FloatRegister fs);
BufferOffset as_truncwd(FloatRegister fd, FloatRegister fs);
BufferOffset as_truncld(FloatRegister fd, FloatRegister fs);
diff --git a/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp b/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp
@@ -3163,301 +3163,274 @@ void MacroAssembler::speculationBarrier() { MOZ_CRASH(); }
void MacroAssembler::floorFloat32ToInt32(FloatRegister src, Register dest,
Label* fail) {
ScratchFloat32Scope fscratch(*this);
- UseScratchRegisterScope temps(*this);
- Register scratch2 = temps.Acquire();
-
- Label skipCheck, done;
-
- // If Nan, 0 or -0 check for bailout
- loadConstantFloat32(0.0f, fscratch);
- ma_bc1s(src, fscratch, &skipCheck, Assembler::DoubleNotEqual, ShortJump);
-
- // If binary value is not zero, it is NaN or -0, so we bail.
- moveFromDoubleLo(src, scratch2);
- branch32(Assembler::NotEqual, scratch2, Imm32(0), fail);
- // Input was zero, so return zero.
- move32(Imm32(0), dest);
- ma_b(&done, ShortJump);
+ // Round toward negative infinity.
+ as_floorls(fscratch, src);
+ moveFromDouble(fscratch, dest);
- bind(&skipCheck);
- as_floorws(fscratch, src);
- moveFromDoubleLo(fscratch, dest);
+ // Sign extend lower 32 bits to test if the result isn't an Int32.
+ {
+ UseScratchRegisterScope temps(*this);
+ Register scratch = temps.Acquire();
- branch32(Assembler::Equal, dest, Imm32(INT_MIN), fail);
- branch32(Assembler::Equal, dest, Imm32(INT_MAX), fail);
+ move32SignExtendToPtr(dest, scratch);
+ branchPtr(Assembler::NotEqual, dest, scratch, fail);
+ }
- bind(&done);
+ // We have to check for -0 and NaN when the result is zero.
+ Label notZero;
+ ma_b(dest, zero, ¬Zero, Assembler::NotEqual, ShortJump);
+ {
+ // If any of the two most significant bits is set, |src| is -0 or NaN.
+ moveFromFloat32(src, dest);
+ ma_srl(dest, dest, Imm32(30));
+ branch32(Assembler::NotEqual, dest, zero, fail);
+ }
+ bind(¬Zero);
}
void MacroAssembler::floorDoubleToInt32(FloatRegister src, Register dest,
Label* fail) {
ScratchDoubleScope dscratch(*this);
- UseScratchRegisterScope temps(*this);
- Register scratch2 = temps.Acquire();
-
- Label skipCheck, done;
-
- // If Nan, 0 or -0 check for bailout
- loadConstantDouble(0.0, dscratch);
- ma_bc1d(src, dscratch, &skipCheck, Assembler::DoubleNotEqual, ShortJump);
- // If high part is not zero, it is NaN or -0, so we bail.
- moveFromDoubleHi(src, scratch2);
- branch32(Assembler::NotEqual, scratch2, Imm32(0), fail);
+ // Round toward negative infinity.
+ as_floorld(dscratch, src);
+ moveFromDouble(dscratch, dest);
- // Input was zero, so return zero.
- move32(Imm32(0), dest);
- ma_b(&done, ShortJump);
-
- bind(&skipCheck);
- as_floorwd(dscratch, src);
- moveFromDoubleLo(dscratch, dest);
+ // Sign extend lower 32 bits to test if the result isn't an Int32.
+ {
+ UseScratchRegisterScope temps(*this);
+ Register scratch = temps.Acquire();
- branch32(Assembler::Equal, dest, Imm32(INT_MIN), fail);
- branch32(Assembler::Equal, dest, Imm32(INT_MAX), fail);
+ move32SignExtendToPtr(dest, scratch);
+ branchPtr(Assembler::NotEqual, dest, scratch, fail);
+ }
- bind(&done);
+ // We have to check for -0 and NaN when the result is zero.
+ Label notZero;
+ ma_b(dest, zero, ¬Zero, Assembler::NotEqual, ShortJump);
+ {
+ // If any of the two most significant bits is set, |src| is -0 or NaN.
+ moveFromDouble(src, dest);
+ ma_dsrl(dest, dest, Imm32(62));
+ branchPtr(Assembler::NotEqual, dest, zero, fail);
+ }
+ bind(¬Zero);
}
void MacroAssembler::ceilFloat32ToInt32(FloatRegister src, Register dest,
Label* fail) {
ScratchFloat32Scope fscratch(*this);
- UseScratchRegisterScope temps(*this);
- Register scratch2 = temps.Acquire();
-
- Label performCeil, done;
-
- // If x < -1 or x > 0 then perform ceil.
- loadConstantFloat32(0.0f, fscratch);
- branchFloat(Assembler::DoubleGreaterThan, src, fscratch, &performCeil);
- loadConstantFloat32(-1.0f, fscratch);
- branchFloat(Assembler::DoubleLessThanOrEqual, src, fscratch, &performCeil);
- // If binary value is not zero, the input was not 0, so we bail.
- moveFromFloat32(src, scratch2);
- branch32(Assembler::NotEqual, scratch2, Imm32(0), fail);
+ // Round toward positive infinity.
+ as_ceills(fscratch, src);
+ moveFromDouble(fscratch, dest);
- // Input was zero, so return zero.
- move32(Imm32(0), dest);
- ma_b(&done, ShortJump);
-
- bind(&performCeil);
- as_ceilws(fscratch, src);
- moveFromFloat32(fscratch, dest);
+ // Sign extend lower 32 bits to test if the result isn't an Int32.
+ {
+ UseScratchRegisterScope temps(*this);
+ Register scratch = temps.Acquire();
- branch32(Assembler::Equal, dest, Imm32(INT_MIN), fail);
- branch32(Assembler::Equal, dest, Imm32(INT_MAX), fail);
+ move32SignExtendToPtr(dest, scratch);
+ branchPtr(Assembler::NotEqual, dest, scratch, fail);
+ }
- bind(&done);
+ // We have to check for (-1, -0] and NaN when the result is zero.
+ Label notZero;
+ ma_b(dest, zero, ¬Zero, Assembler::NotEqual, ShortJump);
+ {
+ // If binary value is not zero, the input was not 0, so we bail.
+ moveFromFloat32(src, dest);
+ branch32(Assembler::NotEqual, dest, zero, fail);
+ }
+ bind(¬Zero);
}
void MacroAssembler::ceilDoubleToInt32(FloatRegister src, Register dest,
Label* fail) {
ScratchDoubleScope dscratch(*this);
- UseScratchRegisterScope temps(*this);
- Register scratch2 = temps.Acquire();
-
- Label performCeil, done;
- // If x < -1 or x > 0 then perform ceil.
- loadConstantDouble(0, dscratch);
- branchDouble(Assembler::DoubleGreaterThan, src, dscratch, &performCeil);
- loadConstantDouble(-1, dscratch);
- branchDouble(Assembler::DoubleLessThanOrEqual, src, dscratch, &performCeil);
+ // Round toward positive infinity.
+ as_ceilld(dscratch, src);
+ moveFromDouble(dscratch, dest);
- // If high part is not zero, the input was not 0, so we bail.
- moveFromDoubleHi(src, scratch2);
- branch32(Assembler::NotEqual, scratch2, Imm32(0), fail);
-
- // Input was zero, so return zero.
- move32(Imm32(0), dest);
- ma_b(&done, ShortJump);
-
- bind(&performCeil);
- as_ceilwd(dscratch, src);
- moveFromDoubleLo(dscratch, dest);
+ // Sign extend lower 32 bits to test if the result isn't an Int32.
+ {
+ UseScratchRegisterScope temps(*this);
+ Register scratch = temps.Acquire();
- branch32(Assembler::Equal, dest, Imm32(INT_MIN), fail);
- branch32(Assembler::Equal, dest, Imm32(INT_MAX), fail);
+ move32SignExtendToPtr(dest, scratch);
+ branchPtr(Assembler::NotEqual, dest, scratch, fail);
+ }
- bind(&done);
+ // We have to check for (-1, -0] and NaN when the result is zero.
+ Label notZero;
+ ma_b(dest, zero, ¬Zero, Assembler::NotEqual, ShortJump);
+ {
+ // If binary value is not zero, the input was not 0, so we bail.
+ moveFromDouble(src, dest);
+ branchPtr(Assembler::NotEqual, dest, zero, fail);
+ }
+ bind(¬Zero);
}
void MacroAssembler::roundFloat32ToInt32(FloatRegister src, Register dest,
FloatRegister temp, Label* fail) {
ScratchFloat32Scope fscratch(*this);
- UseScratchRegisterScope temps(*this);
- Register scratch2 = temps.Acquire();
- Label negative, end, skipCheck;
+ Label negative, end, performRound;
- // Load biggest number less than 0.5 in the temp register.
- loadConstantFloat32(GetBiggestNumberLessThan(0.5f), temp);
-
- // Branch to a slow path for negative inputs. Doesn't catch NaN or -0.
+ // Branch for negative inputs. Doesn't catch NaN or -0.
loadConstantFloat32(0.0f, fscratch);
ma_bc1s(src, fscratch, &negative, Assembler::DoubleLessThan, ShortJump);
- // If Nan, 0 or -0 check for bailout
- ma_bc1s(src, fscratch, &skipCheck, Assembler::DoubleNotEqual, ShortJump);
-
- // If binary value is not zero, it is NaN or -0, so we bail.
- moveFromFloat32(src, scratch2);
- branch32(Assembler::NotEqual, scratch2, Imm32(0), fail);
-
- // Input was zero, so return zero.
- move32(Imm32(0), dest);
- ma_b(&end, ShortJump);
-
- bind(&skipCheck);
- as_adds(fscratch, src, temp);
- as_floorws(fscratch, fscratch);
-
- moveFromFloat32(fscratch, dest);
-
- branch32(Assembler::Equal, dest, Imm32(INT_MAX), fail);
-
- jump(&end);
+ // If non-negative check for bailout.
+ ma_bc1s(src, fscratch, &performRound, Assembler::DoubleNotEqual, ShortJump);
+ {
+ // If binary value is not zero, it is NaN or -0, so we bail.
+ moveFromFloat32(src, dest);
+ branch32(Assembler::NotEqual, dest, zero, fail);
+ ma_b(&end, ShortJump);
+ }
// Input is negative, but isn't -0.
bind(&negative);
+ {
+ // Inputs in [-0.5, 0) are rounded to -0. Fail.
+ loadConstantFloat32(-0.5f, fscratch);
+ branchFloat(Assembler::DoubleGreaterThanOrEqual, src, fscratch, fail);
+ }
- // Inputs in ]-0.5; 0] need to be added 0.5, other negative inputs need to
- // be added the biggest double less than 0.5.
- Label loadJoin;
- loadConstantFloat32(-0.5f, fscratch);
- branchFloat(Assembler::DoubleLessThan, src, fscratch, &loadJoin);
- loadConstantFloat32(0.5f, temp);
- bind(&loadJoin);
-
- as_adds(temp, src, temp);
+ bind(&performRound);
+ {
+ // Load biggest number less than 0.5 in the temp register.
+ loadConstantFloat32(GetBiggestNumberLessThan(0.5f), temp);
- // If input + 0.5 >= 0, input is a negative number >= -0.5 and the
- // result is -0.
- branchFloat(Assembler::DoubleGreaterThanOrEqual, temp, fscratch, fail);
+ // Other inputs need the biggest float less than 0.5 added.
+ as_adds(fscratch, src, temp);
- // Truncate and round toward zero.
- // This is off-by-one for everything but integer-valued inputs.
- as_floorws(fscratch, temp);
- moveFromFloat32(fscratch, dest);
+ // Round toward negative infinity.
+ as_floorls(fscratch, fscratch);
+ moveFromDouble(fscratch, dest);
- // Need to test for both INT_MIN and INT_MAX:
- // If NAN2008=0, out-of-range (negative) values return INT_MAX.
- // If NAN2008=1, out-of-range negative values return INT_MIN.
- branch32(Assembler::Equal, dest, Imm32(INT_MIN), fail);
- branch32(Assembler::Equal, dest, Imm32(INT_MAX), fail);
+ // Sign extend lower 32 bits to test if the result isn't an Int32.
+ {
+ UseScratchRegisterScope temps(*this);
+ Register scratch = temps.Acquire();
+ move32SignExtendToPtr(dest, scratch);
+ branchPtr(Assembler::NotEqual, dest, scratch, fail);
+ }
+ }
bind(&end);
}
void MacroAssembler::roundDoubleToInt32(FloatRegister src, Register dest,
FloatRegister temp, Label* fail) {
ScratchDoubleScope dscratch(*this);
- UseScratchRegisterScope temps(*this);
- Register scratch2 = temps.Acquire();
- Label negative, end, skipCheck;
+ Label negative, end, performRound;
- // Load biggest number less than 0.5 in the temp register.
- loadConstantDouble(GetBiggestNumberLessThan(0.5), temp);
-
- // Branch to a slow path for negative inputs. Doesn't catch NaN or -0.
+ // Branch for negative inputs. Doesn't catch NaN or -0.
loadConstantDouble(0.0, dscratch);
ma_bc1d(src, dscratch, &negative, Assembler::DoubleLessThan, ShortJump);
- // If Nan, 0 or -0 check for bailout
- ma_bc1d(src, dscratch, &skipCheck, Assembler::DoubleNotEqual, ShortJump);
-
- // If high part is not zero, it is NaN or -0, so we bail.
- moveFromDoubleHi(src, scratch2);
- branch32(Assembler::NotEqual, scratch2, Imm32(0), fail);
-
- // Input was zero, so return zero.
- move32(Imm32(0), dest);
- ma_b(&end, ShortJump);
-
- bind(&skipCheck);
- as_addd(dscratch, src, temp);
- as_floorwd(dscratch, dscratch);
-
- moveFromDoubleLo(dscratch, dest);
-
- branch32(Assembler::Equal, dest, Imm32(INT_MAX), fail);
-
- jump(&end);
+ // If non-negative check for bailout.
+ ma_bc1d(src, dscratch, &performRound, Assembler::DoubleNotEqual, ShortJump);
+ {
+ // If binary value is not zero, it is NaN or -0, so we bail.
+ moveFromDouble(src, dest);
+ branchPtr(Assembler::NotEqual, dest, zero, fail);
+ ma_b(&end, ShortJump);
+ }
// Input is negative, but isn't -0.
bind(&negative);
+ {
+ // Inputs in [-0.5, 0) are rounded to -0. Fail.
+ loadConstantDouble(-0.5, dscratch);
+ branchDouble(Assembler::DoubleGreaterThanOrEqual, src, dscratch, fail);
+ }
- // Inputs in ]-0.5; 0] need to be added 0.5, other negative inputs need to
- // be added the biggest double less than 0.5.
- Label loadJoin;
- loadConstantDouble(-0.5, dscratch);
- branchDouble(Assembler::DoubleLessThan, src, dscratch, &loadJoin);
- loadConstantDouble(0.5, temp);
- bind(&loadJoin);
-
- addDouble(src, temp);
+ bind(&performRound);
+ {
+ // Load biggest number less than 0.5 in the temp register.
+ loadConstantDouble(GetBiggestNumberLessThan(0.5), temp);
- // If input + 0.5 >= 0, input is a negative number >= -0.5 and the
- // result is -0.
- branchDouble(Assembler::DoubleGreaterThanOrEqual, temp, dscratch, fail);
+ // Other inputs need the biggest double less than 0.5 added.
+ as_addd(dscratch, src, temp);
- // Truncate and round toward zero.
- // This is off-by-one for everything but integer-valued inputs.
- as_floorwd(dscratch, temp);
- moveFromDoubleLo(dscratch, dest);
+ // Round toward negative infinity.
+ as_floorld(dscratch, dscratch);
+ moveFromDouble(dscratch, dest);
- // Need to test for both INT_MIN and INT_MAX:
- // If NAN2008=0, out-of-range (negative) values return INT_MAX.
- // If NAN2008=1, out-of-range negative values return INT_MIN.
- branch32(Assembler::Equal, dest, Imm32(INT_MIN), fail);
- branch32(Assembler::Equal, dest, Imm32(INT_MAX), fail);
+ // Sign extend lower 32 bits to test if the result isn't an Int32.
+ {
+ UseScratchRegisterScope temps(*this);
+ Register scratch = temps.Acquire();
+ move32SignExtendToPtr(dest, scratch);
+ branchPtr(Assembler::NotEqual, dest, scratch, fail);
+ }
+ }
bind(&end);
}
void MacroAssembler::truncFloat32ToInt32(FloatRegister src, Register dest,
Label* fail) {
- UseScratchRegisterScope temps(*this);
- Register scratch = temps.Acquire();
+ ScratchFloat32Scope fscratch(*this);
+
+ // Round toward zero.
+ as_truncls(fscratch, src);
+ moveFromDouble(fscratch, dest);
+
+ // Sign extend lower 32 bits to test if the result isn't an Int32.
+ {
+ UseScratchRegisterScope temps(*this);
+ Register scratch = temps.Acquire();
+
+ move32SignExtendToPtr(dest, scratch);
+ branchPtr(Assembler::NotEqual, dest, scratch, fail);
+ }
+
+ // We have to check for (-1, -0] and NaN when the result is zero.
Label notZero;
- // Perform trunc.w.s
- as_truncws(ScratchFloat32Reg, src);
- // Bail if NaN, Infinity, or int32 overflow.
- as_cfc1(scratch, Assembler::FCSR);
- ma_ext(scratch, scratch, Assembler::CauseV, 1);
- branch32(Assembler::NotEqual, scratch, Imm32(0), fail);
-
- moveFromFloat32(ScratchFloat32Reg, dest);
- ma_b(dest, Imm32(0), ¬Zero, Assembler::NotEqual, ShortJump);
- moveFromFloat32(src, scratch);
- // Check if src is in ]-1; -0] range by checking the sign bit.
- as_slt(scratch, scratch, zero);
- branch32(Assembler::NotEqual, scratch, Imm32(0), fail);
+ ma_b(dest, zero, ¬Zero, Assembler::NotEqual, ShortJump);
+ {
+ // If any of the two most significant bits is set, |src| is negative or NaN.
+ moveFromFloat32(src, dest);
+ ma_srl(dest, dest, Imm32(30));
+ branch32(Assembler::NotEqual, dest, zero, fail);
+ }
bind(¬Zero);
}
void MacroAssembler::truncDoubleToInt32(FloatRegister src, Register dest,
Label* fail) {
- UseScratchRegisterScope temps(*this);
- Register scratch = temps.Acquire();
+ ScratchDoubleScope dscratch(*this);
+
+ // Round toward zero.
+ as_truncld(dscratch, src);
+ moveFromDouble(dscratch, dest);
+
+ // Sign extend lower 32 bits to test if the result isn't an Int32.
+ {
+ UseScratchRegisterScope temps(*this);
+ Register scratch = temps.Acquire();
+
+ move32SignExtendToPtr(dest, scratch);
+ branchPtr(Assembler::NotEqual, dest, scratch, fail);
+ }
+
+ // We have to check for (-1, -0] and NaN when the result is zero.
Label notZero;
- // Perform trunc.w.d
- as_truncwd(ScratchFloat32Reg, src);
- // Bail if NaN, Infinity, or int32 overflow.
- as_cfc1(scratch, Assembler::FCSR);
- ma_ext(scratch, scratch, Assembler::CauseV, 1);
- branch32(Assembler::NotEqual, scratch, Imm32(0), fail);
-
- // Skip the negative zero check if nonzero
- moveFromFloat32(ScratchFloat32Reg, dest);
- ma_b(dest, Imm32(0), ¬Zero, Assembler::NotEqual, ShortJump);
- moveFromDoubleHi(src, scratch);
- // Check if src is in ]-1; -0] range by checking the sign bit.
- as_slt(scratch, scratch, zero);
- branch32(Assembler::NotEqual, scratch, Imm32(0), fail);
+ ma_b(dest, zero, ¬Zero, Assembler::NotEqual, ShortJump);
+ {
+ // If any of the two most significant bits is set, |src| is negative or NaN.
+ moveFromDouble(src, dest);
+ ma_dsrl(dest, dest, Imm32(62));
+ branchPtr(Assembler::NotEqual, dest, zero, fail);
+ }
bind(¬Zero);
}
diff --git a/js/src/jit/mips-shared/MacroAssembler-mips-shared.h b/js/src/jit/mips-shared/MacroAssembler-mips-shared.h
@@ -206,11 +206,6 @@ class MacroAssemblerMIPSShared : public Assembler {
void ma_cmp_set_float32(Register dst, FloatRegister lhs, FloatRegister rhs,
DoubleCondition c);
- void moveToDoubleLo(Register src, FloatRegister dest) { as_mtc1(src, dest); }
- void moveFromDoubleLo(FloatRegister src, Register dest) {
- as_mfc1(dest, src);
- }
-
void moveToFloat32(Register src, FloatRegister dest) { as_mtc1(src, dest); }
void moveFromFloat32(FloatRegister src, Register dest) { as_mfc1(dest, src); }