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