MIPS: Fix dd() implementations for compact branches.
BUG= Review URL: https://codereview.chromium.org/1573953002 Cr-Commit-Position: refs/heads/master@{#33249}
This commit is contained in:
parent
6cfe250868
commit
5091e8f2f5
@ -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()) {
|
||||
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 (Instruction::IsForbiddenAfterBranchInstr(x)) {
|
||||
// Nop instruction to preceed a CTI in forbidden slot:
|
||||
@ -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 v8
|
||||
|
||||
|
@ -2865,46 +2865,34 @@ void Assembler::GrowBuffer() {
|
||||
|
||||
|
||||
void Assembler::db(uint8_t data) {
|
||||
CheckBuffer();
|
||||
*reinterpret_cast<uint8_t*>(pc_) = data;
|
||||
pc_ += sizeof(uint8_t);
|
||||
CheckForEmitInForbiddenSlot();
|
||||
EmitHelper(data);
|
||||
}
|
||||
|
||||
|
||||
void Assembler::dd(uint32_t data) {
|
||||
CheckBuffer();
|
||||
*reinterpret_cast<uint32_t*>(pc_) = data;
|
||||
pc_ += sizeof(uint32_t);
|
||||
CheckForEmitInForbiddenSlot();
|
||||
EmitHelper(data);
|
||||
}
|
||||
|
||||
|
||||
void Assembler::dq(uint64_t data) {
|
||||
CheckBuffer();
|
||||
*reinterpret_cast<uint64_t*>(pc_) = data;
|
||||
pc_ += sizeof(uint64_t);
|
||||
CheckForEmitInForbiddenSlot();
|
||||
EmitHelper(data);
|
||||
}
|
||||
|
||||
|
||||
void Assembler::dd(Label* label) {
|
||||
CheckBuffer();
|
||||
RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
|
||||
uint32_t data;
|
||||
CheckForEmitInForbiddenSlot();
|
||||
if (label->is_bound()) {
|
||||
data = reinterpret_cast<uint32_t>(buffer_ + label->pos());
|
||||
} else {
|
||||
data = jump_address(label);
|
||||
internal_reference_positions_.insert(label->pos());
|
||||
}
|
||||
*reinterpret_cast<uint32_t*>(pc_) = data;
|
||||
pc_ += sizeof(uint32_t);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
|
||||
EmitHelper(data);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1049,9 +1049,6 @@ class Assembler : public AssemblerBase {
|
||||
void dp(uintptr_t data) { dd(data); }
|
||||
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_; }
|
||||
|
||||
// Postpone the generation of the trampoline pool for the specified number of
|
||||
@ -1261,6 +1258,11 @@ class Assembler : public AssemblerBase {
|
||||
void GrowBuffer();
|
||||
inline void emit(Instr x,
|
||||
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.
|
||||
// We have 3 different kind of encoding layout on MIPS.
|
||||
|
@ -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()) {
|
||||
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 (Instruction::IsForbiddenAfterBranchInstr(x)) {
|
||||
// Nop instruction to preceed a CTI in forbidden slot:
|
||||
@ -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()) {
|
||||
CheckBuffer();
|
||||
}
|
||||
if (IsPrevInstrCompactBranch()) {
|
||||
// Nop instruction to preceed a CTI in forbidden slot:
|
||||
Instr nop = SPECIAL | SLL;
|
||||
*reinterpret_cast<Instr*>(pc_) = nop;
|
||||
pc_ += kInstrSize;
|
||||
EmitHelper(x, is_compact_branch);
|
||||
}
|
||||
|
||||
ClearCompactBranchState();
|
||||
}
|
||||
*reinterpret_cast<uint64_t*>(pc_) = x;
|
||||
pc_ += kInstrSize * 2;
|
||||
CheckTrampolinePoolQuick();
|
||||
|
||||
void Assembler::emit(uint64_t data) {
|
||||
CheckForEmitInForbiddenSlot();
|
||||
EmitHelper(data);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3175,46 +3175,34 @@ void Assembler::GrowBuffer() {
|
||||
|
||||
|
||||
void Assembler::db(uint8_t data) {
|
||||
CheckBuffer();
|
||||
*reinterpret_cast<uint8_t*>(pc_) = data;
|
||||
pc_ += sizeof(uint8_t);
|
||||
CheckForEmitInForbiddenSlot();
|
||||
EmitHelper(data);
|
||||
}
|
||||
|
||||
|
||||
void Assembler::dd(uint32_t data) {
|
||||
CheckBuffer();
|
||||
*reinterpret_cast<uint32_t*>(pc_) = data;
|
||||
pc_ += sizeof(uint32_t);
|
||||
CheckForEmitInForbiddenSlot();
|
||||
EmitHelper(data);
|
||||
}
|
||||
|
||||
|
||||
void Assembler::dq(uint64_t data) {
|
||||
CheckBuffer();
|
||||
*reinterpret_cast<uint64_t*>(pc_) = data;
|
||||
pc_ += sizeof(uint64_t);
|
||||
CheckForEmitInForbiddenSlot();
|
||||
EmitHelper(data);
|
||||
}
|
||||
|
||||
|
||||
void Assembler::dd(Label* label) {
|
||||
CheckBuffer();
|
||||
RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
|
||||
uint64_t data;
|
||||
CheckForEmitInForbiddenSlot();
|
||||
if (label->is_bound()) {
|
||||
data = reinterpret_cast<uint64_t>(buffer_ + label->pos());
|
||||
} else {
|
||||
data = jump_address(label);
|
||||
internal_reference_positions_.insert(label->pos());
|
||||
}
|
||||
*reinterpret_cast<uint64_t*>(pc_) = data;
|
||||
pc_ += sizeof(uint64_t);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
|
||||
EmitHelper(data);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1105,9 +1105,6 @@ class Assembler : public AssemblerBase {
|
||||
void dp(uintptr_t data) { dq(data); }
|
||||
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_; }
|
||||
|
||||
// Postpone the generation of the trampoline pool for the specified number of
|
||||
@ -1329,6 +1326,10 @@ class Assembler : public AssemblerBase {
|
||||
inline void emit(Instr x,
|
||||
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.
|
||||
// We have 3 different kind of encoding layout on MIPS.
|
||||
|
@ -5091,9 +5091,8 @@ int32_t run_bc(int32_t offset) {
|
||||
__ li(t8, 0);
|
||||
__ 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) {
|
||||
__ dd(instruction_addiu);
|
||||
__ addiu(v0, v0, 1);
|
||||
}
|
||||
|
||||
__ addiu(t8, t8, 1); // -10
|
||||
@ -5112,7 +5111,7 @@ int32_t run_bc(int32_t offset) {
|
||||
__ bc(offset); // -1
|
||||
|
||||
for (int32_t i = 0; i <= 99; ++i) {
|
||||
__ dd(instruction_addiu);
|
||||
__ addiu(v0, v0, 1);
|
||||
}
|
||||
|
||||
__ pop(ra);
|
||||
|
@ -3222,9 +3222,7 @@ TEST(jump_tables1) {
|
||||
|
||||
__ daddiu(sp, sp, -8);
|
||||
__ sd(ra, MemOperand(sp));
|
||||
if ((assm.pc_offset() & 7) == 0) {
|
||||
__ nop();
|
||||
}
|
||||
__ Align(8);
|
||||
|
||||
Label done;
|
||||
{
|
||||
@ -3304,9 +3302,7 @@ TEST(jump_tables2) {
|
||||
__ nop();
|
||||
}
|
||||
|
||||
if ((assm.pc_offset() & 7) == 0) {
|
||||
__ nop();
|
||||
}
|
||||
__ Align(8);
|
||||
__ bind(&dispatch);
|
||||
{
|
||||
__ BlockTrampolinePoolFor(kNumCases * 2 + 7);
|
||||
@ -3372,6 +3368,7 @@ TEST(jump_tables3) {
|
||||
|
||||
Label done, dispatch;
|
||||
__ b(&dispatch);
|
||||
__ nop();
|
||||
|
||||
|
||||
for (int i = 0; i < kNumCases; ++i) {
|
||||
@ -3386,10 +3383,7 @@ TEST(jump_tables3) {
|
||||
__ nop();
|
||||
}
|
||||
|
||||
__ stop("chk");
|
||||
if ((assm.pc_offset() & 7) == 0) {
|
||||
__ nop();
|
||||
}
|
||||
__ Align(8);
|
||||
__ bind(&dispatch);
|
||||
{
|
||||
__ BlockTrampolinePoolFor(kNumCases * 2 + 7);
|
||||
@ -5547,9 +5541,8 @@ int64_t run_bc(int32_t offset) {
|
||||
__ li(t8, 0);
|
||||
__ 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) {
|
||||
__ dd(instruction_addiu);
|
||||
__ addiu(v0, v0, 1);
|
||||
}
|
||||
|
||||
__ addiu(t8, t8, 1); // -10
|
||||
@ -5568,7 +5561,7 @@ int64_t run_bc(int32_t offset) {
|
||||
__ bc(offset); // -1
|
||||
|
||||
for (int32_t i = 0; i <= 99; ++i) {
|
||||
__ dd(instruction_addiu);
|
||||
__ addiu(v0, v0, 1);
|
||||
}
|
||||
|
||||
__ pop(ra);
|
||||
|
@ -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) {
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
HandleScope scope(isolate);
|
||||
|
@ -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) {
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
HandleScope scope(isolate);
|
||||
|
Loading…
Reference in New Issue
Block a user