5 #if V8_TARGET_ARCH_ARM64 7 #include "src/arm64/assembler-arm64-inl.h" 8 #include "src/arm64/instructions-arm64.h" 13 bool Instruction::IsLoad()
const {
14 if (Mask(LoadStoreAnyFMask) != LoadStoreAnyFixed) {
18 if (Mask(LoadStorePairAnyFMask) == LoadStorePairAnyFixed) {
19 return Mask(LoadStorePairLBit) != 0;
21 LoadStoreOp op =
static_cast<LoadStoreOp
>(Mask(LoadStoreMask));
38 default:
return false;
44 bool Instruction::IsStore()
const {
45 if (Mask(LoadStoreAnyFMask) != LoadStoreAnyFixed) {
49 if (Mask(LoadStorePairAnyFMask) == LoadStorePairAnyFixed) {
50 return Mask(LoadStorePairLBit) == 0;
52 LoadStoreOp op =
static_cast<LoadStoreOp
>(Mask(LoadStoreMask));
64 default:
return false;
70 static uint64_t RotateRight(uint64_t value,
75 return ((value & ((1ULL << rotate) - 1ULL)) << (width - rotate)) |
80 static uint64_t RepeatBitsAcrossReg(
unsigned reg_size,
83 DCHECK((width == 2) || (width == 4) || (width == 8) || (width == 16) ||
85 DCHECK((reg_size == kWRegSizeInBits) || (reg_size == kXRegSizeInBits));
86 uint64_t result = value & ((1ULL << width) - 1ULL);
87 for (
unsigned i = width;
i < reg_size;
i *= 2) {
88 result |= (result <<
i);
97 uint64_t Instruction::ImmLogical() {
98 unsigned reg_size = SixtyFourBits() ? kXRegSizeInBits : kWRegSizeInBits;
100 int32_t imm_s = ImmSetBits();
101 int32_t imm_r = ImmRotate();
124 uint64_t bits = (1ULL << (imm_s + 1)) - 1;
125 return RotateRight(bits, imm_r, 64);
127 if ((imm_s >> 1) == 0x1F) {
130 for (
int width = 0x20; width >= 0x2; width >>= 1) {
131 if ((imm_s & width) == 0) {
132 int mask = width - 1;
133 if ((imm_s & mask) == mask) {
136 uint64_t bits = (1ULL << ((imm_s & mask) + 1)) - 1;
137 return RepeatBitsAcrossReg(reg_size,
138 RotateRight(bits, imm_r & mask, width),
146 uint32_t Instruction::ImmNEONabcdefgh()
const {
147 return ImmNEONabc() << 5 | ImmNEONdefgh();
150 float Instruction::ImmFP32() {
return Imm8ToFP32(ImmFP()); }
152 double Instruction::ImmFP64() {
return Imm8ToFP64(ImmFP()); }
154 float Instruction::ImmNEONFP32()
const {
return Imm8ToFP32(ImmNEONabcdefgh()); }
156 double Instruction::ImmNEONFP64()
const {
157 return Imm8ToFP64(ImmNEONabcdefgh());
160 unsigned CalcLSDataSize(LoadStoreOp op) {
161 DCHECK_EQ(static_cast<unsigned>(LSSize_offset + LSSize_width),
163 unsigned size =
static_cast<Instr
>(op) >> LSSize_offset;
164 if ((op & LSVector_mask) != 0) {
167 if ((size == 0) && ((op & LSOpc_mask) >> LSOpc_offset) >= 2) {
168 size = kQRegSizeLog2;
174 unsigned CalcLSPairDataSize(LoadStorePairOp op) {
175 static_assert(kXRegSize == kDRegSize,
"X and D registers must be same size.");
176 static_assert(kWRegSize == kSRegSize,
"W and S registers must be same size.");
180 return kQRegSizeLog2;
185 return kXRegSizeLog2;
187 return kWRegSizeLog2;
192 int64_t Instruction::ImmPCOffset() {
194 if (IsPCRelAddressing()) {
197 }
else if (BranchType() != UnknownBranchType) {
200 offset = ImmBranch() << kInstrSizeLog2;
201 }
else if (IsUnresolvedInternalReference()) {
203 offset = ImmUnresolvedInternalReference() << kInstrSizeLog2;
206 DCHECK(IsLdrLiteral());
209 offset = ImmLLiteral() << kInstrSizeLog2;
215 Instruction* Instruction::ImmPCOffsetTarget() {
216 return InstructionAtOffset(ImmPCOffset());
220 bool Instruction::IsValidImmPCOffset(ImmBranchType branch_type,
222 return is_intn(offset, ImmBranchRangeBitwidth(branch_type));
226 bool Instruction::IsTargetInImmPCOffsetRange(Instruction* target) {
227 return IsValidImmPCOffset(BranchType(), DistanceTo(target));
230 void Instruction::SetImmPCOffsetTarget(
const AssemblerOptions& options,
231 Instruction* target) {
232 if (IsPCRelAddressing()) {
233 SetPCRelImmTarget(options, target);
234 }
else if (BranchType() != UnknownBranchType) {
235 SetBranchImmTarget(target);
236 }
else if (IsUnresolvedInternalReference()) {
237 SetUnresolvedInternalReferenceImmTarget(options, target);
240 SetImmLLiteral(target);
244 void Instruction::SetPCRelImmTarget(
const AssemblerOptions& options,
245 Instruction* target) {
249 ptrdiff_t target_offset = DistanceTo(target);
251 if (Instruction::IsValidPCRelOffset(target_offset)) {
252 imm = Assembler::ImmPCRelAddress(static_cast<int>(target_offset));
253 SetInstructionBits(Mask(~ImmPCRel_mask) | imm);
255 PatchingAssembler patcher(options, reinterpret_cast<byte*>(
this),
256 PatchingAssembler::kAdrFarPatchableNInstrs);
257 patcher.PatchAdrFar(target_offset);
262 void Instruction::SetBranchImmTarget(Instruction* target) {
263 DCHECK(IsAligned(DistanceTo(target), kInstrSize));
265 IsValidImmPCOffset(BranchType(), DistanceTo(target) >> kInstrSizeLog2));
266 int offset =
static_cast<int>(DistanceTo(target) >> kInstrSizeLog2);
267 Instr branch_imm = 0;
269 switch (BranchType()) {
270 case CondBranchType: {
271 branch_imm = Assembler::ImmCondBranch(offset);
272 imm_mask = ImmCondBranch_mask;
275 case UncondBranchType: {
276 branch_imm = Assembler::ImmUncondBranch(offset);
277 imm_mask = ImmUncondBranch_mask;
280 case CompareBranchType: {
281 branch_imm = Assembler::ImmCmpBranch(offset);
282 imm_mask = ImmCmpBranch_mask;
285 case TestBranchType: {
286 branch_imm = Assembler::ImmTestBranch(offset);
287 imm_mask = ImmTestBranch_mask;
290 default: UNREACHABLE();
292 SetInstructionBits(Mask(~imm_mask) | branch_imm);
295 void Instruction::SetUnresolvedInternalReferenceImmTarget(
296 const AssemblerOptions& options, Instruction* target) {
297 DCHECK(IsUnresolvedInternalReference());
298 DCHECK(IsAligned(DistanceTo(target), kInstrSize));
299 DCHECK(is_int32(DistanceTo(target) >> kInstrSizeLog2));
300 int32_t target_offset =
301 static_cast<int32_t
>(DistanceTo(target) >> kInstrSizeLog2);
302 uint32_t high16 = unsigned_bitextract_32(31, 16, target_offset);
303 uint32_t low16 = unsigned_bitextract_32(15, 0, target_offset);
305 PatchingAssembler patcher(options, reinterpret_cast<byte*>(
this), 2);
311 void Instruction::SetImmLLiteral(Instruction* source) {
312 DCHECK(IsLdrLiteral());
313 DCHECK(IsAligned(DistanceTo(source), kInstrSize));
314 DCHECK(Assembler::IsImmLLiteral(DistanceTo(source)));
315 Instr imm = Assembler::ImmLLiteral(
316 static_cast<int>(DistanceTo(source) >> kLoadLiteralScaleLog2));
317 Instr mask = ImmLLiteral_mask;
319 SetInstructionBits(Mask(~mask) | imm);
326 bool InstructionSequence::IsInlineData()
const {
329 return IsMovz() && SixtyFourBits() && (Rd() == kZeroRegCode);
338 uint64_t InstructionSequence::InlineData()
const {
339 DCHECK(IsInlineData());
340 uint64_t payload = ImmMoveWide();
346 VectorFormat VectorFormatHalfWidth(VectorFormat vform) {
347 DCHECK(vform == kFormat8H || vform == kFormat4S || vform == kFormat2D ||
348 vform == kFormatH || vform == kFormatS || vform == kFormatD);
367 VectorFormat VectorFormatDoubleWidth(VectorFormat vform) {
368 DCHECK(vform == kFormat8B || vform == kFormat4H || vform == kFormat2S ||
369 vform == kFormatB || vform == kFormatH || vform == kFormatS);
388 VectorFormat VectorFormatFillQ(VectorFormat vform) {
411 VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform) {
430 VectorFormat VectorFormatDoubleLanes(VectorFormat vform) {
431 DCHECK(vform == kFormat8B || vform == kFormat4H || vform == kFormat2S);
444 VectorFormat VectorFormatHalfLanes(VectorFormat vform) {
445 DCHECK(vform == kFormat16B || vform == kFormat8H || vform == kFormat4S);
458 VectorFormat ScalarFormatFromLaneSize(
int laneSize) {
473 VectorFormat ScalarFormatFromFormat(VectorFormat vform) {
474 return ScalarFormatFromLaneSize(LaneSizeInBitsFromFormat(vform));
477 unsigned RegisterSizeInBytesFromFormat(VectorFormat vform) {
478 return RegisterSizeInBitsFromFormat(vform) / 8;
481 unsigned RegisterSizeInBitsFromFormat(VectorFormat vform) {
482 DCHECK_NE(vform, kFormatUndefined);
485 return kBRegSizeInBits;
487 return kHRegSizeInBits;
489 return kSRegSizeInBits;
491 return kDRegSizeInBits;
496 return kDRegSizeInBits;
498 return kQRegSizeInBits;
502 unsigned LaneSizeInBitsFromFormat(VectorFormat vform) {
503 DCHECK_NE(vform, kFormatUndefined);
526 int LaneSizeInBytesFromFormat(VectorFormat vform) {
527 return LaneSizeInBitsFromFormat(vform) / 8;
530 int LaneSizeInBytesLog2FromFormat(VectorFormat vform) {
531 DCHECK_NE(vform, kFormatUndefined);
554 int LaneCountFromFormat(VectorFormat vform) {
555 DCHECK_NE(vform, kFormatUndefined);
579 int MaxLaneCountFromFormat(VectorFormat vform) {
580 DCHECK_NE(vform, kFormatUndefined);
604 bool IsVectorFormat(VectorFormat vform) {
605 DCHECK_NE(vform, kFormatUndefined);
617 int64_t MaxIntFromFormat(VectorFormat vform) {
618 return INT64_MAX >> (64 - LaneSizeInBitsFromFormat(vform));
621 int64_t MinIntFromFormat(VectorFormat vform) {
622 return INT64_MIN >> (64 - LaneSizeInBitsFromFormat(vform));
625 uint64_t MaxUintFromFormat(VectorFormat vform) {
626 return UINT64_MAX >> (64 - LaneSizeInBitsFromFormat(vform));
629 NEONFormatDecoder::NEONFormatDecoder(
const Instruction* instr) {
630 instrbits_ = instr->InstructionBits();
631 SetFormatMaps(IntegerFormatMap());
634 NEONFormatDecoder::NEONFormatDecoder(
const Instruction* instr,
635 const NEONFormatMap* format) {
636 instrbits_ = instr->InstructionBits();
637 SetFormatMaps(format);
640 NEONFormatDecoder::NEONFormatDecoder(
const Instruction* instr,
641 const NEONFormatMap* format0,
642 const NEONFormatMap* format1) {
643 instrbits_ = instr->InstructionBits();
644 SetFormatMaps(format0, format1);
647 NEONFormatDecoder::NEONFormatDecoder(
const Instruction* instr,
648 const NEONFormatMap* format0,
649 const NEONFormatMap* format1,
650 const NEONFormatMap* format2) {
651 instrbits_ = instr->InstructionBits();
652 SetFormatMaps(format0, format1, format2);
655 void NEONFormatDecoder::SetFormatMaps(
const NEONFormatMap* format0,
656 const NEONFormatMap* format1,
657 const NEONFormatMap* format2) {
658 DCHECK_NOT_NULL(format0);
659 formats_[0] = format0;
660 formats_[1] = (format1 ==
nullptr) ? formats_[0] : format1;
661 formats_[2] = (format2 ==
nullptr) ? formats_[1] : format2;
664 void NEONFormatDecoder::SetFormatMap(
unsigned index,
665 const NEONFormatMap* format) {
666 DCHECK_LT(index, arraysize(formats_));
667 DCHECK_NOT_NULL(format);
668 formats_[index] = format;
671 const char* NEONFormatDecoder::SubstitutePlaceholders(
const char*
string) {
672 return Substitute(
string, kPlaceholder, kPlaceholder, kPlaceholder);
675 const char* NEONFormatDecoder::Substitute(
const char*
string,
676 SubstitutionMode mode0,
677 SubstitutionMode mode1,
678 SubstitutionMode mode2) {
679 snprintf(form_buffer_,
sizeof(form_buffer_),
string, GetSubstitute(0, mode0),
680 GetSubstitute(1, mode1), GetSubstitute(2, mode2));
684 const char* NEONFormatDecoder::Mnemonic(
const char* mnemonic) {
685 if ((instrbits_ & NEON_Q) != 0) {
686 snprintf(mne_buffer_,
sizeof(mne_buffer_),
"%s2", mnemonic);
692 VectorFormat NEONFormatDecoder::GetVectorFormat(
int format_index) {
693 return GetVectorFormat(formats_[format_index]);
696 VectorFormat NEONFormatDecoder::GetVectorFormat(
697 const NEONFormatMap* format_map) {
698 static const VectorFormat vform[] = {
699 kFormatUndefined, kFormat8B, kFormat16B, kFormat4H, kFormat8H,
700 kFormat2S, kFormat4S, kFormat1D, kFormat2D, kFormatB,
701 kFormatH, kFormatS, kFormatD};
702 DCHECK_LT(GetNEONFormat(format_map), arraysize(vform));
703 return vform[GetNEONFormat(format_map)];
706 const char* NEONFormatDecoder::GetSubstitute(
int index, SubstitutionMode mode) {
707 if (mode == kFormat) {
708 return NEONFormatAsString(GetNEONFormat(formats_[index]));
710 DCHECK_EQ(mode, kPlaceholder);
711 return NEONFormatAsPlaceholder(GetNEONFormat(formats_[index]));
714 NEONFormat NEONFormatDecoder::GetNEONFormat(
const NEONFormatMap* format_map) {
715 return format_map->map[PickBits(format_map->bits)];
718 const char* NEONFormatDecoder::NEONFormatAsString(NEONFormat format) {
719 static const char* formats[] = {
"undefined",
"8b",
"16b",
"4h",
"8h",
720 "2s",
"4s",
"1d",
"2d",
"b",
722 DCHECK_LT(format, arraysize(formats));
723 return formats[format];
726 const char* NEONFormatDecoder::NEONFormatAsPlaceholder(NEONFormat format) {
727 DCHECK((format == NF_B) || (format == NF_H) || (format == NF_S) ||
728 (format == NF_D) || (format == NF_UNDEF));
729 static const char* formats[] = {
730 "undefined",
"undefined",
"undefined",
"undefined",
"undefined",
731 "undefined",
"undefined",
"undefined",
"undefined",
"'B",
733 return formats[format];
736 uint8_t NEONFormatDecoder::PickBits(
const uint8_t bits[]) {
738 for (
unsigned b = 0; b < kNEONFormatMaxBits; b++) {
739 if (bits[b] == 0)
break;
741 result |= ((instrbits_ & (1 << bits[b])) == 0) ? 0 : 1;
748 #endif // V8_TARGET_ARCH_ARM64