| 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
|
|
|