OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #define ARM64_DEFINE_FP_STATICS | 9 #define ARM64_DEFINE_FP_STATICS |
10 | 10 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 case STR_d: return true; | 60 case STR_d: return true; |
61 default: return false; | 61 default: return false; |
62 } | 62 } |
63 } | 63 } |
64 } | 64 } |
65 | 65 |
66 | 66 |
67 static uint64_t RotateRight(uint64_t value, | 67 static uint64_t RotateRight(uint64_t value, |
68 unsigned int rotate, | 68 unsigned int rotate, |
69 unsigned int width) { | 69 unsigned int width) { |
70 ASSERT(width <= 64); | 70 DCHECK(width <= 64); |
71 rotate &= 63; | 71 rotate &= 63; |
72 return ((value & ((1UL << rotate) - 1UL)) << (width - rotate)) | | 72 return ((value & ((1UL << rotate) - 1UL)) << (width - rotate)) | |
73 (value >> rotate); | 73 (value >> rotate); |
74 } | 74 } |
75 | 75 |
76 | 76 |
77 static uint64_t RepeatBitsAcrossReg(unsigned reg_size, | 77 static uint64_t RepeatBitsAcrossReg(unsigned reg_size, |
78 uint64_t value, | 78 uint64_t value, |
79 unsigned width) { | 79 unsigned width) { |
80 ASSERT((width == 2) || (width == 4) || (width == 8) || (width == 16) || | 80 DCHECK((width == 2) || (width == 4) || (width == 8) || (width == 16) || |
81 (width == 32)); | 81 (width == 32)); |
82 ASSERT((reg_size == kWRegSizeInBits) || (reg_size == kXRegSizeInBits)); | 82 DCHECK((reg_size == kWRegSizeInBits) || (reg_size == kXRegSizeInBits)); |
83 uint64_t result = value & ((1UL << width) - 1UL); | 83 uint64_t result = value & ((1UL << width) - 1UL); |
84 for (unsigned i = width; i < reg_size; i *= 2) { | 84 for (unsigned i = width; i < reg_size; i *= 2) { |
85 result |= (result << i); | 85 result |= (result << i); |
86 } | 86 } |
87 return result; | 87 return result; |
88 } | 88 } |
89 | 89 |
90 | 90 |
91 // Logical immediates can't encode zero, so a return value of zero is used to | 91 // Logical immediates can't encode zero, so a return value of zero is used to |
92 // indicate a failure case. Specifically, where the constraints on imm_s are not | 92 // indicate a failure case. Specifically, where the constraints on imm_s are not |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 ptrdiff_t offset; | 186 ptrdiff_t offset; |
187 if (IsPCRelAddressing()) { | 187 if (IsPCRelAddressing()) { |
188 // PC-relative addressing. Only ADR is supported. | 188 // PC-relative addressing. Only ADR is supported. |
189 offset = ImmPCRel(); | 189 offset = ImmPCRel(); |
190 } else if (BranchType() != UnknownBranchType) { | 190 } else if (BranchType() != UnknownBranchType) { |
191 // All PC-relative branches. | 191 // All PC-relative branches. |
192 // Relative branch offsets are instruction-size-aligned. | 192 // Relative branch offsets are instruction-size-aligned. |
193 offset = ImmBranch() << kInstructionSizeLog2; | 193 offset = ImmBranch() << kInstructionSizeLog2; |
194 } else { | 194 } else { |
195 // Load literal (offset from PC). | 195 // Load literal (offset from PC). |
196 ASSERT(IsLdrLiteral()); | 196 DCHECK(IsLdrLiteral()); |
197 // The offset is always shifted by 2 bits, even for loads to 64-bits | 197 // The offset is always shifted by 2 bits, even for loads to 64-bits |
198 // registers. | 198 // registers. |
199 offset = ImmLLiteral() << kInstructionSizeLog2; | 199 offset = ImmLLiteral() << kInstructionSizeLog2; |
200 } | 200 } |
201 return offset; | 201 return offset; |
202 } | 202 } |
203 | 203 |
204 | 204 |
205 Instruction* Instruction::ImmPCOffsetTarget() { | 205 Instruction* Instruction::ImmPCOffsetTarget() { |
206 return InstructionAtOffset(ImmPCOffset()); | 206 return InstructionAtOffset(ImmPCOffset()); |
(...skipping 17 matching lines...) Expand all Loading... |
224 } else if (BranchType() != UnknownBranchType) { | 224 } else if (BranchType() != UnknownBranchType) { |
225 SetBranchImmTarget(target); | 225 SetBranchImmTarget(target); |
226 } else { | 226 } else { |
227 SetImmLLiteral(target); | 227 SetImmLLiteral(target); |
228 } | 228 } |
229 } | 229 } |
230 | 230 |
231 | 231 |
232 void Instruction::SetPCRelImmTarget(Instruction* target) { | 232 void Instruction::SetPCRelImmTarget(Instruction* target) { |
233 // ADRP is not supported, so 'this' must point to an ADR instruction. | 233 // ADRP is not supported, so 'this' must point to an ADR instruction. |
234 ASSERT(IsAdr()); | 234 DCHECK(IsAdr()); |
235 | 235 |
236 ptrdiff_t target_offset = DistanceTo(target); | 236 ptrdiff_t target_offset = DistanceTo(target); |
237 Instr imm; | 237 Instr imm; |
238 if (Instruction::IsValidPCRelOffset(target_offset)) { | 238 if (Instruction::IsValidPCRelOffset(target_offset)) { |
239 imm = Assembler::ImmPCRelAddress(target_offset); | 239 imm = Assembler::ImmPCRelAddress(target_offset); |
240 SetInstructionBits(Mask(~ImmPCRel_mask) | imm); | 240 SetInstructionBits(Mask(~ImmPCRel_mask) | imm); |
241 } else { | 241 } else { |
242 PatchingAssembler patcher(this, | 242 PatchingAssembler patcher(this, |
243 PatchingAssembler::kAdrFarPatchableNInstrs); | 243 PatchingAssembler::kAdrFarPatchableNInstrs); |
244 patcher.PatchAdrFar(target_offset); | 244 patcher.PatchAdrFar(target_offset); |
245 } | 245 } |
246 } | 246 } |
247 | 247 |
248 | 248 |
249 void Instruction::SetBranchImmTarget(Instruction* target) { | 249 void Instruction::SetBranchImmTarget(Instruction* target) { |
250 ASSERT(IsAligned(DistanceTo(target), kInstructionSize)); | 250 DCHECK(IsAligned(DistanceTo(target), kInstructionSize)); |
251 Instr branch_imm = 0; | 251 Instr branch_imm = 0; |
252 uint32_t imm_mask = 0; | 252 uint32_t imm_mask = 0; |
253 ptrdiff_t offset = DistanceTo(target) >> kInstructionSizeLog2; | 253 ptrdiff_t offset = DistanceTo(target) >> kInstructionSizeLog2; |
254 switch (BranchType()) { | 254 switch (BranchType()) { |
255 case CondBranchType: { | 255 case CondBranchType: { |
256 branch_imm = Assembler::ImmCondBranch(offset); | 256 branch_imm = Assembler::ImmCondBranch(offset); |
257 imm_mask = ImmCondBranch_mask; | 257 imm_mask = ImmCondBranch_mask; |
258 break; | 258 break; |
259 } | 259 } |
260 case UncondBranchType: { | 260 case UncondBranchType: { |
(...skipping 11 matching lines...) Expand all Loading... |
272 imm_mask = ImmTestBranch_mask; | 272 imm_mask = ImmTestBranch_mask; |
273 break; | 273 break; |
274 } | 274 } |
275 default: UNREACHABLE(); | 275 default: UNREACHABLE(); |
276 } | 276 } |
277 SetInstructionBits(Mask(~imm_mask) | branch_imm); | 277 SetInstructionBits(Mask(~imm_mask) | branch_imm); |
278 } | 278 } |
279 | 279 |
280 | 280 |
281 void Instruction::SetImmLLiteral(Instruction* source) { | 281 void Instruction::SetImmLLiteral(Instruction* source) { |
282 ASSERT(IsAligned(DistanceTo(source), kInstructionSize)); | 282 DCHECK(IsAligned(DistanceTo(source), kInstructionSize)); |
283 ptrdiff_t offset = DistanceTo(source) >> kLoadLiteralScaleLog2; | 283 ptrdiff_t offset = DistanceTo(source) >> kLoadLiteralScaleLog2; |
284 Instr imm = Assembler::ImmLLiteral(offset); | 284 Instr imm = Assembler::ImmLLiteral(offset); |
285 Instr mask = ImmLLiteral_mask; | 285 Instr mask = ImmLLiteral_mask; |
286 | 286 |
287 SetInstructionBits(Mask(~mask) | imm); | 287 SetInstructionBits(Mask(~mask) | imm); |
288 } | 288 } |
289 | 289 |
290 | 290 |
291 // TODO(jbramley): We can't put this inline in the class because things like | 291 // TODO(jbramley): We can't put this inline in the class because things like |
292 // xzr and Register are not defined in that header. Consider adding | 292 // xzr and Register are not defined in that header. Consider adding |
293 // instructions-arm64-inl.h to work around this. | 293 // instructions-arm64-inl.h to work around this. |
294 bool InstructionSequence::IsInlineData() const { | 294 bool InstructionSequence::IsInlineData() const { |
295 // Inline data is encoded as a single movz instruction which writes to xzr | 295 // Inline data is encoded as a single movz instruction which writes to xzr |
296 // (x31). | 296 // (x31). |
297 return IsMovz() && SixtyFourBits() && (Rd() == xzr.code()); | 297 return IsMovz() && SixtyFourBits() && (Rd() == xzr.code()); |
298 // TODO(all): If we extend ::InlineData() to support bigger data, we need | 298 // TODO(all): If we extend ::InlineData() to support bigger data, we need |
299 // to update this method too. | 299 // to update this method too. |
300 } | 300 } |
301 | 301 |
302 | 302 |
303 // TODO(jbramley): We can't put this inline in the class because things like | 303 // TODO(jbramley): We can't put this inline in the class because things like |
304 // xzr and Register are not defined in that header. Consider adding | 304 // xzr and Register are not defined in that header. Consider adding |
305 // instructions-arm64-inl.h to work around this. | 305 // instructions-arm64-inl.h to work around this. |
306 uint64_t InstructionSequence::InlineData() const { | 306 uint64_t InstructionSequence::InlineData() const { |
307 ASSERT(IsInlineData()); | 307 DCHECK(IsInlineData()); |
308 uint64_t payload = ImmMoveWide(); | 308 uint64_t payload = ImmMoveWide(); |
309 // TODO(all): If we extend ::InlineData() to support bigger data, we need | 309 // TODO(all): If we extend ::InlineData() to support bigger data, we need |
310 // to update this method too. | 310 // to update this method too. |
311 return payload; | 311 return payload; |
312 } | 312 } |
313 | 313 |
314 | 314 |
315 } } // namespace v8::internal | 315 } } // namespace v8::internal |
316 | 316 |
317 #endif // V8_TARGET_ARCH_ARM64 | 317 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |