Commit cb1084a8 authored by akos.palfi's avatar akos.palfi Committed by Commit bot

MIPS: Fix Sltu macro instruction.

Fixes the case when the 'imm' is in range [8000,ffff], as the specification
says the 'imm' is sign-extended before the comparsion, so the effective range
is [max_unsigned-7fff,max_unsigned].

TEST=mjsunit/generated-transition-stub@3b8ad45e
BUG=

Review-Url: https://codereview.chromium.org/2386673002
Cr-Commit-Position: refs/heads/master@{#39922}
parent 2ab7a917
......@@ -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<int16_t>::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<uint16_t>(rt.imm32_));
} else {
// li handles the relocation.
DCHECK(!rs.is(at));
......
......@@ -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<int16_t>::min();
if (is_uint15(rt.imm64_) && !MustUseReg(rt.rmode_)) {
// Imm range is: [0, 32767].
sltiu(rd, rs, static_cast<int32_t>(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<uint16_t>(rt.imm64_));
} else {
// li handles the relocation.
DCHECK(!rs.is(at));
......
......@@ -1306,4 +1306,57 @@ TEST(Uldc1) {
}
}
static const std::vector<uint32_t> 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<uint32_t>(&kValues[0], &kValues[arraysize(kValues)]);
}
template <typename Func>
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> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
F_CVT f = FUNCTION_CAST<F_CVT>(code->entry());
int32_t res = reinterpret_cast<int32_t>(
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 __
......@@ -1901,4 +1901,68 @@ TEST(Uldc1) {
}
}
static const std::vector<uint64_t> 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<uint64_t>(&kValues[0], &kValues[arraysize(kValues)]);
}
template <typename Func>
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> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
F_CVT f = FUNCTION_CAST<F_CVT>(code->entry());
int64_t res = reinterpret_cast<int64_t>(
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 __
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment