| 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 |