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}
This commit is contained in:
parent
2ab7a917c9
commit
cb1084a800
@ -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 __
|
||||
|
Loading…
Reference in New Issue
Block a user