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 #ifndef V8_ARM64_INSTRUCTIONS_ARM64_H_ | 5 #ifndef V8_ARM64_INSTRUCTIONS_ARM64_H_ |
6 #define V8_ARM64_INSTRUCTIONS_ARM64_H_ | 6 #define V8_ARM64_INSTRUCTIONS_ARM64_H_ |
7 | 7 |
8 #include "src/arm64/constants-arm64.h" | 8 #include "src/arm64/constants-arm64.h" |
9 #include "src/arm64/utils-arm64.h" | 9 #include "src/arm64/utils-arm64.h" |
10 #include "src/globals.h" | 10 #include "src/globals.h" |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 | 114 |
115 int32_t SignedBits(int msb, int lsb) const { | 115 int32_t SignedBits(int msb, int lsb) const { |
116 int32_t bits = *(reinterpret_cast<const int32_t*>(this)); | 116 int32_t bits = *(reinterpret_cast<const int32_t*>(this)); |
117 return signed_bitextract_32(msb, lsb, bits); | 117 return signed_bitextract_32(msb, lsb, bits); |
118 } | 118 } |
119 | 119 |
120 Instr Mask(uint32_t mask) const { | 120 Instr Mask(uint32_t mask) const { |
121 return InstructionBits() & mask; | 121 return InstructionBits() & mask; |
122 } | 122 } |
123 | 123 |
| 124 V8_INLINE const Instruction* following(int count = 1) const { |
| 125 return InstructionAtOffset(count * static_cast<int>(kInstructionSize)); |
| 126 } |
| 127 |
124 V8_INLINE Instruction* following(int count = 1) { | 128 V8_INLINE Instruction* following(int count = 1) { |
125 return InstructionAtOffset(count * static_cast<int>(kInstructionSize)); | 129 return InstructionAtOffset(count * static_cast<int>(kInstructionSize)); |
126 } | 130 } |
127 | 131 |
| 132 V8_INLINE const Instruction* preceding(int count = 1) const { |
| 133 return following(-count); |
| 134 } |
| 135 |
128 V8_INLINE Instruction* preceding(int count = 1) { | 136 V8_INLINE Instruction* preceding(int count = 1) { |
129 return following(-count); | 137 return following(-count); |
130 } | 138 } |
131 | 139 |
132 #define DEFINE_GETTER(Name, HighBit, LowBit, Func) \ | 140 #define DEFINE_GETTER(Name, HighBit, LowBit, Func) \ |
133 int64_t Name() const { return Func(HighBit, LowBit); } | 141 int64_t Name() const { return Func(HighBit, LowBit); } |
134 INSTRUCTION_FIELDS_LIST(DEFINE_GETTER) | 142 INSTRUCTION_FIELDS_LIST(DEFINE_GETTER) |
135 #undef DEFINE_GETTER | 143 #undef DEFINE_GETTER |
136 | 144 |
137 // ImmPCRel is a compound field (not present in INSTRUCTION_FIELDS_LIST), | 145 // ImmPCRel is a compound field (not present in INSTRUCTION_FIELDS_LIST), |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 } | 190 } |
183 | 191 |
184 bool IsPCRelAddressing() const { | 192 bool IsPCRelAddressing() const { |
185 return Mask(PCRelAddressingFMask) == PCRelAddressingFixed; | 193 return Mask(PCRelAddressingFMask) == PCRelAddressingFixed; |
186 } | 194 } |
187 | 195 |
188 bool IsAdr() const { | 196 bool IsAdr() const { |
189 return Mask(PCRelAddressingMask) == ADR; | 197 return Mask(PCRelAddressingMask) == ADR; |
190 } | 198 } |
191 | 199 |
| 200 bool IsBrk() const { return Mask(ExceptionMask) == BRK; } |
| 201 |
| 202 bool IsUnresolvedInternalReference() const { |
| 203 // Unresolved internal references are encoded as two consecutive brk |
| 204 // instructions. |
| 205 return IsBrk() && following()->IsBrk(); |
| 206 } |
| 207 |
192 bool IsLogicalImmediate() const { | 208 bool IsLogicalImmediate() const { |
193 return Mask(LogicalImmediateFMask) == LogicalImmediateFixed; | 209 return Mask(LogicalImmediateFMask) == LogicalImmediateFixed; |
194 } | 210 } |
195 | 211 |
196 bool IsAddSubImmediate() const { | 212 bool IsAddSubImmediate() const { |
197 return Mask(AddSubImmediateFMask) == AddSubImmediateFixed; | 213 return Mask(AddSubImmediateFMask) == AddSubImmediateFixed; |
198 } | 214 } |
199 | 215 |
200 bool IsAddSubShifted() const { | 216 bool IsAddSubShifted() const { |
201 return Mask(AddSubShiftedFMask) == AddSubShiftedFixed; | 217 return Mask(AddSubShiftedFMask) == AddSubShiftedFixed; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 switch (BranchType()) { | 315 switch (BranchType()) { |
300 case CondBranchType: return ImmCondBranch(); | 316 case CondBranchType: return ImmCondBranch(); |
301 case UncondBranchType: return ImmUncondBranch(); | 317 case UncondBranchType: return ImmUncondBranch(); |
302 case CompareBranchType: return ImmCmpBranch(); | 318 case CompareBranchType: return ImmCmpBranch(); |
303 case TestBranchType: return ImmTestBranch(); | 319 case TestBranchType: return ImmTestBranch(); |
304 default: UNREACHABLE(); | 320 default: UNREACHABLE(); |
305 } | 321 } |
306 return 0; | 322 return 0; |
307 } | 323 } |
308 | 324 |
| 325 int ImmUnresolvedInternalReference() const { |
| 326 DCHECK(IsUnresolvedInternalReference()); |
| 327 // Unresolved references are encoded as two consecutive brk instructions. |
| 328 // The associated immediate is made of the two 16-bit payloads. |
| 329 int32_t high16 = ImmException(); |
| 330 int32_t low16 = following()->ImmException(); |
| 331 return (high16 << 16) | low16; |
| 332 } |
| 333 |
309 bool IsBranchAndLinkToRegister() const { | 334 bool IsBranchAndLinkToRegister() const { |
310 return Mask(UnconditionalBranchToRegisterMask) == BLR; | 335 return Mask(UnconditionalBranchToRegisterMask) == BLR; |
311 } | 336 } |
312 | 337 |
313 bool IsMovz() const { | 338 bool IsMovz() const { |
314 return (Mask(MoveWideImmediateMask) == MOVZ_x) || | 339 return (Mask(MoveWideImmediateMask) == MOVZ_x) || |
315 (Mask(MoveWideImmediateMask) == MOVZ_w); | 340 (Mask(MoveWideImmediateMask) == MOVZ_w); |
316 } | 341 } |
317 | 342 |
318 bool IsMovk() const { | 343 bool IsMovk() const { |
(...skipping 23 matching lines...) Expand all Loading... |
342 | 367 |
343 // Find the target of this instruction. 'this' may be a branch or a | 368 // Find the target of this instruction. 'this' may be a branch or a |
344 // PC-relative addressing instruction. | 369 // PC-relative addressing instruction. |
345 Instruction* ImmPCOffsetTarget(); | 370 Instruction* ImmPCOffsetTarget(); |
346 | 371 |
347 static bool IsValidImmPCOffset(ImmBranchType branch_type, int32_t offset); | 372 static bool IsValidImmPCOffset(ImmBranchType branch_type, int32_t offset); |
348 bool IsTargetInImmPCOffsetRange(Instruction* target); | 373 bool IsTargetInImmPCOffsetRange(Instruction* target); |
349 // Patch a PC-relative offset to refer to 'target'. 'this' may be a branch or | 374 // Patch a PC-relative offset to refer to 'target'. 'this' may be a branch or |
350 // a PC-relative addressing instruction. | 375 // a PC-relative addressing instruction. |
351 void SetImmPCOffsetTarget(Instruction* target); | 376 void SetImmPCOffsetTarget(Instruction* target); |
| 377 void SetUnresolvedInternalReferenceImmTarget(Instruction* target); |
352 // Patch a literal load instruction to load from 'source'. | 378 // Patch a literal load instruction to load from 'source'. |
353 void SetImmLLiteral(Instruction* source); | 379 void SetImmLLiteral(Instruction* source); |
354 | 380 |
355 uintptr_t LiteralAddress() { | 381 uintptr_t LiteralAddress() { |
356 int offset = ImmLLiteral() << kLoadLiteralScaleLog2; | 382 int offset = ImmLLiteral() << kLoadLiteralScaleLog2; |
357 return reinterpret_cast<uintptr_t>(this) + offset; | 383 return reinterpret_cast<uintptr_t>(this) + offset; |
358 } | 384 } |
359 | 385 |
360 enum CheckAlignment { NO_CHECK, CHECK_ALIGNMENT }; | 386 enum CheckAlignment { NO_CHECK, CHECK_ALIGNMENT }; |
361 | 387 |
| 388 V8_INLINE const Instruction* InstructionAtOffset( |
| 389 int64_t offset, CheckAlignment check = CHECK_ALIGNMENT) const { |
| 390 // The FUZZ_disasm test relies on no check being done. |
| 391 DCHECK(check == NO_CHECK || IsAligned(offset, kInstructionSize)); |
| 392 return this + offset; |
| 393 } |
| 394 |
362 V8_INLINE Instruction* InstructionAtOffset( | 395 V8_INLINE Instruction* InstructionAtOffset( |
363 int64_t offset, | 396 int64_t offset, CheckAlignment check = CHECK_ALIGNMENT) { |
364 CheckAlignment check = CHECK_ALIGNMENT) { | |
365 Address addr = reinterpret_cast<Address>(this) + offset; | |
366 // The FUZZ_disasm test relies on no check being done. | 397 // The FUZZ_disasm test relies on no check being done. |
367 DCHECK(check == NO_CHECK || IsAddressAligned(addr, kInstructionSize)); | 398 DCHECK(check == NO_CHECK || IsAligned(offset, kInstructionSize)); |
368 return Cast(addr); | 399 return this + offset; |
369 } | 400 } |
370 | 401 |
371 template<typename T> V8_INLINE static Instruction* Cast(T src) { | 402 template<typename T> V8_INLINE static Instruction* Cast(T src) { |
372 return reinterpret_cast<Instruction*>(src); | 403 return reinterpret_cast<Instruction*>(src); |
373 } | 404 } |
374 | 405 |
375 V8_INLINE ptrdiff_t DistanceTo(Instruction* target) { | 406 V8_INLINE ptrdiff_t DistanceTo(Instruction* target) { |
376 return reinterpret_cast<Address>(target) - reinterpret_cast<Address>(this); | 407 return reinterpret_cast<Address>(target) - reinterpret_cast<Address>(this); |
377 } | 408 } |
378 | 409 |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
500 TRACE_ENABLE = 1 << 6, | 531 TRACE_ENABLE = 1 << 6, |
501 TRACE_DISABLE = 2 << 6, | 532 TRACE_DISABLE = 2 << 6, |
502 TRACE_OVERRIDE = 3 << 6 | 533 TRACE_OVERRIDE = 3 << 6 |
503 }; | 534 }; |
504 | 535 |
505 | 536 |
506 } } // namespace v8::internal | 537 } } // namespace v8::internal |
507 | 538 |
508 | 539 |
509 #endif // V8_ARM64_INSTRUCTIONS_ARM64_H_ | 540 #endif // V8_ARM64_INSTRUCTIONS_ARM64_H_ |
OLD | NEW |