[Liftoff][mips] Implement f32/f64 to i32/u32 conversion
Implement float to i32/u32 conversion on mips. Also, fix order
of arguments in some macro-assembler instructions used for these
conversions.
Bug: v8:6600
Change-Id: I94c91f8ac7796ac66fb3cf0129a2a27c1a6ec336
Reviewed-on: https://chromium-review.googlesource.com/1028232
Commit-Queue: Sreten Kovacevic <sreten.kovacevic@mips.com>
Reviewed-by: Ivica Bogosavljevic <ivica.bogosavljevic@mips.com>
Cr-Commit-Position: refs/heads/master@{#52806}
diff --git a/src/compiler/mips/code-generator-mips.cc b/src/compiler/mips/code-generator-mips.cc
index 9a10201..ee7b78e 100644
--- a/src/compiler/mips/code-generator-mips.cc
+++ b/src/compiler/mips/code-generator-mips.cc
@@ -1410,14 +1410,12 @@
}
case kMipsTruncUwD: {
FPURegister scratch = kScratchDoubleReg;
- // TODO(plind): Fix wrong param order of Trunc_uw_d() macro-asm function.
- __ Trunc_uw_d(i.InputDoubleRegister(0), i.OutputRegister(), scratch);
+ __ Trunc_uw_d(i.OutputRegister(), i.InputDoubleRegister(0), scratch);
break;
}
case kMipsTruncUwS: {
FPURegister scratch = kScratchDoubleReg;
- // TODO(plind): Fix wrong param order of Trunc_uw_s() macro-asm function.
- __ Trunc_uw_s(i.InputDoubleRegister(0), i.OutputRegister(), scratch);
+ __ Trunc_uw_s(i.OutputRegister(), i.InputDoubleRegister(0), scratch);
// Avoid UINT32_MAX as an overflow indicator and use 0 instead,
// because 0 allows easier out-of-bounds detection.
__ Addu(kScratchReg, i.OutputRegister(), 1);
diff --git a/src/compiler/mips64/code-generator-mips64.cc b/src/compiler/mips64/code-generator-mips64.cc
index aea62e7..11875aa 100644
--- a/src/compiler/mips64/code-generator-mips64.cc
+++ b/src/compiler/mips64/code-generator-mips64.cc
@@ -1588,14 +1588,12 @@
}
case kMips64TruncUwD: {
FPURegister scratch = kScratchDoubleReg;
- // TODO(plind): Fix wrong param order of Trunc_uw_d() macro-asm function.
- __ Trunc_uw_d(i.InputDoubleRegister(0), i.OutputRegister(), scratch);
+ __ Trunc_uw_d(i.OutputRegister(), i.InputDoubleRegister(0), scratch);
break;
}
case kMips64TruncUwS: {
FPURegister scratch = kScratchDoubleReg;
- // TODO(plind): Fix wrong param order of Trunc_uw_d() macro-asm function.
- __ Trunc_uw_s(i.InputDoubleRegister(0), i.OutputRegister(), scratch);
+ __ Trunc_uw_s(i.OutputRegister(), i.InputDoubleRegister(0), scratch);
// Avoid UINT32_MAX as an overflow indicator and use 0 instead,
// because 0 allows easier out-of-bounds detection.
__ addiu(kScratchReg, i.OutputRegister(), 1);
@@ -1605,16 +1603,14 @@
case kMips64TruncUlS: {
FPURegister scratch = kScratchDoubleReg;
Register result = instr->OutputCount() > 1 ? i.OutputRegister(1) : no_reg;
- // TODO(plind): Fix wrong param order of Trunc_ul_s() macro-asm function.
- __ Trunc_ul_s(i.InputDoubleRegister(0), i.OutputRegister(), scratch,
+ __ Trunc_ul_s(i.OutputRegister(), i.InputDoubleRegister(0), scratch,
result);
break;
}
case kMips64TruncUlD: {
FPURegister scratch = kScratchDoubleReg;
Register result = instr->OutputCount() > 1 ? i.OutputRegister(1) : no_reg;
- // TODO(plind): Fix wrong param order of Trunc_ul_d() macro-asm function.
- __ Trunc_ul_d(i.InputDoubleRegister(0), i.OutputRegister(0), scratch,
+ __ Trunc_ul_d(i.OutputRegister(0), i.InputDoubleRegister(0), scratch,
result);
break;
}
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc
index 4d7038a..15e67c3 100644
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -1797,13 +1797,15 @@
void TurboAssembler::Trunc_uw_d(FPURegister fd, FPURegister fs,
FPURegister scratch) {
- Trunc_uw_d(fs, t8, scratch);
+ BlockTrampolinePoolScope block_trampoline_pool(this);
+ Trunc_uw_d(t8, fs, scratch);
mtc1(t8, fd);
}
void TurboAssembler::Trunc_uw_s(FPURegister fd, FPURegister fs,
FPURegister scratch) {
- Trunc_uw_s(fs, t8, scratch);
+ BlockTrampolinePoolScope block_trampoline_pool(this);
+ Trunc_uw_s(t8, fs, scratch);
mtc1(t8, fd);
}
@@ -1847,10 +1849,10 @@
}
}
-void TurboAssembler::Trunc_uw_d(FPURegister fd, Register rs,
+void TurboAssembler::Trunc_uw_d(Register rd, FPURegister fs,
FPURegister scratch) {
- DCHECK(fd != scratch);
- DCHECK(rs != at);
+ DCHECK(fs != scratch);
+ DCHECK(rd != at);
{
// Load 2^31 into scratch as its float representation.
@@ -1860,33 +1862,33 @@
mtc1(zero_reg, scratch);
Mthc1(scratch1, scratch);
}
- // Test if scratch > fd.
- // If fd < 2^31 we can convert it normally.
+ // Test if scratch > fs.
+ // If fs < 2^31 we can convert it normally.
Label simple_convert;
- CompareF64(OLT, fd, scratch);
+ CompareF64(OLT, fs, scratch);
BranchTrueShortF(&simple_convert);
- // First we subtract 2^31 from fd, then trunc it to rs
- // and add 2^31 to rs.
- sub_d(scratch, fd, scratch);
+ // First we subtract 2^31 from fs, then trunc it to rd
+ // and add 2^31 to rd.
+ sub_d(scratch, fs, scratch);
trunc_w_d(scratch, scratch);
- mfc1(rs, scratch);
- Or(rs, rs, 1 << 31);
+ mfc1(rd, scratch);
+ Or(rd, rd, 1 << 31);
Label done;
Branch(&done);
// Simple conversion.
bind(&simple_convert);
- trunc_w_d(scratch, fd);
- mfc1(rs, scratch);
+ trunc_w_d(scratch, fs);
+ mfc1(rd, scratch);
bind(&done);
}
-void TurboAssembler::Trunc_uw_s(FPURegister fd, Register rs,
+void TurboAssembler::Trunc_uw_s(Register rd, FPURegister fs,
FPURegister scratch) {
- DCHECK(fd != scratch);
- DCHECK(rs != at);
+ DCHECK(fs != scratch);
+ DCHECK(rd != at);
{
// Load 2^31 into scratch as its float representation.
@@ -1895,25 +1897,25 @@
li(scratch1, 0x4F000000);
mtc1(scratch1, scratch);
}
- // Test if scratch > fd.
- // If fd < 2^31 we can convert it normally.
+ // Test if scratch > fs.
+ // If fs < 2^31 we can convert it normally.
Label simple_convert;
- CompareF32(OLT, fd, scratch);
+ CompareF32(OLT, fs, scratch);
BranchTrueShortF(&simple_convert);
- // First we subtract 2^31 from fd, then trunc it to rs
- // and add 2^31 to rs.
- sub_s(scratch, fd, scratch);
+ // First we subtract 2^31 from fs, then trunc it to rd
+ // and add 2^31 to rd.
+ sub_s(scratch, fs, scratch);
trunc_w_s(scratch, scratch);
- mfc1(rs, scratch);
- Or(rs, rs, 1 << 31);
+ mfc1(rd, scratch);
+ Or(rd, rd, 1 << 31);
Label done;
Branch(&done);
// Simple conversion.
bind(&simple_convert);
- trunc_w_s(scratch, fd);
- mfc1(rs, scratch);
+ trunc_w_s(scratch, fs);
+ mfc1(rd, scratch);
bind(&done);
}
diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h
index df37993..f8245ff 100644
--- a/src/mips/macro-assembler-mips.h
+++ b/src/mips/macro-assembler-mips.h
@@ -632,7 +632,7 @@
// Convert single to unsigned word.
void Trunc_uw_s(FPURegister fd, FPURegister fs, FPURegister scratch);
- void Trunc_uw_s(FPURegister fd, Register rs, FPURegister scratch);
+ void Trunc_uw_s(Register rd, FPURegister fs, FPURegister scratch);
void Trunc_w_d(FPURegister fd, FPURegister fs);
void Round_w_d(FPURegister fd, FPURegister fs);
@@ -820,7 +820,7 @@
// Convert double to unsigned word.
void Trunc_uw_d(FPURegister fd, FPURegister fs, FPURegister scratch);
- void Trunc_uw_d(FPURegister fd, Register rs, FPURegister scratch);
+ void Trunc_uw_d(Register rd, FPURegister fs, FPURegister scratch);
// Jump the register contains a smi.
void JumpIfSmi(Register value, Label* smi_label, Register scratch = at,
diff --git a/src/mips64/macro-assembler-mips64.cc b/src/mips64/macro-assembler-mips64.cc
index e09134f..81a245a 100644
--- a/src/mips64/macro-assembler-mips64.cc
+++ b/src/mips64/macro-assembler-mips64.cc
@@ -2249,25 +2249,29 @@
void TurboAssembler::Trunc_uw_d(FPURegister fd, FPURegister fs,
FPURegister scratch) {
- Trunc_uw_d(fs, t8, scratch);
+ BlockTrampolinePoolScope block_trampoline_pool(this);
+ Trunc_uw_d(t8, fs, scratch);
mtc1(t8, fd);
}
void TurboAssembler::Trunc_uw_s(FPURegister fd, FPURegister fs,
FPURegister scratch) {
- Trunc_uw_s(fs, t8, scratch);
+ BlockTrampolinePoolScope block_trampoline_pool(this);
+ Trunc_uw_s(t8, fs, scratch);
mtc1(t8, fd);
}
void TurboAssembler::Trunc_ul_d(FPURegister fd, FPURegister fs,
FPURegister scratch, Register result) {
- Trunc_ul_d(fs, t8, scratch, result);
+ BlockTrampolinePoolScope block_trampoline_pool(this);
+ Trunc_ul_d(t8, fs, scratch, result);
dmtc1(t8, fd);
}
void TurboAssembler::Trunc_ul_s(FPURegister fd, FPURegister fs,
FPURegister scratch, Register result) {
- Trunc_ul_s(fs, t8, scratch, result);
+ BlockTrampolinePoolScope block_trampoline_pool(this);
+ Trunc_ul_s(t8, fs, scratch, result);
dmtc1(t8, fd);
}
@@ -2291,10 +2295,10 @@
ceil_w_d(fd, fs);
}
-void TurboAssembler::Trunc_uw_d(FPURegister fd, Register rs,
+void TurboAssembler::Trunc_uw_d(Register rd, FPURegister fs,
FPURegister scratch) {
- DCHECK(fd != scratch);
- DCHECK(rs != at);
+ DCHECK(fs != scratch);
+ DCHECK(rd != at);
{
// Load 2^31 into scratch as its float representation.
@@ -2307,30 +2311,30 @@
// Test if scratch > fd.
// If fd < 2^31 we can convert it normally.
Label simple_convert;
- CompareF64(OLT, fd, scratch);
+ CompareF64(OLT, fs, scratch);
BranchTrueShortF(&simple_convert);
// First we subtract 2^31 from fd, then trunc it to rs
// and add 2^31 to rs.
- sub_d(scratch, fd, scratch);
+ sub_d(scratch, fs, scratch);
trunc_w_d(scratch, scratch);
- mfc1(rs, scratch);
- Or(rs, rs, 1 << 31);
+ mfc1(rd, scratch);
+ Or(rd, rd, 1 << 31);
Label done;
Branch(&done);
// Simple conversion.
bind(&simple_convert);
- trunc_w_d(scratch, fd);
- mfc1(rs, scratch);
+ trunc_w_d(scratch, fs);
+ mfc1(rd, scratch);
bind(&done);
}
-void TurboAssembler::Trunc_uw_s(FPURegister fd, Register rs,
+void TurboAssembler::Trunc_uw_s(Register rd, FPURegister fs,
FPURegister scratch) {
- DCHECK(fd != scratch);
- DCHECK(rs != at);
+ DCHECK(fs != scratch);
+ DCHECK(rd != at);
{
// Load 2^31 into scratch as its float representation.
@@ -2339,42 +2343,42 @@
li(scratch1, 0x4F000000);
mtc1(scratch1, scratch);
}
- // Test if scratch > fd.
- // If fd < 2^31 we can convert it normally.
+ // Test if scratch > fs.
+ // If fs < 2^31 we can convert it normally.
Label simple_convert;
- CompareF32(OLT, fd, scratch);
+ CompareF32(OLT, fs, scratch);
BranchTrueShortF(&simple_convert);
- // First we subtract 2^31 from fd, then trunc it to rs
- // and add 2^31 to rs.
- sub_s(scratch, fd, scratch);
+ // First we subtract 2^31 from fs, then trunc it to rd
+ // and add 2^31 to rd.
+ sub_s(scratch, fs, scratch);
trunc_w_s(scratch, scratch);
- mfc1(rs, scratch);
- Or(rs, rs, 1 << 31);
+ mfc1(rd, scratch);
+ Or(rd, rd, 1 << 31);
Label done;
Branch(&done);
// Simple conversion.
bind(&simple_convert);
- trunc_w_s(scratch, fd);
- mfc1(rs, scratch);
+ trunc_w_s(scratch, fs);
+ mfc1(rd, scratch);
bind(&done);
}
-void TurboAssembler::Trunc_ul_d(FPURegister fd, Register rs,
+void TurboAssembler::Trunc_ul_d(Register rd, FPURegister fs,
FPURegister scratch, Register result) {
- DCHECK(fd != scratch);
- DCHECK(!AreAliased(rs, result, at));
+ DCHECK(fs != scratch);
+ DCHECK(!AreAliased(rd, result, at));
Label simple_convert, done, fail;
if (result.is_valid()) {
mov(result, zero_reg);
Move(scratch, -1.0);
// If fd =< -1 or unordered, then the conversion fails.
- CompareF64(OLE, fd, scratch);
+ CompareF64(OLE, fs, scratch);
BranchTrueShortF(&fail);
- CompareIsNanF64(fd, scratch);
+ CompareIsNanF64(fs, scratch);
BranchTrueShortF(&fail);
}
@@ -2382,23 +2386,23 @@
li(at, 0x43E0000000000000);
dmtc1(at, scratch);
- // Test if scratch > fd.
- // If fd < 2^63 we can convert it normally.
- CompareF64(OLT, fd, scratch);
+ // Test if scratch > fs.
+ // If fs < 2^63 we can convert it normally.
+ CompareF64(OLT, fs, scratch);
BranchTrueShortF(&simple_convert);
- // First we subtract 2^63 from fd, then trunc it to rs
- // and add 2^63 to rs.
- sub_d(scratch, fd, scratch);
+ // First we subtract 2^63 from fs, then trunc it to rd
+ // and add 2^63 to rd.
+ sub_d(scratch, fs, scratch);
trunc_l_d(scratch, scratch);
- dmfc1(rs, scratch);
- Or(rs, rs, Operand(1UL << 63));
+ dmfc1(rd, scratch);
+ Or(rd, rd, Operand(1UL << 63));
Branch(&done);
// Simple conversion.
bind(&simple_convert);
- trunc_l_d(scratch, fd);
- dmfc1(rs, scratch);
+ trunc_l_d(scratch, fs);
+ dmfc1(rd, scratch);
bind(&done);
if (result.is_valid()) {
@@ -2417,19 +2421,19 @@
bind(&fail);
}
-void TurboAssembler::Trunc_ul_s(FPURegister fd, Register rs,
+void TurboAssembler::Trunc_ul_s(Register rd, FPURegister fs,
FPURegister scratch, Register result) {
- DCHECK(fd != scratch);
- DCHECK(!AreAliased(rs, result, at));
+ DCHECK(fs != scratch);
+ DCHECK(!AreAliased(rd, result, at));
Label simple_convert, done, fail;
if (result.is_valid()) {
mov(result, zero_reg);
Move(scratch, -1.0f);
// If fd =< -1 or unordered, then the conversion fails.
- CompareF32(OLE, fd, scratch);
+ CompareF32(OLE, fs, scratch);
BranchTrueShortF(&fail);
- CompareIsNanF32(fd, scratch);
+ CompareIsNanF32(fs, scratch);
BranchTrueShortF(&fail);
}
@@ -2441,23 +2445,23 @@
mtc1(scratch1, scratch);
}
- // Test if scratch > fd.
- // If fd < 2^63 we can convert it normally.
- CompareF32(OLT, fd, scratch);
+ // Test if scratch > fs.
+ // If fs < 2^63 we can convert it normally.
+ CompareF32(OLT, fs, scratch);
BranchTrueShortF(&simple_convert);
- // First we subtract 2^63 from fd, then trunc it to rs
- // and add 2^63 to rs.
- sub_s(scratch, fd, scratch);
+ // First we subtract 2^63 from fs, then trunc it to rd
+ // and add 2^63 to rd.
+ sub_s(scratch, fs, scratch);
trunc_l_s(scratch, scratch);
- dmfc1(rs, scratch);
- Or(rs, rs, Operand(1UL << 63));
+ dmfc1(rd, scratch);
+ Or(rd, rd, Operand(1UL << 63));
Branch(&done);
// Simple conversion.
bind(&simple_convert);
- trunc_l_s(scratch, fd);
- dmfc1(rs, scratch);
+ trunc_l_s(scratch, fs);
+ dmfc1(rd, scratch);
bind(&done);
if (result.is_valid()) {
diff --git a/src/mips64/macro-assembler-mips64.h b/src/mips64/macro-assembler-mips64.h
index faf9275..064abc65 100644
--- a/src/mips64/macro-assembler-mips64.h
+++ b/src/mips64/macro-assembler-mips64.h
@@ -630,7 +630,7 @@
// Convert single to unsigned word.
void Trunc_uw_s(FPURegister fd, FPURegister fs, FPURegister scratch);
- void Trunc_uw_s(FPURegister fd, Register rs, FPURegister scratch);
+ void Trunc_uw_s(Register rd, FPURegister fs, FPURegister scratch);
// Change endianness
void ByteSwapSigned(Register dest, Register src, int operand_size);
@@ -814,18 +814,18 @@
// Convert double to unsigned word.
void Trunc_uw_d(FPURegister fd, FPURegister fs, FPURegister scratch);
- void Trunc_uw_d(FPURegister fd, Register rs, FPURegister scratch);
+ void Trunc_uw_d(Register rd, FPURegister fs, FPURegister scratch);
// Convert double to unsigned long.
void Trunc_ul_d(FPURegister fd, FPURegister fs, FPURegister scratch,
Register result = no_reg);
- void Trunc_ul_d(FPURegister fd, Register rs, FPURegister scratch,
+ void Trunc_ul_d(Register rd, FPURegister fs, FPURegister scratch,
Register result = no_reg);
// Convert single to unsigned long.
void Trunc_ul_s(FPURegister fd, FPURegister fs, FPURegister scratch,
Register result = no_reg);
- void Trunc_ul_s(FPURegister fd, Register rs, FPURegister scratch,
+ void Trunc_ul_s(Register rd, FPURegister fs, FPURegister scratch,
Register result = no_reg);
// Round double functions
diff --git a/src/wasm/baseline/mips/liftoff-assembler-mips.h b/src/wasm/baseline/mips/liftoff-assembler-mips.h
index d330639..f587064 100644
--- a/src/wasm/baseline/mips/liftoff-assembler-mips.h
+++ b/src/wasm/baseline/mips/liftoff-assembler-mips.h
@@ -821,6 +821,97 @@
case kExprI32ConvertI64:
TurboAssembler::Move(dst.gp(), src.low_gp());
return true;
+ case kExprI32SConvertF32: {
+ LiftoffRegister rounded =
+ GetUnusedRegister(kFpReg, LiftoffRegList::ForRegs(src));
+ LiftoffRegister converted_back =
+ GetUnusedRegister(kFpReg, LiftoffRegList::ForRegs(src, rounded));
+
+ // Real conversion.
+ TurboAssembler::Trunc_s_s(rounded.fp(), src.fp());
+ trunc_w_s(kScratchDoubleReg, rounded.fp());
+ mfc1(dst.gp(), kScratchDoubleReg);
+ // Avoid INT32_MAX as an overflow indicator and use INT32_MIN instead,
+ // because INT32_MIN allows easier out-of-bounds detection.
+ TurboAssembler::Addu(kScratchReg, dst.gp(), 1);
+ TurboAssembler::Slt(kScratchReg2, kScratchReg, dst.gp());
+ TurboAssembler::Movn(dst.gp(), kScratchReg, kScratchReg2);
+
+ // Checking if trap.
+ mtc1(dst.gp(), kScratchDoubleReg);
+ cvt_s_w(converted_back.fp(), kScratchDoubleReg);
+ TurboAssembler::CompareF32(EQ, rounded.fp(), converted_back.fp());
+ TurboAssembler::BranchFalseF(trap);
+ return true;
+ }
+ case kExprI32UConvertF32: {
+ LiftoffRegister rounded =
+ GetUnusedRegister(kFpReg, LiftoffRegList::ForRegs(src));
+ LiftoffRegister converted_back =
+ GetUnusedRegister(kFpReg, LiftoffRegList::ForRegs(src, rounded));
+
+ // Real conversion.
+ TurboAssembler::Trunc_s_s(rounded.fp(), src.fp());
+ TurboAssembler::Trunc_uw_s(dst.gp(), rounded.fp(), kScratchDoubleReg);
+ // Avoid UINT32_MAX as an overflow indicator and use 0 instead,
+ // because 0 allows easier out-of-bounds detection.
+ TurboAssembler::Addu(kScratchReg, dst.gp(), 1);
+ TurboAssembler::Movz(dst.gp(), zero_reg, kScratchReg);
+
+ // Checking if trap.
+ TurboAssembler::Cvt_d_uw(converted_back.fp(), dst.gp(),
+ kScratchDoubleReg);
+ cvt_s_d(converted_back.fp(), converted_back.fp());
+ TurboAssembler::CompareF32(EQ, rounded.fp(), converted_back.fp());
+ TurboAssembler::BranchFalseF(trap);
+ return true;
+ }
+ case kExprI32SConvertF64: {
+ if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
+ IsFp64Mode()) {
+ LiftoffRegister rounded =
+ GetUnusedRegister(kFpReg, LiftoffRegList::ForRegs(src));
+ LiftoffRegister converted_back =
+ GetUnusedRegister(kFpReg, LiftoffRegList::ForRegs(src, rounded));
+
+ // Real conversion.
+ TurboAssembler::Trunc_d_d(rounded.fp(), src.fp());
+ TurboAssembler::Trunc_w_d(kScratchDoubleReg, rounded.fp());
+ mfc1(dst.gp(), kScratchDoubleReg);
+
+ // Checking if trap.
+ cvt_d_w(converted_back.fp(), kScratchDoubleReg);
+ TurboAssembler::CompareF64(EQ, rounded.fp(), converted_back.fp());
+ TurboAssembler::BranchFalseF(trap);
+ return true;
+ } else {
+ BAILOUT("emit_type_conversion kExprI32SConvertF64");
+ return true;
+ }
+ }
+ case kExprI32UConvertF64: {
+ if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
+ IsFp64Mode()) {
+ LiftoffRegister rounded =
+ GetUnusedRegister(kFpReg, LiftoffRegList::ForRegs(src));
+ LiftoffRegister converted_back =
+ GetUnusedRegister(kFpReg, LiftoffRegList::ForRegs(src, rounded));
+
+ // Real conversion.
+ TurboAssembler::Trunc_d_d(rounded.fp(), src.fp());
+ TurboAssembler::Trunc_uw_d(dst.gp(), rounded.fp(), kScratchDoubleReg);
+
+ // Checking if trap.
+ TurboAssembler::Cvt_d_uw(converted_back.fp(), dst.gp(),
+ kScratchDoubleReg);
+ TurboAssembler::CompareF64(EQ, rounded.fp(), converted_back.fp());
+ TurboAssembler::BranchFalseF(trap);
+ return true;
+ } else {
+ BAILOUT("emit_type_conversion kExprI32UConvertF64");
+ return true;
+ }
+ }
case kExprI32ReinterpretF32:
mfc1(dst.gp(), src.fp());
return true;
diff --git a/src/wasm/baseline/mips64/liftoff-assembler-mips64.h b/src/wasm/baseline/mips64/liftoff-assembler-mips64.h
index a42a52e..8c96c83 100644
--- a/src/wasm/baseline/mips64/liftoff-assembler-mips64.h
+++ b/src/wasm/baseline/mips64/liftoff-assembler-mips64.h
@@ -661,6 +661,83 @@
case kExprI32ConvertI64:
TurboAssembler::Ext(dst.gp(), src.gp(), 0, 32);
return true;
+ case kExprI32SConvertF32: {
+ LiftoffRegister rounded =
+ GetUnusedRegister(kFpReg, LiftoffRegList::ForRegs(src));
+ LiftoffRegister converted_back =
+ GetUnusedRegister(kFpReg, LiftoffRegList::ForRegs(src, rounded));
+
+ // Real conversion.
+ TurboAssembler::Trunc_s_s(rounded.fp(), src.fp());
+ trunc_w_s(kScratchDoubleReg, rounded.fp());
+ mfc1(dst.gp(), kScratchDoubleReg);
+ // Avoid INT32_MAX as an overflow indicator and use INT32_MIN instead,
+ // because INT32_MIN allows easier out-of-bounds detection.
+ TurboAssembler::Addu(kScratchReg, dst.gp(), 1);
+ TurboAssembler::Slt(kScratchReg2, kScratchReg, dst.gp());
+ TurboAssembler::Movn(dst.gp(), kScratchReg, kScratchReg2);
+
+ // Checking if trap.
+ mtc1(dst.gp(), kScratchDoubleReg);
+ cvt_s_w(converted_back.fp(), kScratchDoubleReg);
+ TurboAssembler::CompareF32(EQ, rounded.fp(), converted_back.fp());
+ TurboAssembler::BranchFalseF(trap);
+ return true;
+ }
+ case kExprI32UConvertF32: {
+ LiftoffRegister rounded =
+ GetUnusedRegister(kFpReg, LiftoffRegList::ForRegs(src));
+ LiftoffRegister converted_back =
+ GetUnusedRegister(kFpReg, LiftoffRegList::ForRegs(src, rounded));
+
+ // Real conversion.
+ TurboAssembler::Trunc_s_s(rounded.fp(), src.fp());
+ TurboAssembler::Trunc_uw_s(dst.gp(), rounded.fp(), kScratchDoubleReg);
+ // Avoid UINT32_MAX as an overflow indicator and use 0 instead,
+ // because 0 allows easier out-of-bounds detection.
+ TurboAssembler::Addu(kScratchReg, dst.gp(), 1);
+ TurboAssembler::Movz(dst.gp(), zero_reg, kScratchReg);
+
+ // Checking if trap.
+ TurboAssembler::Cvt_d_uw(converted_back.fp(), dst.gp());
+ cvt_s_d(converted_back.fp(), converted_back.fp());
+ TurboAssembler::CompareF32(EQ, rounded.fp(), converted_back.fp());
+ TurboAssembler::BranchFalseF(trap);
+ return true;
+ }
+ case kExprI32SConvertF64: {
+ LiftoffRegister rounded =
+ GetUnusedRegister(kFpReg, LiftoffRegList::ForRegs(src));
+ LiftoffRegister converted_back =
+ GetUnusedRegister(kFpReg, LiftoffRegList::ForRegs(src, rounded));
+
+ // Real conversion.
+ TurboAssembler::Trunc_d_d(rounded.fp(), src.fp());
+ trunc_w_d(kScratchDoubleReg, rounded.fp());
+ mfc1(dst.gp(), kScratchDoubleReg);
+
+ // Checking if trap.
+ cvt_d_w(converted_back.fp(), kScratchDoubleReg);
+ TurboAssembler::CompareF64(EQ, rounded.fp(), converted_back.fp());
+ TurboAssembler::BranchFalseF(trap);
+ return true;
+ }
+ case kExprI32UConvertF64: {
+ LiftoffRegister rounded =
+ GetUnusedRegister(kFpReg, LiftoffRegList::ForRegs(src));
+ LiftoffRegister converted_back =
+ GetUnusedRegister(kFpReg, LiftoffRegList::ForRegs(src, rounded));
+
+ // Real conversion.
+ TurboAssembler::Trunc_d_d(rounded.fp(), src.fp());
+ TurboAssembler::Trunc_uw_d(dst.gp(), rounded.fp(), kScratchDoubleReg);
+
+ // Checking if trap.
+ TurboAssembler::Cvt_d_uw(converted_back.fp(), dst.gp());
+ TurboAssembler::CompareF64(EQ, rounded.fp(), converted_back.fp());
+ TurboAssembler::BranchFalseF(trap);
+ return true;
+ }
case kExprI32ReinterpretF32:
TurboAssembler::FmoveLow(dst.gp(), src.fp());
return true;