Index: src/arm64/instructions-arm64.cc |
diff --git a/src/arm64/instructions-arm64.cc b/src/arm64/instructions-arm64.cc |
index 7c8776d8d0897f223b4671001687360c6dd1de66..4b419d6dbdb152de5c344b52a817746e95cb3570 100644 |
--- a/src/arm64/instructions-arm64.cc |
+++ b/src/arm64/instructions-arm64.cc |
@@ -21,7 +21,7 @@ bool Instruction::IsLoad() const { |
if (Mask(LoadStorePairAnyFMask) == LoadStorePairAnyFixed) { |
return Mask(LoadStorePairLBit) != 0; |
} else { |
- LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreMask)); |
+ LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreOpMask)); |
switch (op) { |
case LDRB_w: |
case LDRH_w: |
@@ -32,12 +32,8 @@ bool Instruction::IsLoad() const { |
case LDRSH_w: |
case LDRSH_x: |
case LDRSW_x: |
- case LDR_b: |
- case LDR_h: |
case LDR_s: |
- case LDR_d: |
- case LDR_q: |
- return true; |
+ case LDR_d: return true; |
default: return false; |
} |
} |
@@ -52,18 +48,14 @@ bool Instruction::IsStore() const { |
if (Mask(LoadStorePairAnyFMask) == LoadStorePairAnyFixed) { |
return Mask(LoadStorePairLBit) == 0; |
} else { |
- LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreMask)); |
+ LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreOpMask)); |
switch (op) { |
case STRB_w: |
case STRH_w: |
case STR_w: |
case STR_x: |
- case STR_b: |
- case STR_h: |
case STR_s: |
- case STR_d: |
- case STR_q: |
- return true; |
+ case STR_d: return true; |
default: return false; |
} |
} |
@@ -147,48 +139,43 @@ uint64_t Instruction::ImmLogical() { |
return 0; |
} |
-uint32_t Instruction::ImmNEONabcdefgh() const { |
- return ImmNEONabc() << 5 | ImmNEONdefgh(); |
-} |
-float Instruction::ImmFP32() { return Imm8ToFP32(ImmFP()); } |
+float Instruction::ImmFP32() { |
+ // ImmFP: abcdefgh (8 bits) |
+ // Single: aBbb.bbbc.defg.h000.0000.0000.0000.0000 (32 bits) |
+ // where B is b ^ 1 |
+ uint32_t bits = ImmFP(); |
+ uint32_t bit7 = (bits >> 7) & 0x1; |
+ uint32_t bit6 = (bits >> 6) & 0x1; |
+ uint32_t bit5_to_0 = bits & 0x3f; |
+ uint32_t result = (bit7 << 31) | ((32 - bit6) << 25) | (bit5_to_0 << 19); |
-double Instruction::ImmFP64() { return Imm8ToFP64(ImmFP()); } |
+ return rawbits_to_float(result); |
+} |
-float Instruction::ImmNEONFP32() const { return Imm8ToFP32(ImmNEONabcdefgh()); } |
-double Instruction::ImmNEONFP64() const { |
- return Imm8ToFP64(ImmNEONabcdefgh()); |
-} |
+double Instruction::ImmFP64() { |
+ // ImmFP: abcdefgh (8 bits) |
+ // Double: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000 |
+ // 0000.0000.0000.0000.0000.0000.0000.0000 (64 bits) |
+ // where B is b ^ 1 |
+ uint32_t bits = ImmFP(); |
+ uint64_t bit7 = (bits >> 7) & 0x1; |
+ uint64_t bit6 = (bits >> 6) & 0x1; |
+ uint64_t bit5_to_0 = bits & 0x3f; |
+ uint64_t result = (bit7 << 63) | ((256 - bit6) << 54) | (bit5_to_0 << 48); |
-unsigned CalcLSDataSize(LoadStoreOp op) { |
- DCHECK_EQ(static_cast<unsigned>(LSSize_offset + LSSize_width), |
- kInstructionSize * 8); |
- unsigned size = static_cast<Instr>(op) >> LSSize_offset; |
- if ((op & LSVector_mask) != 0) { |
- // Vector register memory operations encode the access size in the "size" |
- // and "opc" fields. |
- if ((size == 0) && ((op & LSOpc_mask) >> LSOpc_offset) >= 2) { |
- size = kQRegSizeLog2; |
- } |
- } |
- return size; |
+ return rawbits_to_double(result); |
} |
-unsigned CalcLSPairDataSize(LoadStorePairOp op) { |
- static_assert(kXRegSize == kDRegSize, "X and D registers must be same size."); |
- static_assert(kWRegSize == kSRegSize, "W and S registers must be same size."); |
+ |
+LSDataSize CalcLSPairDataSize(LoadStorePairOp op) { |
switch (op) { |
- case STP_q: |
- case LDP_q: |
- return kQRegSizeLog2; |
case STP_x: |
case LDP_x: |
case STP_d: |
- case LDP_d: |
- return kXRegSizeLog2; |
- default: |
- return kWRegSizeLog2; |
+ case LDP_d: return LSDoubleWord; |
+ default: return LSWord; |
} |
} |
@@ -347,416 +334,7 @@ uint64_t InstructionSequence::InlineData() const { |
return payload; |
} |
-VectorFormat VectorFormatHalfWidth(VectorFormat vform) { |
- DCHECK(vform == kFormat8H || vform == kFormat4S || vform == kFormat2D || |
- vform == kFormatH || vform == kFormatS || vform == kFormatD); |
- switch (vform) { |
- case kFormat8H: |
- return kFormat8B; |
- case kFormat4S: |
- return kFormat4H; |
- case kFormat2D: |
- return kFormat2S; |
- case kFormatH: |
- return kFormatB; |
- case kFormatS: |
- return kFormatH; |
- case kFormatD: |
- return kFormatS; |
- default: |
- UNREACHABLE(); |
- return kFormatUndefined; |
- } |
-} |
- |
-VectorFormat VectorFormatDoubleWidth(VectorFormat vform) { |
- DCHECK(vform == kFormat8B || vform == kFormat4H || vform == kFormat2S || |
- vform == kFormatB || vform == kFormatH || vform == kFormatS); |
- switch (vform) { |
- case kFormat8B: |
- return kFormat8H; |
- case kFormat4H: |
- return kFormat4S; |
- case kFormat2S: |
- return kFormat2D; |
- case kFormatB: |
- return kFormatH; |
- case kFormatH: |
- return kFormatS; |
- case kFormatS: |
- return kFormatD; |
- default: |
- UNREACHABLE(); |
- return kFormatUndefined; |
- } |
-} |
- |
-VectorFormat VectorFormatFillQ(VectorFormat vform) { |
- switch (vform) { |
- case kFormatB: |
- case kFormat8B: |
- case kFormat16B: |
- return kFormat16B; |
- case kFormatH: |
- case kFormat4H: |
- case kFormat8H: |
- return kFormat8H; |
- case kFormatS: |
- case kFormat2S: |
- case kFormat4S: |
- return kFormat4S; |
- case kFormatD: |
- case kFormat1D: |
- case kFormat2D: |
- return kFormat2D; |
- default: |
- UNREACHABLE(); |
- return kFormatUndefined; |
- } |
-} |
- |
-VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform) { |
- switch (vform) { |
- case kFormat4H: |
- return kFormat8B; |
- case kFormat8H: |
- return kFormat16B; |
- case kFormat2S: |
- return kFormat4H; |
- case kFormat4S: |
- return kFormat8H; |
- case kFormat1D: |
- return kFormat2S; |
- case kFormat2D: |
- return kFormat4S; |
- default: |
- UNREACHABLE(); |
- return kFormatUndefined; |
- } |
-} |
- |
-VectorFormat VectorFormatDoubleLanes(VectorFormat vform) { |
- DCHECK(vform == kFormat8B || vform == kFormat4H || vform == kFormat2S); |
- switch (vform) { |
- case kFormat8B: |
- return kFormat16B; |
- case kFormat4H: |
- return kFormat8H; |
- case kFormat2S: |
- return kFormat4S; |
- default: |
- UNREACHABLE(); |
- return kFormatUndefined; |
- } |
-} |
- |
-VectorFormat VectorFormatHalfLanes(VectorFormat vform) { |
- DCHECK(vform == kFormat16B || vform == kFormat8H || vform == kFormat4S); |
- switch (vform) { |
- case kFormat16B: |
- return kFormat8B; |
- case kFormat8H: |
- return kFormat4H; |
- case kFormat4S: |
- return kFormat2S; |
- default: |
- UNREACHABLE(); |
- return kFormatUndefined; |
- } |
-} |
- |
-VectorFormat ScalarFormatFromLaneSize(int laneSize) { |
- switch (laneSize) { |
- case 8: |
- return kFormatB; |
- case 16: |
- return kFormatH; |
- case 32: |
- return kFormatS; |
- case 64: |
- return kFormatD; |
- default: |
- UNREACHABLE(); |
- return kFormatUndefined; |
- } |
-} |
- |
-VectorFormat ScalarFormatFromFormat(VectorFormat vform) { |
- return ScalarFormatFromLaneSize(LaneSizeInBitsFromFormat(vform)); |
-} |
- |
-unsigned RegisterSizeInBytesFromFormat(VectorFormat vform) { |
- return RegisterSizeInBitsFromFormat(vform) / 8; |
-} |
- |
-unsigned RegisterSizeInBitsFromFormat(VectorFormat vform) { |
- DCHECK_NE(vform, kFormatUndefined); |
- switch (vform) { |
- case kFormatB: |
- return kBRegSizeInBits; |
- case kFormatH: |
- return kHRegSizeInBits; |
- case kFormatS: |
- return kSRegSizeInBits; |
- case kFormatD: |
- return kDRegSizeInBits; |
- case kFormat8B: |
- case kFormat4H: |
- case kFormat2S: |
- case kFormat1D: |
- return kDRegSizeInBits; |
- default: |
- return kQRegSizeInBits; |
- } |
-} |
- |
-unsigned LaneSizeInBitsFromFormat(VectorFormat vform) { |
- DCHECK_NE(vform, kFormatUndefined); |
- switch (vform) { |
- case kFormatB: |
- case kFormat8B: |
- case kFormat16B: |
- return 8; |
- case kFormatH: |
- case kFormat4H: |
- case kFormat8H: |
- return 16; |
- case kFormatS: |
- case kFormat2S: |
- case kFormat4S: |
- return 32; |
- case kFormatD: |
- case kFormat1D: |
- case kFormat2D: |
- return 64; |
- default: |
- UNREACHABLE(); |
- return 0; |
- } |
-} |
- |
-int LaneSizeInBytesFromFormat(VectorFormat vform) { |
- return LaneSizeInBitsFromFormat(vform) / 8; |
-} |
- |
-int LaneSizeInBytesLog2FromFormat(VectorFormat vform) { |
- DCHECK_NE(vform, kFormatUndefined); |
- switch (vform) { |
- case kFormatB: |
- case kFormat8B: |
- case kFormat16B: |
- return 0; |
- case kFormatH: |
- case kFormat4H: |
- case kFormat8H: |
- return 1; |
- case kFormatS: |
- case kFormat2S: |
- case kFormat4S: |
- return 2; |
- case kFormatD: |
- case kFormat1D: |
- case kFormat2D: |
- return 3; |
- default: |
- UNREACHABLE(); |
- return 0; |
- } |
-} |
- |
-int LaneCountFromFormat(VectorFormat vform) { |
- DCHECK_NE(vform, kFormatUndefined); |
- switch (vform) { |
- case kFormat16B: |
- return 16; |
- case kFormat8B: |
- case kFormat8H: |
- return 8; |
- case kFormat4H: |
- case kFormat4S: |
- return 4; |
- case kFormat2S: |
- case kFormat2D: |
- return 2; |
- case kFormat1D: |
- case kFormatB: |
- case kFormatH: |
- case kFormatS: |
- case kFormatD: |
- return 1; |
- default: |
- UNREACHABLE(); |
- return 0; |
- } |
-} |
- |
-int MaxLaneCountFromFormat(VectorFormat vform) { |
- DCHECK_NE(vform, kFormatUndefined); |
- switch (vform) { |
- case kFormatB: |
- case kFormat8B: |
- case kFormat16B: |
- return 16; |
- case kFormatH: |
- case kFormat4H: |
- case kFormat8H: |
- return 8; |
- case kFormatS: |
- case kFormat2S: |
- case kFormat4S: |
- return 4; |
- case kFormatD: |
- case kFormat1D: |
- case kFormat2D: |
- return 2; |
- default: |
- UNREACHABLE(); |
- return 0; |
- } |
-} |
- |
-// Does 'vform' indicate a vector format or a scalar format? |
-bool IsVectorFormat(VectorFormat vform) { |
- DCHECK_NE(vform, kFormatUndefined); |
- switch (vform) { |
- case kFormatB: |
- case kFormatH: |
- case kFormatS: |
- case kFormatD: |
- return false; |
- default: |
- return true; |
- } |
-} |
- |
-int64_t MaxIntFromFormat(VectorFormat vform) { |
- return INT64_MAX >> (64 - LaneSizeInBitsFromFormat(vform)); |
-} |
- |
-int64_t MinIntFromFormat(VectorFormat vform) { |
- return INT64_MIN >> (64 - LaneSizeInBitsFromFormat(vform)); |
-} |
- |
-uint64_t MaxUintFromFormat(VectorFormat vform) { |
- return UINT64_MAX >> (64 - LaneSizeInBitsFromFormat(vform)); |
-} |
- |
-NEONFormatDecoder::NEONFormatDecoder(const Instruction* instr) { |
- instrbits_ = instr->InstructionBits(); |
- SetFormatMaps(IntegerFormatMap()); |
-} |
- |
-NEONFormatDecoder::NEONFormatDecoder(const Instruction* instr, |
- const NEONFormatMap* format) { |
- instrbits_ = instr->InstructionBits(); |
- SetFormatMaps(format); |
-} |
- |
-NEONFormatDecoder::NEONFormatDecoder(const Instruction* instr, |
- const NEONFormatMap* format0, |
- const NEONFormatMap* format1) { |
- instrbits_ = instr->InstructionBits(); |
- SetFormatMaps(format0, format1); |
-} |
- |
-NEONFormatDecoder::NEONFormatDecoder(const Instruction* instr, |
- const NEONFormatMap* format0, |
- const NEONFormatMap* format1, |
- const NEONFormatMap* format2) { |
- instrbits_ = instr->InstructionBits(); |
- SetFormatMaps(format0, format1, format2); |
-} |
- |
-void NEONFormatDecoder::SetFormatMaps(const NEONFormatMap* format0, |
- const NEONFormatMap* format1, |
- const NEONFormatMap* format2) { |
- DCHECK_NOT_NULL(format0); |
- formats_[0] = format0; |
- formats_[1] = (format1 == NULL) ? formats_[0] : format1; |
- formats_[2] = (format2 == NULL) ? formats_[1] : format2; |
-} |
- |
-void NEONFormatDecoder::SetFormatMap(unsigned index, |
- const NEONFormatMap* format) { |
- DCHECK_LT(index, arraysize(formats_)); |
- DCHECK_NOT_NULL(format); |
- formats_[index] = format; |
-} |
- |
-const char* NEONFormatDecoder::SubstitutePlaceholders(const char* string) { |
- return Substitute(string, kPlaceholder, kPlaceholder, kPlaceholder); |
-} |
- |
-const char* NEONFormatDecoder::Substitute(const char* string, |
- SubstitutionMode mode0, |
- SubstitutionMode mode1, |
- SubstitutionMode mode2) { |
- snprintf(form_buffer_, sizeof(form_buffer_), string, GetSubstitute(0, mode0), |
- GetSubstitute(1, mode1), GetSubstitute(2, mode2)); |
- return form_buffer_; |
-} |
- |
-const char* NEONFormatDecoder::Mnemonic(const char* mnemonic) { |
- if ((instrbits_ & NEON_Q) != 0) { |
- snprintf(mne_buffer_, sizeof(mne_buffer_), "%s2", mnemonic); |
- return mne_buffer_; |
- } |
- return mnemonic; |
-} |
- |
-VectorFormat NEONFormatDecoder::GetVectorFormat(int format_index) { |
- return GetVectorFormat(formats_[format_index]); |
-} |
- |
-VectorFormat NEONFormatDecoder::GetVectorFormat( |
- const NEONFormatMap* format_map) { |
- static const VectorFormat vform[] = { |
- kFormatUndefined, kFormat8B, kFormat16B, kFormat4H, kFormat8H, |
- kFormat2S, kFormat4S, kFormat1D, kFormat2D, kFormatB, |
- kFormatH, kFormatS, kFormatD}; |
- DCHECK_LT(GetNEONFormat(format_map), arraysize(vform)); |
- return vform[GetNEONFormat(format_map)]; |
-} |
-const char* NEONFormatDecoder::GetSubstitute(int index, SubstitutionMode mode) { |
- if (mode == kFormat) { |
- return NEONFormatAsString(GetNEONFormat(formats_[index])); |
- } |
- DCHECK_EQ(mode, kPlaceholder); |
- return NEONFormatAsPlaceholder(GetNEONFormat(formats_[index])); |
-} |
- |
-NEONFormat NEONFormatDecoder::GetNEONFormat(const NEONFormatMap* format_map) { |
- return format_map->map[PickBits(format_map->bits)]; |
-} |
- |
-const char* NEONFormatDecoder::NEONFormatAsString(NEONFormat format) { |
- static const char* formats[] = {"undefined", "8b", "16b", "4h", "8h", |
- "2s", "4s", "1d", "2d", "b", |
- "h", "s", "d"}; |
- DCHECK_LT(format, arraysize(formats)); |
- return formats[format]; |
-} |
- |
-const char* NEONFormatDecoder::NEONFormatAsPlaceholder(NEONFormat format) { |
- DCHECK((format == NF_B) || (format == NF_H) || (format == NF_S) || |
- (format == NF_D) || (format == NF_UNDEF)); |
- static const char* formats[] = { |
- "undefined", "undefined", "undefined", "undefined", "undefined", |
- "undefined", "undefined", "undefined", "undefined", "'B", |
- "'H", "'S", "'D"}; |
- return formats[format]; |
-} |
- |
-uint8_t NEONFormatDecoder::PickBits(const uint8_t bits[]) { |
- uint8_t result = 0; |
- for (unsigned b = 0; b < kNEONFormatMaxBits; b++) { |
- if (bits[b] == 0) break; |
- result <<= 1; |
- result |= ((instrbits_ & (1 << bits[b])) == 0) ? 0 : 1; |
- } |
- return result; |
-} |
} // namespace internal |
} // namespace v8 |