| 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 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 |
| 93 // met. | 93 // met. |
| 94 uint64_t Instruction::ImmLogical() { | 94 uint64_t Instruction::ImmLogical() { |
| 95 unsigned reg_size = SixtyFourBits() ? kXRegSizeInBits : kWRegSizeInBits; | 95 unsigned reg_size = SixtyFourBits() ? kXRegSizeInBits : kWRegSizeInBits; |
| 96 int64_t n = BitN(); | 96 int32_t n = BitN(); |
| 97 int64_t imm_s = ImmSetBits(); | 97 int32_t imm_s = ImmSetBits(); |
| 98 int64_t imm_r = ImmRotate(); | 98 int32_t imm_r = ImmRotate(); |
| 99 | 99 |
| 100 // An integer is constructed from the n, imm_s and imm_r bits according to | 100 // An integer is constructed from the n, imm_s and imm_r bits according to |
| 101 // the following table: | 101 // the following table: |
| 102 // | 102 // |
| 103 // N imms immr size S R | 103 // N imms immr size S R |
| 104 // 1 ssssss rrrrrr 64 UInt(ssssss) UInt(rrrrrr) | 104 // 1 ssssss rrrrrr 64 UInt(ssssss) UInt(rrrrrr) |
| 105 // 0 0sssss xrrrrr 32 UInt(sssss) UInt(rrrrr) | 105 // 0 0sssss xrrrrr 32 UInt(sssss) UInt(rrrrr) |
| 106 // 0 10ssss xxrrrr 16 UInt(ssss) UInt(rrrr) | 106 // 0 10ssss xxrrrr 16 UInt(ssss) UInt(rrrr) |
| 107 // 0 110sss xxxrrr 8 UInt(sss) UInt(rrr) | 107 // 0 110sss xxxrrr 8 UInt(sss) UInt(rrr) |
| 108 // 0 1110ss xxxxrr 4 UInt(ss) UInt(rr) | 108 // 0 1110ss xxxxrr 4 UInt(ss) UInt(rr) |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 return offset; | 204 return offset; |
| 205 } | 205 } |
| 206 | 206 |
| 207 | 207 |
| 208 Instruction* Instruction::ImmPCOffsetTarget() { | 208 Instruction* Instruction::ImmPCOffsetTarget() { |
| 209 return InstructionAtOffset(ImmPCOffset()); | 209 return InstructionAtOffset(ImmPCOffset()); |
| 210 } | 210 } |
| 211 | 211 |
| 212 | 212 |
| 213 bool Instruction::IsValidImmPCOffset(ImmBranchType branch_type, | 213 bool Instruction::IsValidImmPCOffset(ImmBranchType branch_type, |
| 214 int32_t offset) { | 214 ptrdiff_t offset) { |
| 215 return is_intn(offset, ImmBranchRangeBitwidth(branch_type)); | 215 return is_intn(offset, ImmBranchRangeBitwidth(branch_type)); |
| 216 } | 216 } |
| 217 | 217 |
| 218 | 218 |
| 219 bool Instruction::IsTargetInImmPCOffsetRange(Instruction* target) { | 219 bool Instruction::IsTargetInImmPCOffsetRange(Instruction* target) { |
| 220 return IsValidImmPCOffset(BranchType(), DistanceTo(target)); | 220 return IsValidImmPCOffset(BranchType(), DistanceTo(target)); |
| 221 } | 221 } |
| 222 | 222 |
| 223 | 223 |
| 224 void Instruction::SetImmPCOffsetTarget(Instruction* target) { | 224 void Instruction::SetImmPCOffsetTarget(Instruction* target) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 235 } | 235 } |
| 236 | 236 |
| 237 | 237 |
| 238 void Instruction::SetPCRelImmTarget(Instruction* target) { | 238 void Instruction::SetPCRelImmTarget(Instruction* target) { |
| 239 // ADRP is not supported, so 'this' must point to an ADR instruction. | 239 // ADRP is not supported, so 'this' must point to an ADR instruction. |
| 240 DCHECK(IsAdr()); | 240 DCHECK(IsAdr()); |
| 241 | 241 |
| 242 ptrdiff_t target_offset = DistanceTo(target); | 242 ptrdiff_t target_offset = DistanceTo(target); |
| 243 Instr imm; | 243 Instr imm; |
| 244 if (Instruction::IsValidPCRelOffset(target_offset)) { | 244 if (Instruction::IsValidPCRelOffset(target_offset)) { |
| 245 imm = Assembler::ImmPCRelAddress(target_offset); | 245 imm = Assembler::ImmPCRelAddress(static_cast<int>(target_offset)); |
| 246 SetInstructionBits(Mask(~ImmPCRel_mask) | imm); | 246 SetInstructionBits(Mask(~ImmPCRel_mask) | imm); |
| 247 } else { | 247 } else { |
| 248 PatchingAssembler patcher(this, | 248 PatchingAssembler patcher(this, |
| 249 PatchingAssembler::kAdrFarPatchableNInstrs); | 249 PatchingAssembler::kAdrFarPatchableNInstrs); |
| 250 patcher.PatchAdrFar(target_offset); | 250 patcher.PatchAdrFar(target_offset); |
| 251 } | 251 } |
| 252 } | 252 } |
| 253 | 253 |
| 254 | 254 |
| 255 void Instruction::SetBranchImmTarget(Instruction* target) { | 255 void Instruction::SetBranchImmTarget(Instruction* target) { |
| 256 DCHECK(IsAligned(DistanceTo(target), kInstructionSize)); | 256 DCHECK(IsAligned(DistanceTo(target), kInstructionSize)); |
| 257 DCHECK(IsValidImmPCOffset(BranchType(), |
| 258 DistanceTo(target) >> kInstructionSizeLog2)); |
| 259 int offset = static_cast<int>(DistanceTo(target) >> kInstructionSizeLog2); |
| 257 Instr branch_imm = 0; | 260 Instr branch_imm = 0; |
| 258 uint32_t imm_mask = 0; | 261 uint32_t imm_mask = 0; |
| 259 ptrdiff_t offset = DistanceTo(target) >> kInstructionSizeLog2; | |
| 260 switch (BranchType()) { | 262 switch (BranchType()) { |
| 261 case CondBranchType: { | 263 case CondBranchType: { |
| 262 branch_imm = Assembler::ImmCondBranch(offset); | 264 branch_imm = Assembler::ImmCondBranch(offset); |
| 263 imm_mask = ImmCondBranch_mask; | 265 imm_mask = ImmCondBranch_mask; |
| 264 break; | 266 break; |
| 265 } | 267 } |
| 266 case UncondBranchType: { | 268 case UncondBranchType: { |
| 267 branch_imm = Assembler::ImmUncondBranch(offset); | 269 branch_imm = Assembler::ImmUncondBranch(offset); |
| 268 imm_mask = ImmUncondBranch_mask; | 270 imm_mask = ImmUncondBranch_mask; |
| 269 break; | 271 break; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 280 } | 282 } |
| 281 default: UNREACHABLE(); | 283 default: UNREACHABLE(); |
| 282 } | 284 } |
| 283 SetInstructionBits(Mask(~imm_mask) | branch_imm); | 285 SetInstructionBits(Mask(~imm_mask) | branch_imm); |
| 284 } | 286 } |
| 285 | 287 |
| 286 | 288 |
| 287 void Instruction::SetUnresolvedInternalReferenceImmTarget(Instruction* target) { | 289 void Instruction::SetUnresolvedInternalReferenceImmTarget(Instruction* target) { |
| 288 DCHECK(IsUnresolvedInternalReference()); | 290 DCHECK(IsUnresolvedInternalReference()); |
| 289 DCHECK(IsAligned(DistanceTo(target), kInstructionSize)); | 291 DCHECK(IsAligned(DistanceTo(target), kInstructionSize)); |
| 290 | 292 DCHECK(is_int32(DistanceTo(target) >> kInstructionSizeLog2)); |
| 291 ptrdiff_t target_offset = DistanceTo(target) >> kInstructionSizeLog2; | 293 int32_t target_offset = |
| 292 DCHECK(is_int32(target_offset)); | 294 static_cast<int32_t>(DistanceTo(target) >> kInstructionSizeLog2); |
| 293 uint32_t high16 = unsigned_bitextract_32(31, 16, target_offset); | 295 uint32_t high16 = unsigned_bitextract_32(31, 16, target_offset); |
| 294 uint32_t low16 = unsigned_bitextract_32(15, 0, target_offset); | 296 uint32_t low16 = unsigned_bitextract_32(15, 0, target_offset); |
| 295 | 297 |
| 296 PatchingAssembler patcher(this, 2); | 298 PatchingAssembler patcher(this, 2); |
| 297 patcher.brk(high16); | 299 patcher.brk(high16); |
| 298 patcher.brk(low16); | 300 patcher.brk(low16); |
| 299 } | 301 } |
| 300 | 302 |
| 301 | 303 |
| 302 void Instruction::SetImmLLiteral(Instruction* source) { | 304 void Instruction::SetImmLLiteral(Instruction* source) { |
| 303 DCHECK(IsLdrLiteral()); | 305 DCHECK(IsLdrLiteral()); |
| 304 DCHECK(IsAligned(DistanceTo(source), kInstructionSize)); | 306 DCHECK(IsAligned(DistanceTo(source), kInstructionSize)); |
| 305 ptrdiff_t offset = DistanceTo(source) >> kLoadLiteralScaleLog2; | 307 DCHECK(Assembler::IsImmLLiteral(DistanceTo(source))); |
| 306 Instr imm = Assembler::ImmLLiteral(offset); | 308 Instr imm = Assembler::ImmLLiteral( |
| 309 static_cast<int>(DistanceTo(source) >> kLoadLiteralScaleLog2)); |
| 307 Instr mask = ImmLLiteral_mask; | 310 Instr mask = ImmLLiteral_mask; |
| 308 | 311 |
| 309 SetInstructionBits(Mask(~mask) | imm); | 312 SetInstructionBits(Mask(~mask) | imm); |
| 310 } | 313 } |
| 311 | 314 |
| 312 | 315 |
| 313 // TODO(jbramley): We can't put this inline in the class because things like | 316 // TODO(jbramley): We can't put this inline in the class because things like |
| 314 // xzr and Register are not defined in that header. Consider adding | 317 // xzr and Register are not defined in that header. Consider adding |
| 315 // instructions-arm64-inl.h to work around this. | 318 // instructions-arm64-inl.h to work around this. |
| 316 bool InstructionSequence::IsInlineData() const { | 319 bool InstructionSequence::IsInlineData() const { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 330 uint64_t payload = ImmMoveWide(); | 333 uint64_t payload = ImmMoveWide(); |
| 331 // TODO(all): If we extend ::InlineData() to support bigger data, we need | 334 // TODO(all): If we extend ::InlineData() to support bigger data, we need |
| 332 // to update this method too. | 335 // to update this method too. |
| 333 return payload; | 336 return payload; |
| 334 } | 337 } |
| 335 | 338 |
| 336 | 339 |
| 337 } } // namespace v8::internal | 340 } } // namespace v8::internal |
| 338 | 341 |
| 339 #endif // V8_TARGET_ARCH_ARM64 | 342 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |