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 |