| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
| 6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/constants_arm64.h" | 9 #include "vm/constants_arm64.h" |
| 10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 | 27 |
| 28 Register reg; | 28 Register reg; |
| 29 ic_data_load_end_ = | 29 ic_data_load_end_ = |
| 30 InstructionPattern::DecodeLoadWordFromPool(end_ - Instr::kInstrSize, | 30 InstructionPattern::DecodeLoadWordFromPool(end_ - Instr::kInstrSize, |
| 31 ®, | 31 ®, |
| 32 &target_address_pool_index_); | 32 &target_address_pool_index_); |
| 33 ASSERT(reg == IP0); | 33 ASSERT(reg == IP0); |
| 34 } | 34 } |
| 35 | 35 |
| 36 | 36 |
| 37 intptr_t InstructionPattern::OffsetFromPPIndex(intptr_t index) { |
| 38 return Array::element_offset(index); |
| 39 } |
| 40 |
| 41 |
| 37 // Decodes a load sequence ending at 'end' (the last instruction of the load | 42 // Decodes a load sequence ending at 'end' (the last instruction of the load |
| 38 // sequence is the instruction before the one at end). Returns a pointer to | 43 // sequence is the instruction before the one at end). Returns a pointer to |
| 39 // the first instruction in the sequence. Returns the register being loaded | 44 // the first instruction in the sequence. Returns the register being loaded |
| 40 // and the loaded object in the output parameters 'reg' and 'obj' | 45 // and the loaded object in the output parameters 'reg' and 'obj' |
| 41 // respectively. | 46 // respectively. |
| 42 uword InstructionPattern::DecodeLoadObject(uword end, | 47 uword InstructionPattern::DecodeLoadObject(uword end, |
| 43 const Array& object_pool, | 48 const Array& object_pool, |
| 44 Register* reg, | 49 Register* reg, |
| 45 Object* obj) { | 50 Object* obj) { |
| 46 // 1. LoadWordFromPool | 51 // 1. LoadWordFromPool |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 // Decodes a load sequence ending at 'end' (the last instruction of the load | 145 // Decodes a load sequence ending at 'end' (the last instruction of the load |
| 141 // sequence is the instruction before the one at end). Returns a pointer to | 146 // sequence is the instruction before the one at end). Returns a pointer to |
| 142 // the first instruction in the sequence. Returns the register being loaded | 147 // the first instruction in the sequence. Returns the register being loaded |
| 143 // and the index in the pool being read from in the output parameters 'reg' | 148 // and the index in the pool being read from in the output parameters 'reg' |
| 144 // and 'index' respectively. | 149 // and 'index' respectively. |
| 145 uword InstructionPattern::DecodeLoadWordFromPool(uword end, | 150 uword InstructionPattern::DecodeLoadWordFromPool(uword end, |
| 146 Register* reg, | 151 Register* reg, |
| 147 intptr_t* index) { | 152 intptr_t* index) { |
| 148 // 1. ldr dst, [pp, offset] | 153 // 1. ldr dst, [pp, offset] |
| 149 // or | 154 // or |
| 150 // 2. movz dst, low_offset, 0 | 155 // 2. add dst, pp, #offset_hi12 |
| 156 // ldr dst [dst, #offset_lo12] |
| 157 // or |
| 158 // 3. movz dst, low_offset, 0 |
| 151 // movk dst, hi_offset, 1 (optional) | 159 // movk dst, hi_offset, 1 (optional) |
| 152 // ldr dst, [pp, dst] | 160 // ldr dst, [pp, dst] |
| 153 uword start = end - Instr::kInstrSize; | 161 uword start = end - Instr::kInstrSize; |
| 154 Instr* instr = Instr::At(start); | 162 Instr* instr = Instr::At(start); |
| 155 intptr_t offset = 0; | 163 intptr_t offset = 0; |
| 156 | 164 |
| 157 // Last instruction is always an ldr into a 64-bit X register. | 165 // Last instruction is always an ldr into a 64-bit X register. |
| 158 ASSERT(instr->IsLoadStoreRegOp() && (instr->Bit(22) == 1) && | 166 ASSERT(instr->IsLoadStoreRegOp() && (instr->Bit(22) == 1) && |
| 159 (instr->Bits(30, 2) == 3)); | 167 (instr->Bits(30, 2) == 3)); |
| 160 | 168 |
| 161 // Grab the destination register from the ldr instruction. | 169 // Grab the destination register from the ldr instruction. |
| 162 *reg = instr->RtField(); | 170 *reg = instr->RtField(); |
| 163 | 171 |
| 164 if (instr->Bit(24) == 1) { | 172 if (instr->Bit(24) == 1) { |
| 165 // pp + scaled unsigned 12-bit immediate offset. | 173 // base + scaled unsigned 12-bit immediate offset. |
| 166 // Case 1. | 174 // Case 1. |
| 167 offset = instr->Imm12Field() << 3; | 175 offset |= (instr->Imm12Field() << 3); |
| 176 if (instr->RnField() == *reg) { |
| 177 start -= Instr::kInstrSize; |
| 178 instr = Instr::At(start); |
| 179 ASSERT(instr->IsAddSubImmOp()); |
| 180 ASSERT(instr->RnField() == PP); |
| 181 ASSERT(instr->RdField() == *reg); |
| 182 offset |= (instr->Imm12Field() << 12); |
| 183 } |
| 168 } else { | 184 } else { |
| 169 ASSERT(instr->Bits(10, 2) == 2); | 185 ASSERT(instr->Bits(10, 2) == 2); |
| 170 // We have to look at the preceding one or two instructions to find the | 186 // We have to look at the preceding one or two instructions to find the |
| 171 // offset. | 187 // offset. |
| 172 | 188 |
| 173 start -= Instr::kInstrSize; | 189 start -= Instr::kInstrSize; |
| 174 instr = Instr::At(start); | 190 instr = Instr::At(start); |
| 175 ASSERT(instr->IsMoveWideOp()); | 191 ASSERT(instr->IsMoveWideOp()); |
| 176 ASSERT(instr->RdField() == *reg); | 192 ASSERT(instr->RdField() == *reg); |
| 177 if (instr->Bits(29, 2) == 2) { // movz dst, low_offset, 0 | 193 if (instr->Bits(29, 2) == 2) { // movz dst, low_offset, 0 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 191 ASSERT(instr->HWField() == 0); | 207 ASSERT(instr->HWField() == 0); |
| 192 offset |= instr->Imm16Field(); | 208 offset |= instr->Imm16Field(); |
| 193 } | 209 } |
| 194 } | 210 } |
| 195 ASSERT(Utils::IsAligned(offset, 8)); | 211 ASSERT(Utils::IsAligned(offset, 8)); |
| 196 *index = (offset - Array::data_offset()) / 8; | 212 *index = (offset - Array::data_offset()) / 8; |
| 197 return start; | 213 return start; |
| 198 } | 214 } |
| 199 | 215 |
| 200 | 216 |
| 217 // Encodes a load sequence ending at 'end'. Encodes a fixed length two |
| 218 // instruction load from the pool pointer in PP using the destination |
| 219 // register reg as a temporary for the base address. |
| 220 // Assumes that the location has already been validated for patching. |
| 221 void InstructionPattern::EncodeLoadWordFromPoolFixed(uword end, |
| 222 int32_t offset) { |
| 223 uword start = end - Instr::kInstrSize; |
| 224 Instr* instr = Instr::At(start); |
| 225 const int32_t upper12 = offset & 0x00fff000; |
| 226 const int32_t lower12 = offset & 0x00000fff; |
| 227 ASSERT((offset & 0xff000000) == 0); // Can't encode > 24 bits. |
| 228 ASSERT(((lower12 >> 3) << 3) == lower12); // 8-byte aligned. |
| 229 instr->SetImm12Bits(instr->InstructionBits(), lower12 >> 3); |
| 230 |
| 231 start -= Instr::kInstrSize; |
| 232 instr = Instr::At(start); |
| 233 instr->SetImm12Bits(instr->InstructionBits(), upper12 >> 12); |
| 234 instr->SetInstructionBits(instr->InstructionBits() | B22); |
| 235 } |
| 236 |
| 237 |
| 201 RawICData* CallPattern::IcData() { | 238 RawICData* CallPattern::IcData() { |
| 202 if (ic_data_.IsNull()) { | 239 if (ic_data_.IsNull()) { |
| 203 Register reg; | 240 Register reg; |
| 204 args_desc_load_end_ = | 241 args_desc_load_end_ = |
| 205 InstructionPattern::DecodeLoadObject(ic_data_load_end_, | 242 InstructionPattern::DecodeLoadObject(ic_data_load_end_, |
| 206 object_pool_, | 243 object_pool_, |
| 207 ®, | 244 ®, |
| 208 &ic_data_); | 245 &ic_data_); |
| 209 ASSERT(reg == R5); | 246 ASSERT(reg == R5); |
| 210 } | 247 } |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 movz0->SetInstructionBits((movz0_bits & ~kImm16Mask) | (h0 << kImm16Shift)); | 361 movz0->SetInstructionBits((movz0_bits & ~kImm16Mask) | (h0 << kImm16Shift)); |
| 325 movk1->SetInstructionBits((movk1_bits & ~kImm16Mask) | (h1 << kImm16Shift)); | 362 movk1->SetInstructionBits((movk1_bits & ~kImm16Mask) | (h1 << kImm16Shift)); |
| 326 movk2->SetInstructionBits((movk2_bits & ~kImm16Mask) | (h2 << kImm16Shift)); | 363 movk2->SetInstructionBits((movk2_bits & ~kImm16Mask) | (h2 << kImm16Shift)); |
| 327 movk3->SetInstructionBits((movk3_bits & ~kImm16Mask) | (h3 << kImm16Shift)); | 364 movk3->SetInstructionBits((movk3_bits & ~kImm16Mask) | (h3 << kImm16Shift)); |
| 328 CPU::FlushICache(pc_, 4 * Instr::kInstrSize); | 365 CPU::FlushICache(pc_, 4 * Instr::kInstrSize); |
| 329 } | 366 } |
| 330 | 367 |
| 331 } // namespace dart | 368 } // namespace dart |
| 332 | 369 |
| 333 #endif // defined TARGET_ARCH_ARM64 | 370 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |