diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc index a6b818a67a..d61717d222 100644 --- a/src/mips/macro-assembler-mips.cc +++ b/src/mips/macro-assembler-mips.cc @@ -1124,8 +1124,13 @@ void MacroAssembler::Sltu(Register rd, Register rs, const Operand& rt) { if (rt.is_reg()) { sltu(rd, rs, rt.rm()); } else { - if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) { + const uint32_t int16_min = std::numeric_limits::min(); + if (is_uint15(rt.imm32_) && !MustUseReg(rt.rmode_)) { + // Imm range is: [0, 32767]. sltiu(rd, rs, rt.imm32_); + } else if (is_uint15(rt.imm32_ - int16_min) && !MustUseReg(rt.rmode_)) { + // Imm range is: [max_unsigned-32767,max_unsigned]. + sltiu(rd, rs, static_cast(rt.imm32_)); } else { // li handles the relocation. DCHECK(!rs.is(at)); diff --git a/src/mips64/macro-assembler-mips64.cc b/src/mips64/macro-assembler-mips64.cc index 1ab4a893e3..dd12f9b51a 100644 --- a/src/mips64/macro-assembler-mips64.cc +++ b/src/mips64/macro-assembler-mips64.cc @@ -1258,8 +1258,13 @@ void MacroAssembler::Sltu(Register rd, Register rs, const Operand& rt) { if (rt.is_reg()) { sltu(rd, rs, rt.rm()); } else { - if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) { + const uint64_t int16_min = std::numeric_limits::min(); + if (is_uint15(rt.imm64_) && !MustUseReg(rt.rmode_)) { + // Imm range is: [0, 32767]. sltiu(rd, rs, static_cast(rt.imm64_)); + } else if (is_uint15(rt.imm64_ - int16_min) && !MustUseReg(rt.rmode_)) { + // Imm range is: [max_unsigned-32767,max_unsigned]. + sltiu(rd, rs, static_cast(rt.imm64_)); } else { // li handles the relocation. DCHECK(!rs.is(at)); diff --git a/test/cctest/test-macro-assembler-mips.cc b/test/cctest/test-macro-assembler-mips.cc index 057c370304..9561db691e 100644 --- a/test/cctest/test-macro-assembler-mips.cc +++ b/test/cctest/test-macro-assembler-mips.cc @@ -1306,4 +1306,57 @@ TEST(Uldc1) { } } +static const std::vector sltu_test_values() { + static const uint32_t kValues[] = { + 0, 1, 0x7ffe, 0x7fff, 0x8000, + 0x8001, 0xfffe, 0xffff, 0xffff7ffe, 0xffff7fff, + 0xffff8000, 0xffff8001, 0xfffffffe, 0xffffffff, + }; + return std::vector(&kValues[0], &kValues[arraysize(kValues)]); +} + +template +bool run_Sltu(uint32_t rs, uint32_t rd, Func GenerateSltuInstructionFunc) { + typedef int32_t (*F_CVT)(uint32_t x0, uint32_t x1, int x2, int x3, int x4); + + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, nullptr, 0, + v8::internal::CodeObjectRequired::kYes); + MacroAssembler* masm = &assm; + + GenerateSltuInstructionFunc(masm, rd); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle()); + + F_CVT f = FUNCTION_CAST(code->entry()); + int32_t res = reinterpret_cast( + CALL_GENERATED_CODE(isolate, f, rs, rd, 0, 0, 0)); + return res == 1; +} + +TEST(Sltu) { + CcTest::InitializeVM(); + + FOR_UINT32_INPUTS(i, sltu_test_values) { + FOR_UINT32_INPUTS(j, sltu_test_values) { + uint32_t rs = *i; + uint32_t rd = *j; + + CHECK_EQ(rs < rd, run_Sltu(rs, rd, + [](MacroAssembler* masm, uint32_t imm) { + __ Sltu(v0, a0, Operand(imm)); + })); + CHECK_EQ(rs < rd, + run_Sltu(rs, rd, [](MacroAssembler* masm, + uint32_t imm) { __ Sltu(v0, a0, a1); })); + } + } +} + #undef __ diff --git a/test/cctest/test-macro-assembler-mips64.cc b/test/cctest/test-macro-assembler-mips64.cc index 5f9451027c..1dc260ff01 100644 --- a/test/cctest/test-macro-assembler-mips64.cc +++ b/test/cctest/test-macro-assembler-mips64.cc @@ -1901,4 +1901,68 @@ TEST(Uldc1) { } } +static const std::vector sltu_test_values() { + static const uint64_t kValues[] = { + 0, + 1, + 0x7ffe, + 0x7fff, + 0x8000, + 0x8001, + 0xfffe, + 0xffff, + 0xffffffffffff7ffe, + 0xffffffffffff7fff, + 0xffffffffffff8000, + 0xffffffffffff8001, + 0xfffffffffffffffe, + 0xffffffffffffffff, + }; + return std::vector(&kValues[0], &kValues[arraysize(kValues)]); +} + +template +bool run_Sltu(uint64_t rs, uint64_t rd, Func GenerateSltuInstructionFunc) { + typedef int64_t (*F_CVT)(uint64_t x0, uint64_t x1, int x2, int x3, int x4); + + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, nullptr, 0, + v8::internal::CodeObjectRequired::kYes); + MacroAssembler* masm = &assm; + + GenerateSltuInstructionFunc(masm, rd); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle()); + + F_CVT f = FUNCTION_CAST(code->entry()); + int64_t res = reinterpret_cast( + CALL_GENERATED_CODE(isolate, f, rs, rd, 0, 0, 0)); + return res == 1; +} + +TEST(Sltu) { + CcTest::InitializeVM(); + + FOR_UINT64_INPUTS(i, sltu_test_values) { + FOR_UINT64_INPUTS(j, sltu_test_values) { + uint64_t rs = *i; + uint64_t rd = *j; + + CHECK_EQ(rs < rd, run_Sltu(rs, rd, + [](MacroAssembler* masm, uint64_t imm) { + __ Sltu(v0, a0, Operand(imm)); + })); + CHECK_EQ(rs < rd, + run_Sltu(rs, rd, [](MacroAssembler* masm, + uint64_t imm) { __ Sltu(v0, a0, a1); })); + } + } +} + #undef __