Commit 04a735c7 authored by balazs.kilvady's avatar balazs.kilvady Committed by Commit bot

MIPS: Improve Lsa/Dlsa implementations.

Make the low level assembler implementation exact and protected to disallow explicit usage.

BUG=

Review URL: https://codereview.chromium.org/1749263002

Cr-Commit-Position: refs/heads/master@{#34673}
parent 899105c0
...@@ -1761,10 +1761,10 @@ void Assembler::rotrv(Register rd, Register rt, Register rs) { ...@@ -1761,10 +1761,10 @@ void Assembler::rotrv(Register rd, Register rt, Register rs) {
void Assembler::lsa(Register rd, Register rt, Register rs, uint8_t sa) { void Assembler::lsa(Register rd, Register rt, Register rs, uint8_t sa) {
DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid()); DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid());
DCHECK(sa < 5 && sa > 0); DCHECK(sa <= 3);
DCHECK(IsMipsArchVariant(kMips32r6)); DCHECK(IsMipsArchVariant(kMips32r6));
Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift) | Instr instr = SPECIAL | rs.code() << kRsShift | rt.code() << kRtShift |
(rd.code() << kRdShift) | (sa - 1) << kSaShift | LSA; rd.code() << kRdShift | sa << kSaShift | LSA;
emit(instr); emit(instr);
} }
......
...@@ -750,9 +750,6 @@ class Assembler : public AssemblerBase { ...@@ -750,9 +750,6 @@ class Assembler : public AssemblerBase {
void rotr(Register rd, Register rt, uint16_t sa); void rotr(Register rd, Register rt, uint16_t sa);
void rotrv(Register rd, Register rt, Register rs); void rotrv(Register rd, Register rt, Register rs);
// Address computing instructions with shift.
void lsa(Register rd, Register rt, Register rs, uint8_t sa);
// ------------Memory-instructions------------- // ------------Memory-instructions-------------
void lb(Register rd, const MemOperand& rs); void lb(Register rd, const MemOperand& rs);
...@@ -1154,6 +1151,9 @@ class Assembler : public AssemblerBase { ...@@ -1154,6 +1151,9 @@ class Assembler : public AssemblerBase {
bool IsPrevInstrCompactBranch() { return prev_instr_compact_branch_; } bool IsPrevInstrCompactBranch() { return prev_instr_compact_branch_; }
protected: protected:
// Load Scaled Address instruction.
void lsa(Register rd, Register rt, Register rs, uint8_t sa);
// Relocation for a type-recording IC has the AST id added to it. This // Relocation for a type-recording IC has the AST id added to it. This
// member variable is a way to pass the information from the call site to // member variable is a way to pass the information from the call site to
// the relocation info. // the relocation info.
......
...@@ -1148,8 +1148,9 @@ void MacroAssembler::Pref(int32_t hint, const MemOperand& rs) { ...@@ -1148,8 +1148,9 @@ void MacroAssembler::Pref(int32_t hint, const MemOperand& rs) {
void MacroAssembler::Lsa(Register rd, Register rt, Register rs, uint8_t sa, void MacroAssembler::Lsa(Register rd, Register rt, Register rs, uint8_t sa,
Register scratch) { Register scratch) {
DCHECK(sa >= 1 && sa <= 31);
if (IsMipsArchVariant(kMips32r6) && sa <= 4) { if (IsMipsArchVariant(kMips32r6) && sa <= 4) {
lsa(rd, rt, rs, sa); lsa(rd, rt, rs, sa - 1);
} else { } else {
Register tmp = rd.is(rt) ? scratch : rd; Register tmp = rd.is(rt) ? scratch : rd;
DCHECK(!tmp.is(rt)); DCHECK(!tmp.is(rt));
......
...@@ -647,8 +647,12 @@ class MacroAssembler: public Assembler { ...@@ -647,8 +647,12 @@ class MacroAssembler: public Assembler {
#undef DEFINE_INSTRUCTION2 #undef DEFINE_INSTRUCTION2
#undef DEFINE_INSTRUCTION3 #undef DEFINE_INSTRUCTION3
// Load Scaled Address instructions. Parameter sa (shift argument) must be
// between [1, 31] (inclusive). On pre-r6 architectures the scratch register
// may be clobbered.
void Lsa(Register rd, Register rs, Register rt, uint8_t sa, void Lsa(Register rd, Register rs, Register rt, uint8_t sa,
Register scratch = at); Register scratch = at);
void Pref(int32_t hint, const MemOperand& rs); void Pref(int32_t hint, const MemOperand& rs);
...@@ -1790,7 +1794,7 @@ void MacroAssembler::GenerateSwitchTable(Register index, size_t case_count, ...@@ -1790,7 +1794,7 @@ void MacroAssembler::GenerateSwitchTable(Register index, size_t case_count,
if (kArchVariant >= kMips32r6) { if (kArchVariant >= kMips32r6) {
BlockTrampolinePoolFor(case_count + 5); BlockTrampolinePoolFor(case_count + 5);
addiupc(at, 5); addiupc(at, 5);
lsa(at, at, index, kPointerSizeLog2); Lsa(at, at, index, kPointerSizeLog2);
lw(at, MemOperand(at)); lw(at, MemOperand(at));
} else { } else {
Label here; Label here;
......
...@@ -1905,20 +1905,20 @@ void Assembler::dsra32(Register rd, Register rt, uint16_t sa) { ...@@ -1905,20 +1905,20 @@ void Assembler::dsra32(Register rd, Register rt, uint16_t sa) {
void Assembler::lsa(Register rd, Register rt, Register rs, uint8_t sa) { void Assembler::lsa(Register rd, Register rt, Register rs, uint8_t sa) {
DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid()); DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid());
DCHECK(sa < 5 && sa > 0); DCHECK(sa <= 3);
DCHECK(kArchVariant == kMips64r6); DCHECK(kArchVariant == kMips64r6);
Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift) | Instr instr = SPECIAL | rs.code() << kRsShift | rt.code() << kRtShift |
(rd.code() << kRdShift) | (sa - 1) << kSaShift | LSA; rd.code() << kRdShift | sa << kSaShift | LSA;
emit(instr); emit(instr);
} }
void Assembler::dlsa(Register rd, Register rt, Register rs, uint8_t sa) { void Assembler::dlsa(Register rd, Register rt, Register rs, uint8_t sa) {
DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid()); DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid());
DCHECK(sa < 5 && sa > 0); DCHECK(sa <= 3);
DCHECK(kArchVariant == kMips64r6); DCHECK(kArchVariant == kMips64r6);
Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift) | Instr instr = SPECIAL | rs.code() << kRsShift | rt.code() << kRtShift |
(rd.code() << kRdShift) | (sa - 1) << kSaShift | DLSA; rd.code() << kRdShift | sa << kSaShift | DLSA;
emit(instr); emit(instr);
} }
......
...@@ -791,10 +791,6 @@ class Assembler : public AssemblerBase { ...@@ -791,10 +791,6 @@ class Assembler : public AssemblerBase {
void dsrl32(Register rt, Register rd, uint16_t sa); void dsrl32(Register rt, Register rd, uint16_t sa);
void dsra32(Register rt, Register rd, uint16_t sa); void dsra32(Register rt, Register rd, uint16_t sa);
// Address computing instructions with shift.
void lsa(Register rd, Register rt, Register rs, uint8_t sa);
void dlsa(Register rd, Register rt, Register rs, uint8_t sa);
// ------------Memory-instructions------------- // ------------Memory-instructions-------------
void lb(Register rd, const MemOperand& rs); void lb(Register rd, const MemOperand& rs);
...@@ -1209,6 +1205,10 @@ class Assembler : public AssemblerBase { ...@@ -1209,6 +1205,10 @@ class Assembler : public AssemblerBase {
bool IsPrevInstrCompactBranch() { return prev_instr_compact_branch_; } bool IsPrevInstrCompactBranch() { return prev_instr_compact_branch_; }
protected: protected:
// Load Scaled Address instructions.
void lsa(Register rd, Register rt, Register rs, uint8_t sa);
void dlsa(Register rd, Register rt, Register rs, uint8_t sa);
// Relocation for a type-recording IC has the AST id added to it. This // Relocation for a type-recording IC has the AST id added to it. This
// member variable is a way to pass the information from the call site to // member variable is a way to pass the information from the call site to
// the relocation info. // the relocation info.
......
...@@ -1294,8 +1294,9 @@ void MacroAssembler::Pref(int32_t hint, const MemOperand& rs) { ...@@ -1294,8 +1294,9 @@ void MacroAssembler::Pref(int32_t hint, const MemOperand& rs) {
void MacroAssembler::Lsa(Register rd, Register rt, Register rs, uint8_t sa, void MacroAssembler::Lsa(Register rd, Register rt, Register rs, uint8_t sa,
Register scratch) { Register scratch) {
DCHECK(sa >= 1 && sa <= 31);
if (kArchVariant == kMips64r6 && sa <= 4) { if (kArchVariant == kMips64r6 && sa <= 4) {
lsa(rd, rt, rs, sa); lsa(rd, rt, rs, sa - 1);
} else { } else {
Register tmp = rd.is(rt) ? scratch : rd; Register tmp = rd.is(rt) ? scratch : rd;
DCHECK(!tmp.is(rt)); DCHECK(!tmp.is(rt));
...@@ -1307,8 +1308,9 @@ void MacroAssembler::Lsa(Register rd, Register rt, Register rs, uint8_t sa, ...@@ -1307,8 +1308,9 @@ void MacroAssembler::Lsa(Register rd, Register rt, Register rs, uint8_t sa,
void MacroAssembler::Dlsa(Register rd, Register rt, Register rs, uint8_t sa, void MacroAssembler::Dlsa(Register rd, Register rt, Register rs, uint8_t sa,
Register scratch) { Register scratch) {
DCHECK(sa >= 1 && sa <= 31);
if (kArchVariant == kMips64r6 && sa <= 4) { if (kArchVariant == kMips64r6 && sa <= 4) {
dlsa(rd, rt, rs, sa); dlsa(rd, rt, rs, sa - 1);
} else { } else {
Register tmp = rd.is(rt) ? scratch : rd; Register tmp = rd.is(rt) ? scratch : rd;
DCHECK(!tmp.is(rt)); DCHECK(!tmp.is(rt));
......
...@@ -677,6 +677,9 @@ class MacroAssembler: public Assembler { ...@@ -677,6 +677,9 @@ class MacroAssembler: public Assembler {
#undef DEFINE_INSTRUCTION2 #undef DEFINE_INSTRUCTION2
#undef DEFINE_INSTRUCTION3 #undef DEFINE_INSTRUCTION3
// Load Scaled Address instructions. Parameter sa (shift argument) must be
// between [1, 31] (inclusive). On pre-r6 architectures the scratch register
// may be clobbered.
void Lsa(Register rd, Register rs, Register rt, uint8_t sa, void Lsa(Register rd, Register rs, Register rt, uint8_t sa,
Register scratch = at); Register scratch = at);
void Dlsa(Register rd, Register rs, Register rt, uint8_t sa, void Dlsa(Register rd, Register rs, Register rt, uint8_t sa,
...@@ -1954,7 +1957,7 @@ void MacroAssembler::GenerateSwitchTable(Register index, size_t case_count, ...@@ -1954,7 +1957,7 @@ void MacroAssembler::GenerateSwitchTable(Register index, size_t case_count,
nop(); nop();
} }
addiupc(at, 5); addiupc(at, 5);
dlsa(at, at, index, kPointerSizeLog2); Dlsa(at, at, index, kPointerSizeLog2);
ld(at, MemOperand(at)); ld(at, MemOperand(at));
} else { } else {
Label here; Label here;
......
...@@ -5360,78 +5360,6 @@ TEST(bal) { ...@@ -5360,78 +5360,6 @@ TEST(bal) {
} }
static uint32_t run_lsa(uint32_t rt, uint32_t rs, int8_t sa) {
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
MacroAssembler assm(isolate, nullptr, 0,
v8::internal::CodeObjectRequired::kYes);
__ lsa(v0, a0, a1, sa);
__ jr(ra);
__ nop();
CodeDesc desc;
assm.GetCode(&desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
F1 f = FUNCTION_CAST<F1>(code->entry());
uint32_t res = reinterpret_cast<uint32_t>(
CALL_GENERATED_CODE(isolate, f, rt, rs, 0, 0, 0));
return res;
}
TEST(lsa) {
if (!IsMipsArchVariant(kMips32r6)) return;
CcTest::InitializeVM();
struct TestCaseLsa {
int32_t rt;
int32_t rs;
uint8_t sa;
uint32_t expected_res;
};
struct TestCaseLsa tc[] = {
// rt, rs, sa, expected_res
{0x4, 0x1, 1, 0x6},
{0x4, 0x1, 2, 0x8},
{0x4, 0x1, 3, 0xc},
{0x4, 0x1, 4, 0x14},
{0x0, 0x1, 1, 0x2},
{0x0, 0x1, 2, 0x4},
{0x0, 0x1, 3, 0x8},
{0x0, 0x1, 4, 0x10},
{0x4, 0x0, 1, 0x4},
{0x4, 0x0, 2, 0x4},
{0x4, 0x0, 3, 0x4},
{0x4, 0x0, 4, 0x4},
{0x4, INT32_MAX, 1, 0x2}, // Shift overflow.
{0x4, INT32_MAX >> 1, 2, 0x0}, // Shift overflow.
{0x4, INT32_MAX >> 2, 3, 0xfffffffc}, // Shift overflow.
{0x4, INT32_MAX >> 3, 4, 0xfffffff4}, // Shift overflow.
{INT32_MAX - 1, 0x1, 1, 0x80000000}, // Signed adition overflow.
{INT32_MAX - 3, 0x1, 2, 0x80000000}, // Signed addition overflow.
{INT32_MAX - 7, 0x1, 3, 0x80000000}, // Signed addition overflow.
{INT32_MAX - 15, 0x1, 4, 0x80000000}, // Signed addition overflow.
{-2, 0x1, 1, 0x0}, // Addition overflow.
{-4, 0x1, 2, 0x0}, // Addition overflow.
{-8, 0x1, 3, 0x0}, // Addition overflow.
{-16, 0x1, 4, 0x0}}; // Addition overflow.
size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLsa);
for (size_t i = 0; i < nr_test_cases; ++i) {
uint32_t res = run_lsa(tc[i].rt, tc[i].rs, tc[i].sa);
PrintF("0x%x =? 0x%x == lsa(v0, %x, %x, %hhu)\n", tc[i].expected_res, res,
tc[i].rt, tc[i].rs, tc[i].sa);
CHECK_EQ(tc[i].expected_res, res);
}
}
TEST(Trampoline) { TEST(Trampoline) {
// Private member of Assembler class. // Private member of Assembler class.
static const int kMaxBranchOffset = (1 << (18 - 1)) - 1; static const int kMaxBranchOffset = (1 << (18 - 1)) - 1;
......
...@@ -267,7 +267,7 @@ TEST(jump_tables5) { ...@@ -267,7 +267,7 @@ TEST(jump_tables5) {
masm, kNumCases * kPointerSize + ((6 + 1) * Assembler::kInstrSize)); masm, kNumCases * kPointerSize + ((6 + 1) * Assembler::kInstrSize));
__ addiupc(at, 6 + 1); __ addiupc(at, 6 + 1);
__ lsa(at, at, a0, 2); __ Lsa(at, at, a0, 2);
__ lw(at, MemOperand(at)); __ lw(at, MemOperand(at));
__ jalr(at); __ jalr(at);
__ nop(); // Branch delay slot nop. __ nop(); // Branch delay slot nop.
......
...@@ -316,7 +316,7 @@ TEST(jump_tables5) { ...@@ -316,7 +316,7 @@ TEST(jump_tables5) {
masm, kNumCases * kPointerSize + ((6 + 1) * Assembler::kInstrSize)); masm, kNumCases * kPointerSize + ((6 + 1) * Assembler::kInstrSize));
__ addiupc(at, 6 + 1); __ addiupc(at, 6 + 1);
__ dlsa(at, at, a0, 3); __ Dlsa(at, at, a0, 3);
__ ld(at, MemOperand(at)); __ ld(at, MemOperand(at));
__ jalr(at); __ jalr(at);
__ nop(); // Branch delay slot nop. __ nop(); // Branch delay slot nop.
......
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