Index: src/arm64/instructions-arm64.cc |
diff --git a/src/arm64/instructions-arm64.cc b/src/arm64/instructions-arm64.cc |
index d23533d8bc7ce629cea809867d1eaa71e0179308..da16826eb2987fe7244e3702a8b27536af676b6d 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() { |
- // 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); |
+double Instruction::ImmFP64() { return Imm8ToFP64(ImmFP()); } |
- return rawbits_to_double(result); |
+float Instruction::ImmNEONFP32() const { return Imm8ToFP32(ImmNEONabcdefgh()); } |
+ |
+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; |
} |
} |
@@ -335,7 +348,299 @@ 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)); |
+} |
} // namespace internal |
} // namespace v8 |