Repository navigation
ARM additional arithmetic intrinsics #32512
Copy link
Copy link
Closed
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedarch-arm64area-System.Runtime.Intrinsics
Description
namespace System.Runtime.Intrinsics.Arm
{
public abstract class AdvSimd
{
/// <summary>
/// Add returning high narrow
/// For each element result[elem] = UpperHalf(left[elem] + right[elem])
/// Corresponds to vector forms of ADDHN and VADDHN
/// </summary>
Vector64<byte> AddHigh(Vector64<ushort> left, Vector64<ushort> right);
Vector64<sbyte> AddHigh(Vector64<short> left, Vector64<short> right);
Vector64<short> AddHigh(Vector64<int> left, Vector64<int> right);
Vector64<ushort> AddHigh(Vector64<uint> left, Vector64<uint> right);
Vector64<int> AddHigh(Vector64<long> left, Vector64<long> right);
Vector64<uint> AddHigh(Vector64<ulong> left, Vector64<ulong> right);
/// <summary>
/// Rounding add returning high narrow
/// For each element result[elem] = UpperHalf(left[elem] + right[elem] + 1)
/// Corresponds to vector forms of RADDHN and VRADHN
/// </summary>
Vector64<byte> RoundedAddHigh(Vector64<ushort> left, Vector64<ushort> right);
Vector64<sbyte> RoundedAddHigh(Vector64<short> left, Vector64<short> right);
Vector64<short> RoundedAddHigh(Vector64<int> left, Vector64<int> right);
Vector64<ushort> RoundedAddHigh(Vector64<uint> left, Vector64<uint> right);
Vector64<int> RoundedAddHigh(Vector64<long> left, Vector64<long> right);
Vector64<uint> RoundedAddHigh(Vector64<ulong> left, Vector64<ulong> right);
/// <summary>
/// Vector halving add
/// For each element result[elem] = (left[elem] + right[elem]) / 2
/// Corresponds to vector forms of SHADD/UHADD and VHADD
/// Supports byte, sbyte, short, ushort, int, uint
/// </summary>
Vector64<T> HalvingAdd(Vector64<T> left, Vector64<T> right);
Vector128<T> HalvingAdd(Vector128<T> left, Vector128<T> right);
/// <summary>
/// Vector rounding halving add
/// For each element result[elem] = (left[elem] + right[elem] + 1) / 2
/// Corresponds to vector forms of SRHADD/URHADD and VRHADD
/// Supports byte, sbyte, short, ushort, int, uint
/// </summary>
Vector64<T> RoundedHalvingAdd(Vector64<T> left, Vector64<T> right);
Vector128<T> RoundedHalvingAdd(Vector128<T> left, Vector128<T> right);
/// <summary>
/// Vector saturating add
/// For each element result[elem] = (left[elem] - right[elem]) / 2
/// Corresponds to vector forms of SQADD/UQADD and VQADD
/// Supports byte, sbyte, short, ushort, int, uint
/// Additionally supports long, ulong for V128
/// </summary>
Vector64<T> AddSaturate(Vector64<T> left, Vector64<T> right);
Vector128<T> AddSaturate(Vector128<T> left, Vector128<T> right);
/// <summary>
/// Subtract returning high narrow
/// For each element result[elem] = UpperHalf(left[elem] - right[elem])
/// Corresponds to vector forms of SUBHN and VSUBHN
/// </summary>
Vector64<byte> SubtractHigh(Vector64<ushort> left, Vector64<ushort> right);
Vector64<sbyte> SubtractHigh(Vector64<short> left, Vector64<short> right);
Vector64<short> SubtractHigh(Vector64<int> left, Vector64<int> right);
Vector64<ushort> SubtractHigh(Vector64<uint> left, Vector64<uint> right);
Vector64<int> SubtractHigh(Vector64<long> left, Vector64<long> right);
Vector64<uint> SubtractHigh(Vector64<ulong> left, Vector64<ulong> right);
/// <summary>
/// Rounding subtract returning high narrow
/// For each element result[elem] = UpperHalf(left[elem] - right[elem] + 1)
/// Corresponds to vector forms of RSUBHN and VRSUBHN
/// </summary>
Vector64<byte> RoundedSubtractHigh(Vector64<ushort> left, Vector64<ushort> right);
Vector64<sbyte> RoundedSubtractHigh(Vector64<short> left, Vector64<short> right);
Vector64<short> RoundedSubtractHigh(Vector64<int> left, Vector64<int> right);
Vector64<ushort> RoundedSubtractHigh(Vector64<uint> left, Vector64<uint> right);
Vector64<int> RoundedSubtractHigh(Vector64<long> left, Vector64<long> right);
Vector64<uint> RoundedSubtractHigh(Vector64<ulong> left, Vector64<ulong> right);
/// <summary>
/// Vector halving subtract
/// For each element result[elem] = (left[elem] - right[elem]) / 2
/// Corresponds to vector forms of SHSUB/UHSUB and VHSUB
/// Supports byte, sbyte, short, ushort, int, uint
/// </summary>
Vector64<T> HalvingSubtract(Vector64<T> left, Vector64<T> right);
Vector128<T> HalvingSubtract(Vector128<T> left, Vector128<T> right);
/// <summary>
/// Vector saturating subtract
/// For each element result[elem] = (left[elem] - right[elem]) / 2
/// Corresponds to vector forms of SQSUB/UQSUB and VQSUB
/// Supports byte, sbyte, short, ushort, int, uint
/// Additionally supports long, ulong for V128
/// </summary>
Vector64<T> SubtractSaturate(Vector64<T> left, Vector64<T> right);
Vector128<T> SubtractSaturate(Vector128<T> left, Vector128<T> right);
public abstract class Arm64
{
/// <summary>
/// Add returning high narrow
/// For each element result[elem] = UpperHalf(left[elem] + right[elem])
/// Corresponds to vector froms of ADDHN2
/// </summary>
Vector128<byte> AddHighUpper(Vector64<byte> lower, Vector64<ushort> left, Vector64<ushort> right);
Vector128<sbyte> AddHighUpper(Vector64<sbyte> lower, Vector64<short> left, Vector64<short> right);
Vector128<short> AddHighUpper(Vector64<short> lower, Vector64<int> left, Vector64<int> right);
Vector128<ushort> AddHighUpper(Vector64<ushort> lower, Vector64<uint> left, Vector64<uint> right);
Vector128<int> AddHighUpper(Vector64<int> lower, Vector64<long> left, Vector64<long> right);
Vector128<uint> AddHighUpper(Vector64<uint> lower, Vector64<ulong> left, Vector64<ulong> right);
/// <summary>
/// Rounding add returning high narrow
/// For each element result[elem] = UpperHalf(left[elem] + right[elem] + 1)
/// Corresponds to vector forms of RADDHN2
/// </summary>
Vector128<byte> RoundedAddHighUpper(Vector64<byte> lower, Vector64<ushort> left, Vector64<ushort> right);
Vector128<sbyte> RoundedAddHighUpper(Vector64<sbyte> lower, Vector64<short> left, Vector64<short> right);
Vector128<short> RoundedAddHighUpper(Vector64<short> lower, Vector64<int> left, Vector64<int> right);
Vector128<ushort> RoundedAddHighUpper(Vector64<ushort> lower, Vector64<uint> left, Vector64<uint> right);
Vector128<int> RoundedAddHighUpper(Vector64<int> lower, Vector64<long> left, Vector64<long> right);
Vector128<uint> RoundedAddHighUpper(Vector64<uint> lower, Vector64<ulong> left, Vector64<ulong> right);
/// <summary>
/// Scalar saturating add
/// For each element result[elem] = (left[elem] - right[elem]) / 2
/// Corresponds to vector forms of SQADD/UQADD
/// Supports byte, sbyte, short, ushort, int, uint, long, ulong
/// </summary>
Vector64<T> AddSaturateScalar(Vector64<T> left, Vector64<T> right);
/// <summary>
/// Subtract returning high narrow
/// For each element result[elem] = UpperHalf(left[elem] - right[elem])
/// Corresponds to vector forms of SUBHN2
/// </summary>
Vector128<byte> SubtractHighUpper(Vector64<byte> lower, Vector64<ushort> left, Vector64<ushort> right);
Vector128<sbyte> SubtractHighUpper(Vector64<sbyte> lower, Vector64<short> left, Vector64<short> right);
Vector128<short> SubtractHighUpper(Vector64<short> lower, Vector64<int> left, Vector64<int> right);
Vector128<ushort> SubtractHighUpper(Vector64<ushort> lower, Vector64<uint> left, Vector64<uint> right);
Vector128<int> SubtractHighUpper(Vector64<int> lower, Vector64<long> left, Vector64<long> right);
Vector128<uint> SubtractHighUpper(Vector64<uint> lower, Vector64<ulong> left, Vector64<ulong> right);
/// <summary>
/// Rounding subtract returning high narrow
/// For each element result[elem] = UpperHalf(left[elem] - right[elem] + 1)
/// Corresponds to vector forms of RSUBHN2
/// </summary>
Vector128<byte> RoundedSubtractHighUpper(Vector64<byte> lower, Vector64<ushort> left, Vector64<ushort> right);
Vector128<sbyte> RoundedSubtractHighUpper(Vector64<sbyte> lower, Vector64<short> left, Vector64<short> right);
Vector128<short> RoundedSubtractHighUpper(Vector64<short> lower, Vector64<int> left, Vector64<int> right);
Vector128<ushort> RoundedSubtractHighUpper(Vector64<ushort> lower, Vector64<uint> left, Vector64<uint> right);
Vector128<int> RoundedSubtractHighUpper(Vector64<int> lower, Vector64<long> left, Vector64<long> right);
Vector128<uint> RoundedSubtractHighUpper(Vector64<uint> lower, Vector64<ulong> left, Vector64<ulong> right);
/// <summary>
/// Scalar saturating subtract
/// For each element result[elem] = (left[elem] - right[elem]) / 2
/// Corresponds to vector forms of SQSUB/UQSUB
/// Supports byte, sbyte, short, ushort, int, uint, long, ulong
/// </summary>
Vector64<T> SubtractSaturateScalar(Vector64<T> left, Vector64<T> right);
/// <summary>
/// Signed/Unsigned Add and Accumulate Pairwise
/// For each element result[elem % 2] = value[elem % 2] + value[elem + 1]
/// Corresponds to vector forms of SADDLP and UADDLP
/// </summary>
public static Vector128<short> AddPairwiseAndWiden(Vector64<sbyte> value) { throw null; }
public static Vector128<ushort> AddPairwiseAndWiden(Vector64<byte> value) { throw null; }
public static Vector128<int> AddPairwiseAndWiden(Vector64<short> value) { throw null; }
public static Vector128<uint> AddPairwiseAndWiden(Vector64<ushort> value) { throw null; }
public static Vector128<long> AddPairwiseAndWiden(Vector64<int> value) { throw null; }
public static Vector128<ulong> AddPairwiseAndWiden(Vector64<uint> value) { throw null; }
/// <summary>
/// Signed/Unsigned Add and Accumulate Pairwise
/// For each element result[elem % 2] = addend[elem % 2] + (value[elem] + value[elem + 1])
/// Corresponds to vector forms of SADALP and UADALP
/// </summary>
public static Vector128<short> AddPairwiseAndWiden(Vector128<short> addend, Vector64<sbyte> value) { throw null; }
public static Vector128<ushort> AddPairwiseAndWiden(Vector128<ushort> addend, Vector64<byte> value) { throw null; }
public static Vector128<int> AddPairwiseAndWiden(Vector128<int> addend, Vector64<short> value) { throw null; }
public static Vector128<uint> AddPairwiseAndWiden(Vector128<uint> addend, Vector64<ushort> value) { throw null; }
public static Vector128<long> AddPairwiseAndWiden(Vector128<long> addend, Vector64<int> value) { throw null; }
public static Vector128<ulong> AddPairwiseAndWiden(Vector128<ulong> addend, Vector64<uint> value) { throw null; }
/// <summary>
/// Signed/Unsigned Absolute Difference and Accumulate Long
/// For each element result[elem] = left[elem] + right[elem]
/// Corresponds to vector forms of SABAL and UABAL
/// </summary>
public static Vector128<ushort> AbsoluteDifferenceAndWidenLow(Vector64<byte> left, Vector64<byte> right) { throw null; }
public static Vector128<ushort> AbsoluteDifferenceAndWidenLow(Vector64<sbyte> left, Vector64<sbyte> right) { throw null; }
public static Vector128<uint> AbsoluteDifferenceAndWidenLow(Vector64<ushort> left, Vector64<ushort> right) { throw null; }
public static Vector128<uint> AbsoluteDifferenceAndWidenLow(Vector64<short> left, Vector64<short> right) { throw null; }
public static Vector128<ulong> AbsoluteDifferenceAndWidenLow(Vector64<uint> left, Vector64<uint> right) { throw null; }
public static Vector128<ulong> AbsoluteDifferenceAndWidenLow(Vector64<int> left, Vector64<int> right) { throw null; }
/// <summary>
/// Signed/Unsigned Absolute Difference Long
/// For each element result[elem] = left[elem] + right[elem]
/// Corresponds to vector forms of SABAL2 and UABAL2
/// </summary>
public static Vector128<ushort> AbsoluteDifferenceAndWidenHigh(Vector128<byte> left, Vector128<byte> right) { throw null; }
public static Vector128<ushort> AbsoluteDifferenceAndWidenHigh(Vector128<sbyte> left, Vector128<sbyte> right) { throw null; }
public static Vector128<uint> AbsoluteDifferenceAndWidenHigh(Vector128<ushort> left, Vector128<ushort> right) { throw null; }
public static Vector128<uint> AbsoluteDifferenceAndWidenHigh(Vector128<short> left, Vector128<short> right) { throw null; }
public static Vector128<ulong> AbsoluteDifferenceAndWidenHigh(Vector128<uint> left, Vector128<uint> right) { throw null; }
public static Vector128<ulong> AbsoluteDifferenceAndWidenHigh(Vector128<int> left, Vector128<int> right) { throw null; }
/// <summary>
/// Signed/Unsigned Absolute Difference and Accumulate Long
/// For each element result[elem] = left[elem] + right[elem]
/// Corresponds to vector forms of SABAL and UABAL
/// </summary>
public static Vector128<ushort> AbsoluteDifferenceAddAndWidenLow(Vector128<ushort> addend, Vector64<byte> left, Vector64<byte> right) { throw null; }
public static Vector128<ushort> AbsoluteDifferenceAddAndWidenLow(Vector128<ushort> addend, Vector64<sbyte> left, Vector64<sbyte> right) { throw null; }
public static Vector128<uint> AbsoluteDifferenceAddAndWidenLow(Vector128<uint> addend, Vector64<ushort> left, Vector64<ushort> right) { throw null; }
public static Vector128<uint> AbsoluteDifferenceAddAndWidenLow(Vector128<uint> addend, Vector64<short> left, Vector64<short> right) { throw null; }
public static Vector128<ulong> AbsoluteDifferenceAddAndWidenLow(Vector128<ulong> addend, Vector64<uint> left, Vector64<uint> right) { throw null; }
public static Vector128<ulong> AbsoluteDifferenceAddAndWidenLow(Vector128<ulong> addend, Vector64<int> left, Vector64<int> right) { throw null; }
/// <summary>
/// Signed/Unsigned Absolute Difference and Accumulate Long
/// For each element result[elem] = left[elem] + right[elem]
/// Corresponds to vector forms of SABAL2 and UABAL2
/// </summary>
public static Vector128<ushort> AbsoluteDifferenceAddAndWidenHigh(Vector128<ushort> addend, Vector128<byte> left, Vector128<byte> right) { throw null; }
public static Vector128<ushort> AbsoluteDifferenceAddAndWidenHigh(Vector128<ushort> addend, Vector128<sbyte> left, Vector128<sbyte> right) { throw null; }
public static Vector128<uint> AbsoluteDifferenceAddAndWidenHigh(Vector128<uint> addend, Vector128<ushort> left, Vector128<ushort> right) { throw null; }
public static Vector128<uint> AbsoluteDifferenceAddAndWidenHigh(Vector128<uint> addend, Vector128<short> left, Vector128<short> right) { throw null; }
public static Vector128<ulong> AbsoluteDifferenceAddAndWidenHigh(Vector128<ulong> addend, Vector128<uint> left, Vector128<uint> right) { throw null; }
public static Vector128<ulong> AbsoluteDifferenceAddAndWidenHigh(Vector128<ulong> addend, Vector128<int> left, Vector128<int> right) { throw null; }
/// <summary>
/// Signed Add Long
/// For each element result[elem] = left[elem] + right[elem]
/// Corresponds to vector forms of SADDL and UADDL
/// </summary>
public static Vector128<short> AddAndWidenLow(Vector64<sbyte> left, Vector64<sbyte> right) { throw null; }
public static Vector128<ushort> AddAndWidenLow(Vector64<byte> left, Vector64<byte> right) { throw null; }
public static Vector128<int> AddAndWidenLow(Vector64<short> left, Vector64<short> right) { throw null; }
public static Vector128<uint> AddAndWidenLow(Vector64<ushort> left, Vector64<ushort> right) { throw null; }
public static Vector128<long> AddAndWidenLow(Vector64<int> left, Vector64<int> right) { throw null; }
public static Vector128<ulong> AddAndWidenLow(Vector64<uint> left, Vector64<uint> right) { throw null; }
/// <summary>
/// Signed Add Long
/// For each element result[elem] = left[elem] + right[elem]
/// Corresponds to vector forms of SADDL2 and UADDL2
/// </summary>
public static Vector128<short> AddAndWidenHigh(Vector128<sbyte> left, Vector128<sbyte> right) { throw null; }
public static Vector128<ushort> AddAndWidenHigh(Vector128<byte> left, Vector128<byte> right) { throw null; }
public static Vector128<int> AddAndWidenHigh(Vector128<short> left, Vector128<short> right) { throw null; }
public static Vector128<uint> AddAndWidenHigh(Vector128<ushort> left, Vector128<ushort> right) { throw null; }
public static Vector128<long> AddAndWidenHigh(Vector128<int> left, Vector128<int> right) { throw null; }
public static Vector128<ulong> AddAndWidenHigh(Vector128<uint> left, Vector128<uint> right) { throw null; }
/// <summary>
/// Signed Add Wide
/// For each element result[elem] = left[elem] + right[elem]
/// Corresponds to vector forms of SADDW and UADDW
/// </summary>
public static Vector128<short> AddAndWidenLow(Vector128<short> left, Vector64<sbyte> right) { throw null; }
public static Vector128<ushort> AddAndWidenLow(Vector128<ushort> left, Vector64<byte> right) { throw null; }
public static Vector128<int> AddAndWidenLow(Vector128<int> left, Vector64<short> right) { throw null; }
public static Vector128<uint> AddAndWidenLow(Vector128<uint> left, Vector64<ushort> right) { throw null; }
public static Vector128<long> AddAndWidenLow(Vector128<long> left, Vector64<int> right) { throw null; }
public static Vector128<ulong> AddAndWidenLow(Vector128<ulong> left, Vector64<uint> right) { throw null; }
/// <summary>
/// Signed Add Wide
/// For each element result[elem] = left[elem] + right[elem]
/// Corresponds to vector forms of SADDW2 and UADDW2
/// </summary>
public static Vector128<short> AddAndWidenHigh(Vector128<short> left, Vector128<sbyte> right) { throw null; }
public static Vector128<ushort> AddAndWidenHigh(Vector128<ushort> left, Vector128<byte> right) { throw null; }
public static Vector128<int> AddAndWidenHigh(Vector128<int> left, Vector128<short> right) { throw null; }
public static Vector128<uint> AddAndWidenHigh(Vector128<uint> left, Vector128<ushort> right) { throw null; }
public static Vector128<long> AddAndWidenHigh(Vector128<long> left, Vector128<int> right) { throw null; }
public static Vector128<ulong> AddAndWidenHigh(Vector128<ulong> left, Vector128<uint> right) { throw null; }
/// <summary>
/// Signed Subtract Long
/// For each element result[elem] = left[elem] - right[elem]
/// Corresponds to vector forms of SSUBL and USUBL
/// </summary>
public static Vector128<short> SubtractAndWidenLow(Vector64<sbyte> left, Vector64<sbyte> right) { throw null; }
public static Vector128<ushort> SubtractAndWidenLow(Vector64<byte> left, Vector64<byte> right) { throw null; }
public static Vector128<int> SubtractAndWidenLow(Vector64<short> left, Vector64<short> right) { throw null; }
public static Vector128<uint> SubtractAndWidenLow(Vector64<ushort> left, Vector64<ushort> right) { throw null; }
public static Vector128<long> SubtractAndWidenLow(Vector64<int> left, Vector64<int> right) { throw null; }
public static Vector128<ulong> SubtractAndWidenLow(Vector64<uint> left, Vector64<uint> right) { throw null; }
/// <summary>
/// Signed Subtract Long
/// For each element result[elem] = left[elem] - right[elem]
/// Corresponds to vector forms of SSUBL2 and USUBL2
/// </summary>
public static Vector128<short> SubtractAndWidenHigh(Vector128<sbyte> left, Vector128<sbyte> right) { throw null; }
public static Vector128<ushort> SubtractAndWidenHigh(Vector128<byte> left, Vector128<byte> right) { throw null; }
public static Vector128<int> SubtractAndWidenHigh(Vector128<short> left, Vector128<short> right) { throw null; }
public static Vector128<uint> SubtractAndWidenHigh(Vector128<ushort> left, Vector128<ushort> right) { throw null; }
public static Vector128<long> SubtractAndWidenHigh(Vector128<int> left, Vector128<int> right) { throw null; }
public static Vector128<ulong> SubtractAndWidenHigh(Vector128<uint> left, Vector128<uint> right) { throw null; }
/// <summary>
/// Signed Subtract Wide
/// For each element result[elem] = left[elem] - right[elem]
/// Corresponds to vector forms of SSUBW and USUBW
/// </summary>
public static Vector128<short> SubtractAndWidenLow(Vector128<short> left, Vector64<sbyte> right) { throw null; }
public static Vector128<ushort> SubtractAndWidenLow(Vector128<ushort> left, Vector64<byte> right) { throw null; }
public static Vector128<int> SubtractAndWidenLow(Vector128<int> left, Vector64<short> right) { throw null; }
public static Vector128<uint> SubtractAndWidenLow(Vector128<uint> left, Vector64<ushort> right) { throw null; }
public static Vector128<long> SubtractAndWidenLow(Vector128<long> left, Vector64<int> right) { throw null; }
public static Vector128<ulong> SubtractAndWidenLow(Vector128<ulong> left, Vector64<uint> right) { throw null; }
/// <summary>
/// Signed Subtract Wide
/// For each element result[elem] = left[elem] - right[elem]
/// Corresponds to vector forms of SSUBW2 and USUBW2
/// </summary>
public static Vector128<short> SubtractAndWidenHigh(Vector128<short> left, Vector128<sbyte> right) { throw null; }
public static Vector128<ushort> SubtractAndWidenHigh(Vector128<ushort> left, Vector128<byte> right) { throw null; }
public static Vector128<int> SubtractAndWidenHigh(Vector128<int> left, Vector128<short> right) { throw null; }
public static Vector128<uint> SubtractAndWidenHigh(Vector128<uint> left, Vector128<ushort> right) { throw null; }
public static Vector128<long> SubtractAndWidenHigh(Vector128<long> left, Vector128<int> right) { throw null; }
public static Vector128<ulong> SubtractAndWidenHigh(Vector128<ulong> left, Vector128<uint> right) { throw null; }
/// <summary>
/// Signed Multiply Long
/// For each element result[elem] = left[elem] * right[elem]
/// Corresponds to vector forms of SMULL and UMULL
/// </summary>
public static Vector128<short> MultiplyAndWidenLow(Vector64<sbyte> left, Vector64<sbyte> right) { throw null; }
public static Vector128<ushort> MultiplyAndWidenLow(Vector64<byte> left, Vector64<byte> right) { throw null; }
public static Vector128<int> MultiplyAndWidenLow(Vector64<short> left, Vector64<short> right) { throw null; }
public static Vector128<uint> MultiplyAndWidenLow(Vector64<ushort> left, Vector64<ushort> right) { throw null; }
public static Vector128<long> MultiplyAndWidenLow(Vector64<int> left, Vector64<int> right) { throw null; }
public static Vector128<ulong> MultiplyAndWidenLow(Vector64<uint> left, Vector64<uint> right) { throw null; }
/// <summary>
/// Signed Multiply Long
/// For each element result[elem] = left[elem] * right[elem]
/// Corresponds to vector forms of SMULL2 and UMULL2
/// </summary>
public static Vector128<short> MultiplyAndWidenHigh(Vector128<sbyte> left, Vector128<sbyte> right) { throw null; }
public static Vector128<ushort> MultiplyAndWidenHigh(Vector128<byte> left, Vector128<byte> right) { throw null; }
public static Vector128<int> MultiplyAndWidenHigh(Vector128<short> left, Vector128<short> right) { throw null; }
public static Vector128<uint> MultiplyAndWidenHigh(Vector128<ushort> left, Vector128<ushort> right) { throw null; }
public static Vector128<long> MultiplyAndWidenHigh(Vector128<int> left, Vector128<int> right) { throw null; }
public static Vector128<ulong> MultiplyAndWidenHigh(Vector128<uint> left, Vector128<uint> right) { throw null; }
/// <summary>
/// Signed Multiply and Add Long
/// For each element result[elem] = addend[elem] + left[elem] * right[elem]
/// Corresponds to vector forms of SMLAL and UMLAL
/// </summary>
public static Vector128<short> MultiplyAddAndWidenLow(Vector128<short> addend, Vector64<sbyte> left, Vector64<sbyte> right) { throw null; }
public static Vector128<ushort> MultiplyAddAndWidenLow(Vector128<ushort> addend, Vector64<byte> left, Vector64<byte> right) { throw null; }
public static Vector128<int> MultiplyAddAndWidenLow(Vector128<int> addend, Vector64<short> left, Vector64<short> right) { throw null; }
public static Vector128<uint> MultiplyAddAndWidenLow(Vector128<uint> addend, Vector64<ushort> left, Vector64<ushort> right) { throw null; }
public static Vector128<long> MultiplyAddAndWidenLow(Vector128<long> addend, Vector64<int> left, Vector64<int> right) { throw null; }
public static Vector128<ulong> MultiplyAddAndWidenLow(Vector128<ulong> addend, Vector64<uint> left, Vector64<uint> right) { throw null; }
/// <summary>
/// Signed Multiply and Add Long
/// For each element result[elem] = addend[elem] + left[elem] * right[elem]
/// Corresponds to vector forms of SMLAL2 and UMLAL2
/// </summary>
public static Vector128<short> MultiplyAddAndWidenHigh(Vector128<short> addend, Vector128<sbyte> left, Vector128<sbyte> right) { throw null; }
public static Vector128<ushort> MultiplyAddAndWidenHigh(Vector128<ushort> addend, Vector128<byte> left, Vector128<byte> right) { throw null; }
public static Vector128<int> MultiplyAddAndWidenHigh(Vector128<int> addend, Vector128<short> left, Vector128<short> right) { throw null; }
public static Vector128<uint> MultiplyAddAndWidenHigh(Vector128<uint> addend, Vector128<ushort> left, Vector128<ushort> right) { throw null; }
public static Vector128<long> MultiplyAddAndWidenHigh(Vector128<long> addend, Vector128<int> left, Vector128<int> right) { throw null; }
public static Vector128<ulong> MultiplyAddAndWidenHigh(Vector128<ulong> addend, Vector128<uint> left, Vector128<uint> right) { throw null; }
/// <summary>
/// Signed Multiply and Add Long
/// For each element result[elem] = minuend[elem] -left[elem] * right[elem]
/// Corresponds to vector forms of SMLSL and UMLSL
/// </summary>
public static Vector128<short> MultiplySubtractAndWidenLow(Vector128<short> minuend, Vector64<sbyte> left, Vector64<sbyte> right) { throw null; }
public static Vector128<ushort> MultiplySubtractAndWidenLow(Vector128<ushort> minuend, Vector64<byte> left, Vector64<byte> right) { throw null; }
public static Vector128<int> MultiplySubtractAndWidenLow(Vector128<int> minuend, Vector64<short> left, Vector64<short> right) { throw null; }
public static Vector128<uint> MultiplySubtractAndWidenLow(Vector128<uint> minuend, Vector64<ushort> left, Vector64<ushort> right) { throw null; }
public static Vector128<long> MultiplySubtractAndWidenLow(Vector128<long> minuend, Vector64<int> left, Vector64<int> right) { throw null; }
public static Vector128<ulong> MultiplySubtractAndWidenLow(Vector128<ulong> minuend, Vector64<uint> left, Vector64<uint> right) { throw null; }
/// <summary>
/// Signed Multiply and Subtract Long
/// For each element result[elem] = minuend[elem] - left[elem] * right[elem]
/// Corresponds to vector forms of SMLSL2 and UMLSL2
/// </summary>
public static Vector128<short> MultiplySubtractAndWidenHigh(Vector128<short> minuend, Vector128<sbyte> left, Vector128<sbyte> right) { throw null; }
public static Vector128<ushort> MultiplySubtractAndWidenHigh(Vector128<ushort> minuend, Vector128<byte> left, Vector128<byte> right) { throw null; }
public static Vector128<int> MultiplySubtractAndWidenHigh(Vector128<int> minuend, Vector128<short> left, Vector128<short> right) { throw null; }
public static Vector128<uint> MultiplySubtractAndWidenHigh(Vector128<uint> minuend, Vector128<ushort> left, Vector128<ushort> right) { throw null; }
public static Vector128<long> MultiplySubtractAndWidenHigh(Vector128<long> minuend, Vector128<int> left, Vector128<int> right) { throw null; }
public static Vector128<ulong> MultiplySubtractAndWidenHigh(Vector128<ulong> minuend, Vector128<uint> left, Vector128<uint> right) { throw null; }
}
}
}Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedarch-arm64area-System.Runtime.Intrinsics
Activity
tannergooding commentedon Feb 18, 2020
CC. @CarolEidt, @echesakovMSFT, @TamarChristinaArm
This is a proposal for some of the remaining intrinsics that aren't yet in an existing proposal. I expect 2-3 more issues in the coming days to get put up before all have been covered.
[-]ARM additional addition and subtraction intrinsics[/-][+]ARM additional arithmetic intrinsics[/+]tannergooding commentedon Mar 11, 2020
Added in some more arithmetic intrinsics.
terrajobst commentedon Mar 17, 2020
Video
AbsoluteDifferenceAddin API Proposal: More SIMD HW Intrinsics #24794 should takeVector128<T>rather thanVector64<T>Halvingmethods are fused, so we should prefix them withFusedtannergooding commentedon Apr 16, 2020
The following intrinsics should be under
AdvSimdnotAdvSimd.Arm64based on https://developer.arm.com/architectures/instruction-sets/simd-isas/neon/intrinsicsThese are all "lower" variants. The "upper" variants are Arm64 only.
CC. @echesakovMSFT, @TamarChristinaArm
TamarChristinaArm commentedon Apr 16, 2020
@tannergooding same here. I believe some, if not all of these are implementable on AArch32 as well. I will go through them.
echesakov commentedon Apr 16, 2020
I believe
AbsoluteDifferenceWideningUpperAndAdd (SABAL2, UABAL2) can also be implemented on Arm32 as
where Dn, Dm corresponds to upper parts of
Vector128<T>left and right arguments.I believe the reason why Arm64 introduces SABAL2, UABAL2 is that you can't access upper 64-bit parts of 128-bit vector registers using 64-bit register names - while on Arm32 D_{2n}, D_{2n+1} corresponds to lower and upper parts of Q_{n}.
echesakov commentedon Apr 16, 2020
@TamarChristinaArm Are you working on these or have started implementing them? If not, I can take these as my next workitem since I am little bit reluctant to start working on the remaining intrinsics in #24794 (*BySelectedScalar) before we agreed on their names
echesakov commentedon Apr 16, 2020
It looks that
AddLowerReturningUppershould operate onVector128<T>?and
AddLowerRoundedReturningUpperas wellechesakov commentedon Apr 16, 2020
Based on the description of
ADDHN{2}andRADDHN{2}shouldn't these be
AddUpperReturningLowerandAddUpperRoundedReturningUpperand even these names are confusing since they imply that the addition operation happens only on upper part of the source registers - which is not true - since we are adding whole registers together and extract upper parts only after that.tannergooding commentedon Apr 16, 2020
Yeah, I think those names were likely messed up during the API review as the general terms are confusing.
They
AddReturningUpperand write the result to the Lower/Upper halves of the result register and I'm not sure of a good name for them that isn't equally confusingechesakov commentedon Apr 17, 2020
AddHighNarrowingToUpper AddHighNarrowingToLower?
tannergooding commentedon Apr 17, 2020
That doesn't fit with the general naming convention we've used elsewhere
TamarChristinaArm commentedon Apr 17, 2020
No I'm not, I'm currently doing the single register TBL/TBX and the SLI/SRI ones.
echesakov commentedon Apr 17, 2020
@tannergooding Can you please add these to the next API meeting agenda? These should be clarification what names to use here.
I don't want to block on this so I am going to start implementing the intrinsics and as the temporary names use AddReturningHighNarrowUpper and AddReturningHighNarrowLower. When the names are finalized - these can be updated with simple search and replace.
echesakov commentedon Apr 18, 2020
I went through all of the instrinsic - it looks that only
AddSaturateScalarandSubtractSaturateScalarfor (8, 16 and 32 byte arguments) are A64-only. Everything else can be implemented on both platforms.Below I attached the corrected API and added the corresponding С++ intrinsic name and the instructions with operands on A32 and A64.
@TamarChristinaArm Can you please take a look and verify my assumptions how *Upper intrinsics should be implemented on A32?
TamarChristinaArm commentedon Apr 20, 2020
@echesakovMSFT Yeah those look correct to me. I'll make sure they're also corrected in the next ACLE release.