[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}
This commit is contained in:
parent
0d200d0832
commit
19896840c7
@ -1410,14 +1410,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
}
|
||||
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);
|
||||
|
@ -1588,14 +1588,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
}
|
||||
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 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
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;
|
||||
}
|
||||
|
@ -1797,13 +1797,15 @@ void TurboAssembler::Cvt_d_uw(FPURegister fd, Register rs,
|
||||
|
||||
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::Ceil_w_d(FPURegister fd, FPURegister 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.
|
||||
@ -1860,33 +1862,33 @@ void TurboAssembler::Trunc_uw_d(FPURegister fd, Register rs,
|
||||
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 @@ void TurboAssembler::Trunc_uw_s(FPURegister fd, Register rs,
|
||||
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);
|
||||
}
|
||||
|
@ -632,7 +632,7 @@ class TurboAssembler : public Assembler {
|
||||
|
||||
// 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 @@ class TurboAssembler : public Assembler {
|
||||
|
||||
// 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,
|
||||
|
@ -2249,25 +2249,29 @@ void MacroAssembler::Trunc_l_ud(FPURegister fd,
|
||||
|
||||
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 @@ void MacroAssembler::Ceil_w_d(FPURegister fd, FPURegister fs) {
|
||||
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 @@ void TurboAssembler::Trunc_uw_d(FPURegister fd, Register rs,
|
||||
// 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 @@ void TurboAssembler::Trunc_uw_s(FPURegister fd, Register rs,
|
||||
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 @@ void TurboAssembler::Trunc_ul_d(FPURegister fd, Register rs,
|
||||
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 @@ void TurboAssembler::Trunc_ul_d(FPURegister fd, Register rs,
|
||||
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 @@ void TurboAssembler::Trunc_ul_s(FPURegister fd, Register rs,
|
||||
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()) {
|
||||
|
@ -630,7 +630,7 @@ class TurboAssembler : public Assembler {
|
||||
|
||||
// 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 @@ class TurboAssembler : public Assembler {
|
||||
|
||||
// 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
|
||||
|
@ -821,6 +821,97 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
|
||||
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;
|
||||
|
@ -661,6 +661,83 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user