Commit 5091e8f2 authored by balazs.kilvady's avatar balazs.kilvady Committed by Commit bot

MIPS: Fix dd() implementations for compact branches.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#33249}
parent 6cfe2508
...@@ -437,10 +437,22 @@ void Assembler::CheckTrampolinePoolQuick(int extra_instructions) { ...@@ -437,10 +437,22 @@ void Assembler::CheckTrampolinePoolQuick(int extra_instructions) {
} }
void Assembler::emit(Instr x, CompactBranchType is_compact_branch) { void Assembler::CheckForEmitInForbiddenSlot() {
if (!is_buffer_growth_blocked()) { if (!is_buffer_growth_blocked()) {
CheckBuffer(); CheckBuffer();
} }
if (IsPrevInstrCompactBranch()) {
// Nop instruction to preceed a CTI in forbidden slot:
Instr nop = SPECIAL | SLL;
*reinterpret_cast<Instr*>(pc_) = nop;
pc_ += kInstrSize;
ClearCompactBranchState();
}
}
void Assembler::EmitHelper(Instr x, CompactBranchType is_compact_branch) {
if (IsPrevInstrCompactBranch()) { if (IsPrevInstrCompactBranch()) {
if (Instruction::IsForbiddenAfterBranchInstr(x)) { if (Instruction::IsForbiddenAfterBranchInstr(x)) {
// Nop instruction to preceed a CTI in forbidden slot: // Nop instruction to preceed a CTI in forbidden slot:
...@@ -459,6 +471,22 @@ void Assembler::emit(Instr x, CompactBranchType is_compact_branch) { ...@@ -459,6 +471,22 @@ void Assembler::emit(Instr x, CompactBranchType is_compact_branch) {
} }
template <typename T>
void Assembler::EmitHelper(T x) {
*reinterpret_cast<T*>(pc_) = x;
pc_ += sizeof(x);
CheckTrampolinePoolQuick();
}
void Assembler::emit(Instr x, CompactBranchType is_compact_branch) {
if (!is_buffer_growth_blocked()) {
CheckBuffer();
}
EmitHelper(x, is_compact_branch);
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -2865,46 +2865,34 @@ void Assembler::GrowBuffer() { ...@@ -2865,46 +2865,34 @@ void Assembler::GrowBuffer() {
void Assembler::db(uint8_t data) { void Assembler::db(uint8_t data) {
CheckBuffer(); CheckForEmitInForbiddenSlot();
*reinterpret_cast<uint8_t*>(pc_) = data; EmitHelper(data);
pc_ += sizeof(uint8_t);
} }
void Assembler::dd(uint32_t data) { void Assembler::dd(uint32_t data) {
CheckBuffer(); CheckForEmitInForbiddenSlot();
*reinterpret_cast<uint32_t*>(pc_) = data; EmitHelper(data);
pc_ += sizeof(uint32_t);
} }
void Assembler::dq(uint64_t data) { void Assembler::dq(uint64_t data) {
CheckBuffer(); CheckForEmitInForbiddenSlot();
*reinterpret_cast<uint64_t*>(pc_) = data; EmitHelper(data);
pc_ += sizeof(uint64_t);
} }
void Assembler::dd(Label* label) { void Assembler::dd(Label* label) {
CheckBuffer();
RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
uint32_t data; uint32_t data;
CheckForEmitInForbiddenSlot();
if (label->is_bound()) { if (label->is_bound()) {
data = reinterpret_cast<uint32_t>(buffer_ + label->pos()); data = reinterpret_cast<uint32_t>(buffer_ + label->pos());
} else { } else {
data = jump_address(label); data = jump_address(label);
internal_reference_positions_.insert(label->pos()); internal_reference_positions_.insert(label->pos());
} }
*reinterpret_cast<uint32_t*>(pc_) = data; RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
pc_ += sizeof(uint32_t); EmitHelper(data);
}
void Assembler::emit_code_stub_address(Code* stub) {
CheckBuffer();
*reinterpret_cast<uint32_t*>(pc_) =
reinterpret_cast<uint32_t>(stub->instruction_start());
pc_ += sizeof(uint32_t);
} }
......
...@@ -1049,9 +1049,6 @@ class Assembler : public AssemblerBase { ...@@ -1049,9 +1049,6 @@ class Assembler : public AssemblerBase {
void dp(uintptr_t data) { dd(data); } void dp(uintptr_t data) { dd(data); }
void dd(Label* label); void dd(Label* label);
// Emits the address of the code stub's first instruction.
void emit_code_stub_address(Code* stub);
PositionsRecorder* positions_recorder() { return &positions_recorder_; } PositionsRecorder* positions_recorder() { return &positions_recorder_; }
// Postpone the generation of the trampoline pool for the specified number of // Postpone the generation of the trampoline pool for the specified number of
...@@ -1261,6 +1258,11 @@ class Assembler : public AssemblerBase { ...@@ -1261,6 +1258,11 @@ class Assembler : public AssemblerBase {
void GrowBuffer(); void GrowBuffer();
inline void emit(Instr x, inline void emit(Instr x,
CompactBranchType is_compact_branch = CompactBranchType::NO); CompactBranchType is_compact_branch = CompactBranchType::NO);
inline void emit(uint64_t x);
inline void CheckForEmitInForbiddenSlot();
template <typename T>
inline void EmitHelper(T x);
inline void EmitHelper(Instr x, CompactBranchType is_compact_branch);
// Instruction generation. // Instruction generation.
// We have 3 different kind of encoding layout on MIPS. // We have 3 different kind of encoding layout on MIPS.
......
...@@ -438,10 +438,22 @@ void Assembler::CheckTrampolinePoolQuick(int extra_instructions) { ...@@ -438,10 +438,22 @@ void Assembler::CheckTrampolinePoolQuick(int extra_instructions) {
} }
void Assembler::emit(Instr x, CompactBranchType is_compact_branch) { void Assembler::CheckForEmitInForbiddenSlot() {
if (!is_buffer_growth_blocked()) { if (!is_buffer_growth_blocked()) {
CheckBuffer(); CheckBuffer();
} }
if (IsPrevInstrCompactBranch()) {
// Nop instruction to preceed a CTI in forbidden slot:
Instr nop = SPECIAL | SLL;
*reinterpret_cast<Instr*>(pc_) = nop;
pc_ += kInstrSize;
ClearCompactBranchState();
}
}
void Assembler::EmitHelper(Instr x, CompactBranchType is_compact_branch) {
if (IsPrevInstrCompactBranch()) { if (IsPrevInstrCompactBranch()) {
if (Instruction::IsForbiddenAfterBranchInstr(x)) { if (Instruction::IsForbiddenAfterBranchInstr(x)) {
// Nop instruction to preceed a CTI in forbidden slot: // Nop instruction to preceed a CTI in forbidden slot:
...@@ -460,21 +472,25 @@ void Assembler::emit(Instr x, CompactBranchType is_compact_branch) { ...@@ -460,21 +472,25 @@ void Assembler::emit(Instr x, CompactBranchType is_compact_branch) {
} }
void Assembler::emit(uint64_t x) { template <typename T>
void Assembler::EmitHelper(T x) {
*reinterpret_cast<T*>(pc_) = x;
pc_ += sizeof(x);
CheckTrampolinePoolQuick();
}
void Assembler::emit(Instr x, CompactBranchType is_compact_branch) {
if (!is_buffer_growth_blocked()) { if (!is_buffer_growth_blocked()) {
CheckBuffer(); CheckBuffer();
} }
if (IsPrevInstrCompactBranch()) { EmitHelper(x, is_compact_branch);
// Nop instruction to preceed a CTI in forbidden slot: }
Instr nop = SPECIAL | SLL;
*reinterpret_cast<Instr*>(pc_) = nop;
pc_ += kInstrSize;
ClearCompactBranchState();
} void Assembler::emit(uint64_t data) {
*reinterpret_cast<uint64_t*>(pc_) = x; CheckForEmitInForbiddenSlot();
pc_ += kInstrSize * 2; EmitHelper(data);
CheckTrampolinePoolQuick();
} }
......
...@@ -3175,46 +3175,34 @@ void Assembler::GrowBuffer() { ...@@ -3175,46 +3175,34 @@ void Assembler::GrowBuffer() {
void Assembler::db(uint8_t data) { void Assembler::db(uint8_t data) {
CheckBuffer(); CheckForEmitInForbiddenSlot();
*reinterpret_cast<uint8_t*>(pc_) = data; EmitHelper(data);
pc_ += sizeof(uint8_t);
} }
void Assembler::dd(uint32_t data) { void Assembler::dd(uint32_t data) {
CheckBuffer(); CheckForEmitInForbiddenSlot();
*reinterpret_cast<uint32_t*>(pc_) = data; EmitHelper(data);
pc_ += sizeof(uint32_t);
} }
void Assembler::dq(uint64_t data) { void Assembler::dq(uint64_t data) {
CheckBuffer(); CheckForEmitInForbiddenSlot();
*reinterpret_cast<uint64_t*>(pc_) = data; EmitHelper(data);
pc_ += sizeof(uint64_t);
} }
void Assembler::dd(Label* label) { void Assembler::dd(Label* label) {
CheckBuffer();
RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
uint64_t data; uint64_t data;
CheckForEmitInForbiddenSlot();
if (label->is_bound()) { if (label->is_bound()) {
data = reinterpret_cast<uint64_t>(buffer_ + label->pos()); data = reinterpret_cast<uint64_t>(buffer_ + label->pos());
} else { } else {
data = jump_address(label); data = jump_address(label);
internal_reference_positions_.insert(label->pos()); internal_reference_positions_.insert(label->pos());
} }
*reinterpret_cast<uint64_t*>(pc_) = data; RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
pc_ += sizeof(uint64_t); EmitHelper(data);
}
void Assembler::emit_code_stub_address(Code* stub) {
CheckBuffer();
*reinterpret_cast<uint64_t*>(pc_) =
reinterpret_cast<uint64_t>(stub->instruction_start());
pc_ += sizeof(uint64_t);
} }
......
...@@ -1105,9 +1105,6 @@ class Assembler : public AssemblerBase { ...@@ -1105,9 +1105,6 @@ class Assembler : public AssemblerBase {
void dp(uintptr_t data) { dq(data); } void dp(uintptr_t data) { dq(data); }
void dd(Label* label); void dd(Label* label);
// Emits the address of the code stub's first instruction.
void emit_code_stub_address(Code* stub);
PositionsRecorder* positions_recorder() { return &positions_recorder_; } PositionsRecorder* positions_recorder() { return &positions_recorder_; }
// Postpone the generation of the trampoline pool for the specified number of // Postpone the generation of the trampoline pool for the specified number of
...@@ -1329,6 +1326,10 @@ class Assembler : public AssemblerBase { ...@@ -1329,6 +1326,10 @@ class Assembler : public AssemblerBase {
inline void emit(Instr x, inline void emit(Instr x,
CompactBranchType is_compact_branch = CompactBranchType::NO); CompactBranchType is_compact_branch = CompactBranchType::NO);
inline void emit(uint64_t x); inline void emit(uint64_t x);
inline void CheckForEmitInForbiddenSlot();
template <typename T>
inline void EmitHelper(T x);
inline void EmitHelper(Instr x, CompactBranchType is_compact_branch);
// Instruction generation. // Instruction generation.
// We have 3 different kind of encoding layout on MIPS. // We have 3 different kind of encoding layout on MIPS.
......
...@@ -5091,9 +5091,8 @@ int32_t run_bc(int32_t offset) { ...@@ -5091,9 +5091,8 @@ int32_t run_bc(int32_t offset) {
__ li(t8, 0); __ li(t8, 0);
__ li(t9, 2); // A condition for stopping execution. __ li(t9, 2); // A condition for stopping execution.
uint32_t instruction_addiu = 0x24420001; // addiu v0, v0, 1
for (int32_t i = -100; i <= -11; ++i) { for (int32_t i = -100; i <= -11; ++i) {
__ dd(instruction_addiu); __ addiu(v0, v0, 1);
} }
__ addiu(t8, t8, 1); // -10 __ addiu(t8, t8, 1); // -10
...@@ -5112,7 +5111,7 @@ int32_t run_bc(int32_t offset) { ...@@ -5112,7 +5111,7 @@ int32_t run_bc(int32_t offset) {
__ bc(offset); // -1 __ bc(offset); // -1
for (int32_t i = 0; i <= 99; ++i) { for (int32_t i = 0; i <= 99; ++i) {
__ dd(instruction_addiu); __ addiu(v0, v0, 1);
} }
__ pop(ra); __ pop(ra);
......
...@@ -3222,9 +3222,7 @@ TEST(jump_tables1) { ...@@ -3222,9 +3222,7 @@ TEST(jump_tables1) {
__ daddiu(sp, sp, -8); __ daddiu(sp, sp, -8);
__ sd(ra, MemOperand(sp)); __ sd(ra, MemOperand(sp));
if ((assm.pc_offset() & 7) == 0) { __ Align(8);
__ nop();
}
Label done; Label done;
{ {
...@@ -3304,9 +3302,7 @@ TEST(jump_tables2) { ...@@ -3304,9 +3302,7 @@ TEST(jump_tables2) {
__ nop(); __ nop();
} }
if ((assm.pc_offset() & 7) == 0) { __ Align(8);
__ nop();
}
__ bind(&dispatch); __ bind(&dispatch);
{ {
__ BlockTrampolinePoolFor(kNumCases * 2 + 7); __ BlockTrampolinePoolFor(kNumCases * 2 + 7);
...@@ -3372,6 +3368,7 @@ TEST(jump_tables3) { ...@@ -3372,6 +3368,7 @@ TEST(jump_tables3) {
Label done, dispatch; Label done, dispatch;
__ b(&dispatch); __ b(&dispatch);
__ nop();
for (int i = 0; i < kNumCases; ++i) { for (int i = 0; i < kNumCases; ++i) {
...@@ -3386,10 +3383,7 @@ TEST(jump_tables3) { ...@@ -3386,10 +3383,7 @@ TEST(jump_tables3) {
__ nop(); __ nop();
} }
__ stop("chk"); __ Align(8);
if ((assm.pc_offset() & 7) == 0) {
__ nop();
}
__ bind(&dispatch); __ bind(&dispatch);
{ {
__ BlockTrampolinePoolFor(kNumCases * 2 + 7); __ BlockTrampolinePoolFor(kNumCases * 2 + 7);
...@@ -5547,9 +5541,8 @@ int64_t run_bc(int32_t offset) { ...@@ -5547,9 +5541,8 @@ int64_t run_bc(int32_t offset) {
__ li(t8, 0); __ li(t8, 0);
__ li(t9, 2); // Condition for the stopping execution. __ li(t9, 2); // Condition for the stopping execution.
uint32_t instruction_addiu = 0x24420001; // addiu v0, v0, 1
for (int32_t i = -100; i <= -11; ++i) { for (int32_t i = -100; i <= -11; ++i) {
__ dd(instruction_addiu); __ addiu(v0, v0, 1);
} }
__ addiu(t8, t8, 1); // -10 __ addiu(t8, t8, 1); // -10
...@@ -5568,7 +5561,7 @@ int64_t run_bc(int32_t offset) { ...@@ -5568,7 +5561,7 @@ int64_t run_bc(int32_t offset) {
__ bc(offset); // -1 __ bc(offset); // -1
for (int32_t i = 0; i <= 99; ++i) { for (int32_t i = 0; i <= 99; ++i) {
__ dd(instruction_addiu); __ addiu(v0, v0, 1);
} }
__ pop(ra); __ pop(ra);
......
...@@ -261,6 +261,77 @@ TEST(jump_tables4) { ...@@ -261,6 +261,77 @@ TEST(jump_tables4) {
} }
TEST(jump_tables5) {
if (!IsMipsArchVariant(kMips32r6)) return;
// Similar to test-assembler-mips jump_tables1, with extra test for emitting a
// compact branch instruction before emission of the dd table.
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
MacroAssembler assembler(isolate, nullptr, 0,
v8::internal::CodeObjectRequired::kYes);
MacroAssembler* masm = &assembler;
const int kNumCases = 512;
int values[kNumCases];
isolate->random_number_generator()->NextBytes(values, sizeof(values));
Label labels[kNumCases];
Label done;
__ addiu(sp, sp, -4);
__ sw(ra, MemOperand(sp));
{
__ BlockTrampolinePoolFor(kNumCases * 2 + 7 + 1);
PredictableCodeSizeScope predictable(
masm, kNumCases * kPointerSize + ((7 + 1) * Assembler::kInstrSize));
Label here;
__ bal(&here);
__ sll(at, a0, 3); // In delay slot.
__ bind(&here);
__ addu(at, at, ra);
__ lw(at, MemOperand(at, 6 * Assembler::kInstrSize));
__ jalr(at);
__ nop(); // Branch delay slot nop.
__ bc(&done);
for (int i = 0; i < kNumCases; ++i) {
__ dd(&labels[i]);
}
}
for (int i = 0; i < kNumCases; ++i) {
__ bind(&labels[i]);
__ lui(v0, (values[i] >> 16) & 0xffff);
__ ori(v0, v0, values[i] & 0xffff);
__ jr(ra);
__ nop();
}
__ bind(&done);
__ lw(ra, MemOperand(sp));
__ addiu(sp, sp, 4);
__ jr(ra);
__ nop();
CodeDesc desc;
masm->GetCode(&desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef OBJECT_PRINT
code->Print(std::cout);
#endif
F1 f = FUNCTION_CAST<F1>(code->entry());
for (int i = 0; i < kNumCases; ++i) {
int64_t res = reinterpret_cast<int64_t>(
CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0));
::printf("f(%d) = %" PRId64 "\n", i, res);
CHECK_EQ(values[i], res);
}
}
static uint32_t run_lsa(uint32_t rt, uint32_t rs, int8_t sa) { static uint32_t run_lsa(uint32_t rt, uint32_t rs, int8_t sa) {
Isolate* isolate = CcTest::i_isolate(); Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate); HandleScope scope(isolate);
......
...@@ -305,6 +305,78 @@ TEST(jump_tables4) { ...@@ -305,6 +305,78 @@ TEST(jump_tables4) {
} }
TEST(jump_tables5) {
if (kArchVariant != kMips64r6) return;
// Similar to test-assembler-mips jump_tables1, with extra test for emitting a
// compact branch instruction before emission of the dd table.
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
MacroAssembler assembler(isolate, nullptr, 0,
v8::internal::CodeObjectRequired::kYes);
MacroAssembler* masm = &assembler;
const int kNumCases = 512;
int values[kNumCases];
isolate->random_number_generator()->NextBytes(values, sizeof(values));
Label labels[kNumCases];
Label done;
__ daddiu(sp, sp, -8);
__ sd(ra, MemOperand(sp));
__ Align(8);
{
__ BlockTrampolinePoolFor(kNumCases * 2 + 7 + 1);
PredictableCodeSizeScope predictable(
masm, kNumCases * kPointerSize + ((7 + 1) * Assembler::kInstrSize));
Label here;
__ bal(&here);
__ dsll(at, a0, 3); // In delay slot.
__ bind(&here);
__ daddu(at, at, ra);
__ ld(at, MemOperand(at, 6 * Assembler::kInstrSize));
__ jalr(at);
__ nop(); // Branch delay slot nop.
__ bc(&done);
for (int i = 0; i < kNumCases; ++i) {
__ dd(&labels[i]);
}
}
for (int i = 0; i < kNumCases; ++i) {
__ bind(&labels[i]);
__ lui(v0, (values[i] >> 16) & 0xffff);
__ ori(v0, v0, values[i] & 0xffff);
__ jr(ra);
__ nop();
}
__ bind(&done);
__ ld(ra, MemOperand(sp));
__ daddiu(sp, sp, 8);
__ jr(ra);
__ nop();
CodeDesc desc;
masm->GetCode(&desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef OBJECT_PRINT
code->Print(std::cout);
#endif
F1 f = FUNCTION_CAST<F1>(code->entry());
for (int i = 0; i < kNumCases; ++i) {
int64_t res = reinterpret_cast<int64_t>(
CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0));
::printf("f(%d) = %" PRId64 "\n", i, res);
CHECK_EQ(values[i], res);
}
}
static uint64_t run_lsa(uint32_t rt, uint32_t rs, int8_t sa) { static uint64_t run_lsa(uint32_t rt, uint32_t rs, int8_t sa) {
Isolate* isolate = CcTest::i_isolate(); Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate); HandleScope scope(isolate);
......
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