ARM64: improve Adr patching

R=ulan@chromium.org, bmeurer@chromium.org

BUG=

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22198 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f3b9ece6
...@@ -3088,31 +3088,12 @@ void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) { ...@@ -3088,31 +3088,12 @@ void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) {
} }
void PatchingAssembler::MovInt64(const Register& rd, int64_t imm) { void PatchingAssembler::PatchAdrFar(ptrdiff_t target_offset) {
Label start;
bind(&start);
ASSERT(rd.Is64Bits());
ASSERT(!rd.IsSP());
for (unsigned i = 0; i < (rd.SizeInBits() / 16); i++) {
uint64_t imm16 = (imm >> (16 * i)) & 0xffffL;
movk(rd, imm16, 16 * i);
}
ASSERT(SizeOfCodeGeneratedSince(&start) ==
kMovInt64NInstrs * kInstructionSize);
}
void PatchingAssembler::PatchAdrFar(Instruction* target) {
// The code at the current instruction should be: // The code at the current instruction should be:
// adr rd, 0 // adr rd, 0
// nop (adr_far) // nop (adr_far)
// nop (adr_far) // nop (adr_far)
// nop (adr_far)
// movz scratch, 0 // movz scratch, 0
// add rd, rd, scratch
// Verify the expected code. // Verify the expected code.
Instruction* expected_adr = InstructionAt(0); Instruction* expected_adr = InstructionAt(0);
...@@ -3122,39 +3103,21 @@ void PatchingAssembler::PatchAdrFar(Instruction* target) { ...@@ -3122,39 +3103,21 @@ void PatchingAssembler::PatchAdrFar(Instruction* target) {
CHECK(InstructionAt((i + 1) * kInstructionSize)->IsNop(ADR_FAR_NOP)); CHECK(InstructionAt((i + 1) * kInstructionSize)->IsNop(ADR_FAR_NOP));
} }
Instruction* expected_movz = Instruction* expected_movz =
InstructionAt((kAdrFarPatchableNInstrs - 2) * kInstructionSize); InstructionAt((kAdrFarPatchableNInstrs - 1) * kInstructionSize);
CHECK(expected_movz->IsMovz() && CHECK(expected_movz->IsMovz() &&
(expected_movz->ImmMoveWide() == 0) && (expected_movz->ImmMoveWide() == 0) &&
(expected_movz->ShiftMoveWide() == 0)); (expected_movz->ShiftMoveWide() == 0));
int scratch_code = expected_movz->Rd(); int scratch_code = expected_movz->Rd();
Instruction* expected_add =
InstructionAt((kAdrFarPatchableNInstrs - 1) * kInstructionSize);
CHECK(expected_add->IsAddSubShifted() &&
(expected_add->Mask(AddSubOpMask) == ADD) &&
expected_add->SixtyFourBits() &&
(expected_add->Rd() == rd_code) && (expected_add->Rn() == rd_code) &&
(expected_add->Rm() == scratch_code) &&
(static_cast<Shift>(expected_add->ShiftDP()) == LSL) &&
(expected_add->ImmDPShift() == 0));
// Patch to load the correct address. // Patch to load the correct address.
Label start;
bind(&start);
Register rd = Register::XRegFromCode(rd_code); Register rd = Register::XRegFromCode(rd_code);
// If the target is in range, we only patch the adr. Otherwise we patch the Register scratch = Register::XRegFromCode(scratch_code);
// nops with fixup instructions. // Addresses are only 48 bits.
int target_offset = expected_adr->DistanceTo(target); adr(rd, target_offset & 0xFFFF);
if (Instruction::IsValidPCRelOffset(target_offset)) { movz(scratch, (target_offset >> 16) & 0xFFFF, 16);
adr(rd, target_offset); movk(scratch, (target_offset >> 32) & 0xFFFF, 32);
for (int i = 0; i < kAdrFarPatchableNInstrs - 2; ++i) { ASSERT((target_offset >> 48) == 0);
nop(ADR_FAR_NOP); add(rd, rd, scratch);
}
} else {
Register scratch = Register::XRegFromCode(scratch_code);
adr(rd, 0);
MovInt64(scratch, target_offset);
add(rd, rd, scratch);
}
} }
......
...@@ -2286,13 +2286,10 @@ class PatchingAssembler : public Assembler { ...@@ -2286,13 +2286,10 @@ class PatchingAssembler : public Assembler {
CpuFeatures::FlushICache(buffer_, length); CpuFeatures::FlushICache(buffer_, length);
} }
static const int kMovInt64NInstrs = 4;
void MovInt64(const Register& rd, int64_t imm);
// See definition of PatchAdrFar() for details. // See definition of PatchAdrFar() for details.
static const int kAdrFarPatchableNNops = kMovInt64NInstrs - 1; static const int kAdrFarPatchableNNops = 2;
static const int kAdrFarPatchableNInstrs = kAdrFarPatchableNNops + 3; static const int kAdrFarPatchableNInstrs = kAdrFarPatchableNNops + 2;
void PatchAdrFar(Instruction* target); void PatchAdrFar(ptrdiff_t target_offset);
}; };
......
...@@ -233,7 +233,7 @@ void Instruction::SetPCRelImmTarget(Instruction* target) { ...@@ -233,7 +233,7 @@ void Instruction::SetPCRelImmTarget(Instruction* target) {
// ADRP is not supported, so 'this' must point to an ADR instruction. // ADRP is not supported, so 'this' must point to an ADR instruction.
ASSERT(IsAdr()); ASSERT(IsAdr());
int target_offset = DistanceTo(target); ptrdiff_t target_offset = DistanceTo(target);
Instr imm; Instr imm;
if (Instruction::IsValidPCRelOffset(target_offset)) { if (Instruction::IsValidPCRelOffset(target_offset)) {
imm = Assembler::ImmPCRelAddress(target_offset); imm = Assembler::ImmPCRelAddress(target_offset);
...@@ -241,7 +241,7 @@ void Instruction::SetPCRelImmTarget(Instruction* target) { ...@@ -241,7 +241,7 @@ void Instruction::SetPCRelImmTarget(Instruction* target) {
} else { } else {
PatchingAssembler patcher(this, PatchingAssembler patcher(this,
PatchingAssembler::kAdrFarPatchableNInstrs); PatchingAssembler::kAdrFarPatchableNInstrs);
patcher.PatchAdrFar(target); patcher.PatchAdrFar(target_offset);
} }
} }
......
...@@ -613,10 +613,6 @@ void MacroAssembler::Adr(const Register& rd, Label* label, AdrHint hint) { ...@@ -613,10 +613,6 @@ void MacroAssembler::Adr(const Register& rd, Label* label, AdrHint hint) {
} }
ASSERT(hint == kAdrFar); ASSERT(hint == kAdrFar);
UseScratchRegisterScope temps(this);
Register scratch = temps.AcquireX();
ASSERT(!AreAliased(rd, scratch));
if (label->is_bound()) { if (label->is_bound()) {
int label_offset = label->pos() - pc_offset(); int label_offset = label->pos() - pc_offset();
if (Instruction::IsValidPCRelOffset(label_offset)) { if (Instruction::IsValidPCRelOffset(label_offset)) {
...@@ -628,6 +624,9 @@ void MacroAssembler::Adr(const Register& rd, Label* label, AdrHint hint) { ...@@ -628,6 +624,9 @@ void MacroAssembler::Adr(const Register& rd, Label* label, AdrHint hint) {
Add(rd, rd, label_offset - min_adr_offset); Add(rd, rd, label_offset - min_adr_offset);
} }
} else { } else {
UseScratchRegisterScope temps(this);
Register scratch = temps.AcquireX();
InstructionAccurateScope scope( InstructionAccurateScope scope(
this, PatchingAssembler::kAdrFarPatchableNInstrs); this, PatchingAssembler::kAdrFarPatchableNInstrs);
adr(rd, label); adr(rd, label);
...@@ -635,7 +634,6 @@ void MacroAssembler::Adr(const Register& rd, Label* label, AdrHint hint) { ...@@ -635,7 +634,6 @@ void MacroAssembler::Adr(const Register& rd, Label* label, AdrHint hint) {
nop(ADR_FAR_NOP); nop(ADR_FAR_NOP);
} }
movz(scratch, 0); movz(scratch, 0);
add(rd, rd, scratch);
} }
} }
......
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