Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Unified Diff: src/arm64/assembler-arm64.cc

Issue 222433002: ARM64: Introduce a version of ADR handling distant targets. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix loop offset Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/arm64/assembler-arm64.cc
diff --git a/src/arm64/assembler-arm64.cc b/src/arm64/assembler-arm64.cc
index 8bee92ccc273a87b1e319481ef0697063c7f4075..2e3c5492164a40663ee55c85862316cbb4e333c5 100644
--- a/src/arm64/assembler-arm64.cc
+++ b/src/arm64/assembler-arm64.cc
@@ -2808,6 +2808,76 @@ void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) {
}
+void PatchingAssembler::MovInt64(const Register& rd, int64_t imm) {
+ 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:
+ // adr rd, 0
+ // nop (adr_far)
+ // nop (adr_far)
+ // nop (adr_far)
+ // movz scratch, 0
+ // add rd, rd, scratch
+
+ // Verify the expected code.
+ Instruction* expected_adr = InstructionAt(0);
+ CHECK(expected_adr->IsAdr() && (expected_adr->ImmPCRel() == 0));
+ int rd_code = expected_adr->Rd();
+ for (int i = 0; i < kAdrFarPatchableNNops; ++i) {
+ CHECK(InstructionAt((i + 1) * kInstructionSize)->IsNop(ADR_FAR_NOP));
+ }
+ Instruction* expected_movz =
+ InstructionAt((kAdrFarPatchableNInstrs - 2) * kInstructionSize);
+ CHECK(expected_movz->IsMovz() &&
+ (expected_movz->ImmMoveWide() == 0) &&
+ (expected_movz->ShiftMoveWide() == 0));
+ 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.
+ Label start;
+ bind(&start);
+ Register rd = Register::XRegFromCode(rd_code);
+ // If the target is in range, we only patch the adr. Otherwise we patch the
+ // nops with fixup instructions.
+ int target_offset = expected_adr->DistanceTo(target);
+ if (Instruction::IsValidPCRelOffset(target_offset)) {
+ adr(rd, target_offset);
+ for (int i = 0; i < kAdrFarPatchableNInstrs - 2; ++i) {
+ nop(ADR_FAR_NOP);
+ }
+ } else {
+ Register scratch = Register::XRegFromCode(scratch_code);
+ adr(rd, 0);
+ MovInt64(scratch, target_offset);
+ add(rd, rd, scratch);
+ }
+}
+
+
} } // namespace v8::internal
#endif // V8_TARGET_ARCH_ARM64

Powered by Google App Engine
This is Rietveld 408576698