| Index: src/arm64/instructions-arm64.cc | 
| diff --git a/src/arm64/instructions-arm64.cc b/src/arm64/instructions-arm64.cc | 
| index 4b419d6dbdb152de5c344b52a817746e95cb3570..7c8776d8d0897f223b4671001687360c6dd1de66 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(LoadStoreOpMask)); | 
| +    LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreMask)); | 
| switch (op) { | 
| case LDRB_w: | 
| case LDRH_w: | 
| @@ -32,8 +32,12 @@ 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: return true; | 
| +      case LDR_d: | 
| +      case LDR_q: | 
| +        return true; | 
| default: return false; | 
| } | 
| } | 
| @@ -48,14 +52,18 @@ bool Instruction::IsStore() const { | 
| if (Mask(LoadStorePairAnyFMask) == LoadStorePairAnyFixed) { | 
| return Mask(LoadStorePairLBit) == 0; | 
| } else { | 
| -    LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreOpMask)); | 
| +    LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreMask)); | 
| 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: return true; | 
| +      case STR_d: | 
| +      case STR_q: | 
| +        return true; | 
| default: return false; | 
| } | 
| } | 
| @@ -139,43 +147,48 @@ uint64_t Instruction::ImmLogical() { | 
| return 0; | 
| } | 
|  | 
| - | 
| -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); | 
| - | 
| -  return rawbits_to_float(result); | 
| +uint32_t Instruction::ImmNEONabcdefgh() const { | 
| +  return ImmNEONabc() << 5 | ImmNEONdefgh(); | 
| } | 
|  | 
| +float Instruction::ImmFP32() { return Imm8ToFP32(ImmFP()); } | 
| + | 
| +double Instruction::ImmFP64() { return Imm8ToFP64(ImmFP()); } | 
|  | 
| -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); | 
| +float Instruction::ImmNEONFP32() const { return Imm8ToFP32(ImmNEONabcdefgh()); } | 
|  | 
| -  return rawbits_to_double(result); | 
| +double Instruction::ImmNEONFP64() const { | 
| +  return Imm8ToFP64(ImmNEONabcdefgh()); | 
| } | 
|  | 
| +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; | 
| +} | 
|  | 
| -LSDataSize CalcLSPairDataSize(LoadStorePairOp op) { | 
| +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."); | 
| switch (op) { | 
| +    case STP_q: | 
| +    case LDP_q: | 
| +      return kQRegSizeLog2; | 
| case STP_x: | 
| case LDP_x: | 
| case STP_d: | 
| -    case LDP_d: return LSDoubleWord; | 
| -    default: return LSWord; | 
| +    case LDP_d: | 
| +      return kXRegSizeLog2; | 
| +    default: | 
| +      return kWRegSizeLog2; | 
| } | 
| } | 
|  | 
| @@ -334,7 +347,416 @@ 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 | 
|  | 
|  |