OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // | 2 // |
3 // Redistribution and use in source and binary forms, with or without | 3 // Redistribution and use in source and binary forms, with or without |
4 // modification, are permitted provided that the following conditions are | 4 // modification, are permitted provided that the following conditions are |
5 // met: | 5 // met: |
6 // | 6 // |
7 // * Redistributions of source code must retain the above copyright | 7 // * Redistributions of source code must retain the above copyright |
8 // notice, this list of conditions and the following disclaimer. | 8 // notice, this list of conditions and the following disclaimer. |
9 // * Redistributions in binary form must reproduce the above | 9 // * Redistributions in binary form must reproduce the above |
10 // copyright notice, this list of conditions and the following | 10 // copyright notice, this list of conditions and the following |
(...skipping 3070 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3081 } | 3081 } |
3082 | 3082 |
3083 | 3083 |
3084 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) { | 3084 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) { |
3085 // No out-of-line constant pool support. | 3085 // No out-of-line constant pool support. |
3086 ASSERT(!FLAG_enable_ool_constant_pool); | 3086 ASSERT(!FLAG_enable_ool_constant_pool); |
3087 return; | 3087 return; |
3088 } | 3088 } |
3089 | 3089 |
3090 | 3090 |
3091 void PatchingAssembler::MovInt64(const Register& rd, int64_t imm) { | 3091 void PatchingAssembler::PatchAdrFar(ptrdiff_t target_offset) { |
3092 Label start; | |
3093 bind(&start); | |
3094 | |
3095 ASSERT(rd.Is64Bits()); | |
3096 ASSERT(!rd.IsSP()); | |
3097 | |
3098 for (unsigned i = 0; i < (rd.SizeInBits() / 16); i++) { | |
3099 uint64_t imm16 = (imm >> (16 * i)) & 0xffffL; | |
3100 movk(rd, imm16, 16 * i); | |
3101 } | |
3102 | |
3103 ASSERT(SizeOfCodeGeneratedSince(&start) == | |
3104 kMovInt64NInstrs * kInstructionSize); | |
3105 } | |
3106 | |
3107 | |
3108 void PatchingAssembler::PatchAdrFar(Instruction* target) { | |
3109 // The code at the current instruction should be: | 3092 // The code at the current instruction should be: |
3110 // adr rd, 0 | 3093 // adr rd, 0 |
3111 // nop (adr_far) | 3094 // nop (adr_far) |
3112 // nop (adr_far) | 3095 // nop (adr_far) |
3113 // nop (adr_far) | |
3114 // movz scratch, 0 | 3096 // movz scratch, 0 |
3115 // add rd, rd, scratch | |
ulan
2014/07/03 10:36:20
Why not remove (nop, nop) instead of (nop, add)?
vincent.belliard
2014/07/03 10:46:06
The add has a cost (the processor doesn't know tha
ulan
2014/07/03 11:01:48
ok, thanks.
| |
3116 | 3097 |
3117 // Verify the expected code. | 3098 // Verify the expected code. |
3118 Instruction* expected_adr = InstructionAt(0); | 3099 Instruction* expected_adr = InstructionAt(0); |
3119 CHECK(expected_adr->IsAdr() && (expected_adr->ImmPCRel() == 0)); | 3100 CHECK(expected_adr->IsAdr() && (expected_adr->ImmPCRel() == 0)); |
3120 int rd_code = expected_adr->Rd(); | 3101 int rd_code = expected_adr->Rd(); |
3121 for (int i = 0; i < kAdrFarPatchableNNops; ++i) { | 3102 for (int i = 0; i < kAdrFarPatchableNNops; ++i) { |
3122 CHECK(InstructionAt((i + 1) * kInstructionSize)->IsNop(ADR_FAR_NOP)); | 3103 CHECK(InstructionAt((i + 1) * kInstructionSize)->IsNop(ADR_FAR_NOP)); |
3123 } | 3104 } |
3124 Instruction* expected_movz = | 3105 Instruction* expected_movz = |
3125 InstructionAt((kAdrFarPatchableNInstrs - 2) * kInstructionSize); | 3106 InstructionAt((kAdrFarPatchableNInstrs - 1) * kInstructionSize); |
3126 CHECK(expected_movz->IsMovz() && | 3107 CHECK(expected_movz->IsMovz() && |
3127 (expected_movz->ImmMoveWide() == 0) && | 3108 (expected_movz->ImmMoveWide() == 0) && |
3128 (expected_movz->ShiftMoveWide() == 0)); | 3109 (expected_movz->ShiftMoveWide() == 0)); |
3129 int scratch_code = expected_movz->Rd(); | 3110 int scratch_code = expected_movz->Rd(); |
3130 Instruction* expected_add = | |
3131 InstructionAt((kAdrFarPatchableNInstrs - 1) * kInstructionSize); | |
3132 CHECK(expected_add->IsAddSubShifted() && | |
3133 (expected_add->Mask(AddSubOpMask) == ADD) && | |
3134 expected_add->SixtyFourBits() && | |
3135 (expected_add->Rd() == rd_code) && (expected_add->Rn() == rd_code) && | |
3136 (expected_add->Rm() == scratch_code) && | |
3137 (static_cast<Shift>(expected_add->ShiftDP()) == LSL) && | |
3138 (expected_add->ImmDPShift() == 0)); | |
3139 | 3111 |
3140 // Patch to load the correct address. | 3112 // Patch to load the correct address. |
3141 Label start; | |
3142 bind(&start); | |
3143 Register rd = Register::XRegFromCode(rd_code); | 3113 Register rd = Register::XRegFromCode(rd_code); |
3144 // If the target is in range, we only patch the adr. Otherwise we patch the | 3114 Register scratch = Register::XRegFromCode(scratch_code); |
3145 // nops with fixup instructions. | 3115 // Addresses are only 48 bits. |
3146 int target_offset = expected_adr->DistanceTo(target); | 3116 adr(rd, target_offset & 0xFFFF); |
3147 if (Instruction::IsValidPCRelOffset(target_offset)) { | 3117 movz(scratch, (target_offset >> 16) & 0xFFFF, 16); |
3148 adr(rd, target_offset); | 3118 movk(scratch, (target_offset >> 32) & 0xFFFF, 32); |
3149 for (int i = 0; i < kAdrFarPatchableNInstrs - 2; ++i) { | 3119 ASSERT((target_offset >> 48) == 0); |
3150 nop(ADR_FAR_NOP); | 3120 add(rd, rd, scratch); |
3151 } | |
3152 } else { | |
3153 Register scratch = Register::XRegFromCode(scratch_code); | |
3154 adr(rd, 0); | |
3155 MovInt64(scratch, target_offset); | |
3156 add(rd, rd, scratch); | |
3157 } | |
3158 } | 3121 } |
3159 | 3122 |
3160 | 3123 |
3161 } } // namespace v8::internal | 3124 } } // namespace v8::internal |
3162 | 3125 |
3163 #endif // V8_TARGET_ARCH_ARM64 | 3126 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |