Commit c91bcf71 authored by balazs.kilvady's avatar balazs.kilvady Committed by Commit bot

MIPS: Fix trampoline pool handling in MacroAssembler::BranchShort() for r6.

BUG=chromium:555543
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#32094}
parent eb8a4238
......@@ -1367,10 +1367,12 @@ void Assembler::bgezalc(Register rt, int16_t offset) {
void Assembler::bgezall(Register rs, int16_t offset) {
DCHECK(IsMipsArchVariant(kMips32r6));
DCHECK(!IsMipsArchVariant(kMips32r6));
DCHECK(!(rs.is(zero_reg)));
BlockTrampolinePoolScope block_trampoline_pool(this);
positions_recorder()->WriteRecordedPositions();
GenInstrImmediate(REGIMM, rs, BGEZALL, offset);
BlockTrampolinePoolFor(1); // For associated delay slot.
}
......@@ -1453,7 +1455,9 @@ void Assembler::j(int32_t target) {
(kImm26Bits + kImmFieldShift)) == 0;
DCHECK(in_range && ((target & 3) == 0));
#endif
BlockTrampolinePoolScope block_trampoline_pool(this);
GenInstrJump(J, (target >> 2) & kImm26Mask);
BlockTrampolinePoolFor(1); // For associated delay slot.
}
......@@ -1479,8 +1483,10 @@ void Assembler::jal(int32_t target) {
(kImm26Bits + kImmFieldShift)) == 0;
DCHECK(in_range && ((target & 3) == 0));
#endif
BlockTrampolinePoolScope block_trampoline_pool(this);
positions_recorder()->WriteRecordedPositions();
GenInstrJump(JAL, (target >> 2) & kImm26Mask);
BlockTrampolinePoolFor(1); // For associated delay slot.
}
......
......@@ -1208,6 +1208,8 @@ class Assembler : public AssemblerBase {
return block_buffer_growth_;
}
inline void CheckTrampolinePoolQuick(int extra_instructions = 0);
private:
inline static void set_target_internal_reference_encoded_at(Address pc,
Address target);
......@@ -1258,7 +1260,6 @@ class Assembler : public AssemblerBase {
void GrowBuffer();
inline void emit(Instr x,
CompactBranchType is_compact_branch = CompactBranchType::NO);
inline void CheckTrampolinePoolQuick(int extra_instructions = 0);
// Instruction generation.
// We have 3 different kind of encoding layout on MIPS.
......
......@@ -2094,270 +2094,273 @@ bool MacroAssembler::BranchShortHelperR6(int32_t offset, Label* L,
// Be careful to always use shifted_branch_offset only just before the
// branch instruction, as the location will be remember for patching the
// target.
BlockTrampolinePoolScope block_trampoline_pool(this);
switch (cond) {
case cc_always:
bits = OffsetSize::kOffset26;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bc(offset);
break;
case eq:
if (rs.code() == rt.rm_.reg_code) {
// Pre R6 beq is used here to make the code patchable. Otherwise bc
// should be used which has no condition field so is not patchable.
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
beq(rs, scratch, offset);
nop();
} else if (IsZero(rt)) {
bits = OffsetSize::kOffset21;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
beqzc(rs, offset);
} else {
// We don't want any other register but scratch clobbered.
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
beqc(rs, scratch, offset);
}
break;
case ne:
if (rs.code() == rt.rm_.reg_code) {
// Pre R6 bne is used here to make the code patchable. Otherwise we
// should not generate any instruction.
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
bne(rs, scratch, offset);
nop();
} else if (IsZero(rt)) {
bits = OffsetSize::kOffset21;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bnezc(rs, offset);
} else {
// We don't want any other register but scratch clobbered.
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
bnec(rs, scratch, offset);
}
break;
// Signed comparison.
case greater:
// rs > rt
if (rs.code() == rt.rm_.reg_code) {
break; // No code needs to be emitted.
} else if (rs.is(zero_reg)) {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
bltzc(scratch, offset);
} else if (IsZero(rt)) {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bgtzc(rs, offset);
} else {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
DCHECK(!rs.is(scratch));
offset = GetOffset(offset, L, bits);
bltc(scratch, rs, offset);
}
break;
case greater_equal:
// rs >= rt
if (rs.code() == rt.rm_.reg_code) {
bits = OffsetSize::kOffset26;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bc(offset);
} else if (rs.is(zero_reg)) {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
blezc(scratch, offset);
} else if (IsZero(rt)) {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bgezc(rs, offset);
} else {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
DCHECK(!rs.is(scratch));
offset = GetOffset(offset, L, bits);
bgec(rs, scratch, offset);
}
break;
case less:
// rs < rt
if (rs.code() == rt.rm_.reg_code) {
break; // No code needs to be emitted.
} else if (rs.is(zero_reg)) {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
bgtzc(scratch, offset);
} else if (IsZero(rt)) {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bltzc(rs, offset);
} else {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
DCHECK(!rs.is(scratch));
offset = GetOffset(offset, L, bits);
bltc(rs, scratch, offset);
}
break;
case less_equal:
// rs <= rt
if (rs.code() == rt.rm_.reg_code) {
{
BlockTrampolinePoolScope block_trampoline_pool(this);
switch (cond) {
case cc_always:
bits = OffsetSize::kOffset26;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bc(offset);
} else if (rs.is(zero_reg)) {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
bgezc(scratch, offset);
} else if (IsZero(rt)) {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
blezc(rs, offset);
} else {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
DCHECK(!rs.is(scratch));
offset = GetOffset(offset, L, bits);
bgec(scratch, rs, offset);
}
break;
break;
case eq:
if (rs.code() == rt.rm_.reg_code) {
// Pre R6 beq is used here to make the code patchable. Otherwise bc
// should be used which has no condition field so is not patchable.
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
beq(rs, scratch, offset);
nop();
} else if (IsZero(rt)) {
bits = OffsetSize::kOffset21;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
beqzc(rs, offset);
} else {
// We don't want any other register but scratch clobbered.
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
beqc(rs, scratch, offset);
}
break;
case ne:
if (rs.code() == rt.rm_.reg_code) {
// Pre R6 bne is used here to make the code patchable. Otherwise we
// should not generate any instruction.
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
bne(rs, scratch, offset);
nop();
} else if (IsZero(rt)) {
bits = OffsetSize::kOffset21;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bnezc(rs, offset);
} else {
// We don't want any other register but scratch clobbered.
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
bnec(rs, scratch, offset);
}
break;
// Unsigned comparison.
case Ugreater:
// rs > rt
if (rs.code() == rt.rm_.reg_code) {
break; // No code needs to be emitted.
} else if (rs.is(zero_reg)) {
bits = OffsetSize::kOffset21;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
bnezc(scratch, offset);
} else if (IsZero(rt)) {
bits = OffsetSize::kOffset21;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bnezc(rs, offset);
} else {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
DCHECK(!rs.is(scratch));
offset = GetOffset(offset, L, bits);
bltuc(scratch, rs, offset);
}
break;
case Ugreater_equal:
// rs >= rt
if (rs.code() == rt.rm_.reg_code) {
bits = OffsetSize::kOffset26;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bc(offset);
} else if (rs.is(zero_reg)) {
bits = OffsetSize::kOffset21;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
beqzc(scratch, offset);
} else if (IsZero(rt)) {
bits = OffsetSize::kOffset26;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bc(offset);
} else {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
DCHECK(!rs.is(scratch));
offset = GetOffset(offset, L, bits);
bgeuc(rs, scratch, offset);
}
break;
case Uless:
// rs < rt
if (rs.code() == rt.rm_.reg_code) {
break; // No code needs to be emitted.
} else if (rs.is(zero_reg)) {
bits = OffsetSize::kOffset21;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
bnezc(scratch, offset);
} else if (IsZero(rt)) {
break; // No code needs to be emitted.
} else {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
DCHECK(!rs.is(scratch));
offset = GetOffset(offset, L, bits);
bltuc(rs, scratch, offset);
}
break;
case Uless_equal:
// rs <= rt
if (rs.code() == rt.rm_.reg_code) {
bits = OffsetSize::kOffset26;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bc(offset);
} else if (rs.is(zero_reg)) {
bits = OffsetSize::kOffset26;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
bc(offset);
} else if (IsZero(rt)) {
bits = OffsetSize::kOffset21;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
beqzc(rs, offset);
} else {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
DCHECK(!rs.is(scratch));
offset = GetOffset(offset, L, bits);
bgeuc(scratch, rs, offset);
}
break;
default:
UNREACHABLE();
// Signed comparison.
case greater:
// rs > rt
if (rs.code() == rt.rm_.reg_code) {
break; // No code needs to be emitted.
} else if (rs.is(zero_reg)) {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
bltzc(scratch, offset);
} else if (IsZero(rt)) {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bgtzc(rs, offset);
} else {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
DCHECK(!rs.is(scratch));
offset = GetOffset(offset, L, bits);
bltc(scratch, rs, offset);
}
break;
case greater_equal:
// rs >= rt
if (rs.code() == rt.rm_.reg_code) {
bits = OffsetSize::kOffset26;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bc(offset);
} else if (rs.is(zero_reg)) {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
blezc(scratch, offset);
} else if (IsZero(rt)) {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bgezc(rs, offset);
} else {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
DCHECK(!rs.is(scratch));
offset = GetOffset(offset, L, bits);
bgec(rs, scratch, offset);
}
break;
case less:
// rs < rt
if (rs.code() == rt.rm_.reg_code) {
break; // No code needs to be emitted.
} else if (rs.is(zero_reg)) {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
bgtzc(scratch, offset);
} else if (IsZero(rt)) {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bltzc(rs, offset);
} else {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
DCHECK(!rs.is(scratch));
offset = GetOffset(offset, L, bits);
bltc(rs, scratch, offset);
}
break;
case less_equal:
// rs <= rt
if (rs.code() == rt.rm_.reg_code) {
bits = OffsetSize::kOffset26;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bc(offset);
} else if (rs.is(zero_reg)) {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
bgezc(scratch, offset);
} else if (IsZero(rt)) {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
blezc(rs, offset);
} else {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
DCHECK(!rs.is(scratch));
offset = GetOffset(offset, L, bits);
bgec(scratch, rs, offset);
}
break;
// Unsigned comparison.
case Ugreater:
// rs > rt
if (rs.code() == rt.rm_.reg_code) {
break; // No code needs to be emitted.
} else if (rs.is(zero_reg)) {
bits = OffsetSize::kOffset21;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
bnezc(scratch, offset);
} else if (IsZero(rt)) {
bits = OffsetSize::kOffset21;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bnezc(rs, offset);
} else {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
DCHECK(!rs.is(scratch));
offset = GetOffset(offset, L, bits);
bltuc(scratch, rs, offset);
}
break;
case Ugreater_equal:
// rs >= rt
if (rs.code() == rt.rm_.reg_code) {
bits = OffsetSize::kOffset26;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bc(offset);
} else if (rs.is(zero_reg)) {
bits = OffsetSize::kOffset21;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
beqzc(scratch, offset);
} else if (IsZero(rt)) {
bits = OffsetSize::kOffset26;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bc(offset);
} else {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
DCHECK(!rs.is(scratch));
offset = GetOffset(offset, L, bits);
bgeuc(rs, scratch, offset);
}
break;
case Uless:
// rs < rt
if (rs.code() == rt.rm_.reg_code) {
break; // No code needs to be emitted.
} else if (rs.is(zero_reg)) {
bits = OffsetSize::kOffset21;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
bnezc(scratch, offset);
} else if (IsZero(rt)) {
break; // No code needs to be emitted.
} else {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
DCHECK(!rs.is(scratch));
offset = GetOffset(offset, L, bits);
bltuc(rs, scratch, offset);
}
break;
case Uless_equal:
// rs <= rt
if (rs.code() == rt.rm_.reg_code) {
bits = OffsetSize::kOffset26;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
bc(offset);
} else if (rs.is(zero_reg)) {
bits = OffsetSize::kOffset26;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
offset = GetOffset(offset, L, bits);
bc(offset);
} else if (IsZero(rt)) {
bits = OffsetSize::kOffset21;
if (!is_near(L, bits)) return false;
offset = GetOffset(offset, L, bits);
beqzc(rs, offset);
} else {
bits = OffsetSize::kOffset16;
if (!is_near(L, bits)) return false;
scratch = GetRtAsRegisterHelper(rt, scratch);
DCHECK(!rs.is(scratch));
offset = GetOffset(offset, L, bits);
bgeuc(scratch, rs, offset);
}
break;
default:
UNREACHABLE();
}
}
CheckTrampolinePoolQuick(1);
return true;
}
......
......@@ -1344,9 +1344,11 @@ void Assembler::bgezalc(Register rt, int16_t offset) {
void Assembler::bgezall(Register rs, int16_t offset) {
DCHECK(kArchVariant == kMips64r6);
DCHECK(kArchVariant != kMips64r6);
DCHECK(!(rs.is(zero_reg)));
BlockTrampolinePoolScope block_trampoline_pool(this);
GenInstrImmediate(REGIMM, rs, BGEZALL, offset);
BlockTrampolinePoolFor(1); // For associated delay slot.
}
......@@ -1409,15 +1411,19 @@ void Assembler::bnezc(Register rs, int32_t offset) {
void Assembler::j(int64_t target) {
BlockTrampolinePoolScope block_trampoline_pool(this);
GenInstrJump(J, static_cast<uint32_t>(target >> 2) & kImm26Mask);
BlockTrampolinePoolFor(1); // For associated delay slot.
}
void Assembler::j(Label* target) {
uint64_t imm = jump_offset(target);
if (target->is_bound()) {
BlockTrampolinePoolScope block_trampoline_pool(this);
GenInstrJump(static_cast<Opcode>(kJRawMark),
static_cast<uint32_t>(imm >> 2) & kImm26Mask);
BlockTrampolinePoolFor(1); // For associated delay slot.
} else {
j(imm);
}
......@@ -1427,8 +1433,11 @@ void Assembler::j(Label* target) {
void Assembler::jal(Label* target) {
uint64_t imm = jump_offset(target);
if (target->is_bound()) {
BlockTrampolinePoolScope block_trampoline_pool(this);
positions_recorder()->WriteRecordedPositions();
GenInstrJump(static_cast<Opcode>(kJalRawMark),
static_cast<uint32_t>(imm >> 2) & kImm26Mask);
BlockTrampolinePoolFor(1); // For associated delay slot.
} else {
jal(imm);
}
......@@ -1450,8 +1459,10 @@ void Assembler::jr(Register rs) {
void Assembler::jal(int64_t target) {
BlockTrampolinePoolScope block_trampoline_pool(this);
positions_recorder()->WriteRecordedPositions();
GenInstrJump(JAL, static_cast<uint32_t>(target >> 2) & kImm26Mask);
BlockTrampolinePoolFor(1); // For associated delay slot.
}
......
......@@ -5102,4 +5102,35 @@ TEST(bal) {
}
TEST(Trampoline) {
// Private member of Assembler class.
static const int kMaxBranchOffset = (1 << (18 - 1)) - 1;
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
MacroAssembler assm(isolate, nullptr, 0);
Label done;
size_t nr_calls = kMaxBranchOffset / (2 * Instruction::kInstrSize) + 2;
for (size_t i = 0; i < nr_calls; ++i) {
__ BranchShort(&done, eq, a0, Operand(a1));
}
__ bind(&done);
__ Ret(USE_DELAY_SLOT);
__ mov(v0, zero_reg);
CodeDesc desc;
assm.GetCode(&desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
F2 f = FUNCTION_CAST<F2>(code->entry());
int32_t res =
reinterpret_cast<int32_t>(CALL_GENERATED_CODE(f, 42, 42, 0, 0, 0));
CHECK_EQ(res, 0);
}
#undef __
......@@ -5492,4 +5492,35 @@ TEST(bal) {
}
TEST(Trampoline) {
// Private member of Assembler class.
static const int kMaxBranchOffset = (1 << (18 - 1)) - 1;
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
MacroAssembler assm(isolate, nullptr, 0);
Label done;
size_t nr_calls = kMaxBranchOffset / (2 * Instruction::kInstrSize) + 2;
for (size_t i = 0; i < nr_calls; ++i) {
__ BranchShort(&done, eq, a0, Operand(a1));
}
__ bind(&done);
__ Ret(USE_DELAY_SLOT);
__ mov(v0, zero_reg);
CodeDesc desc;
assm.GetCode(&desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
F2 f = FUNCTION_CAST<F2>(code->entry());
int64_t res =
reinterpret_cast<int64_t>(CALL_GENERATED_CODE(f, 42, 42, 0, 0, 0));
CHECK_EQ(res, 0);
}
#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