GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op2Reg, op1Reg, opt);
break;
+ case NI_AdvSimd_ExtractAndNarrowHigh:
+ if (targetReg != op1Reg)
+ {
+ GetEmitter()->emitIns_R_R(INS_mov, emitSize, targetReg, op1Reg);
+ }
+ GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op2Reg, opt);
+ break;
+
case NI_AdvSimd_FusedMultiplyAddScalar:
case NI_AdvSimd_FusedMultiplyAddNegatedScalar:
case NI_AdvSimd_FusedMultiplySubtractNegatedScalar:
HARDWARE_INTRINSIC(AdvSimd, CompareLessThanOrEqual, -1, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize|HW_Flag_SpecialCodeGen)
HARDWARE_INTRINSIC(AdvSimd, CompareTest, -1, -1, 2, {INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_invalid, INS_invalid, INS_cmtst, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_Commutative|HW_Flag_UnfixedSIMDSize)
HARDWARE_INTRINSIC(AdvSimd, DivideScalar, -1, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fdiv, INS_fdiv}, HW_Category_SIMDScalar, HW_Flag_NoContainment)
+HARDWARE_INTRINSIC(AdvSimd, ExtractAndNarrowLow, -1, 8, 1, {INS_xtn, INS_xtn, INS_xtn, INS_xtn, INS_xtn, INS_xtn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment)
+HARDWARE_INTRINSIC(AdvSimd, ExtractAndNarrowHigh, -1, 16, 2, {INS_xtn2, INS_xtn2, INS_xtn2, INS_xtn2, INS_xtn2, INS_xtn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_SpecialCodeGen)
HARDWARE_INTRINSIC(AdvSimd, FusedMultiplyAdd, -1, -1, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmla, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
HARDWARE_INTRINSIC(AdvSimd, FusedMultiplyAddScalar, -1, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmadd, INS_fmadd}, HW_Category_SIMDScalar, HW_Flag_NoContainment|HW_Flag_SpecialCodeGen)
HARDWARE_INTRINSIC(AdvSimd, FusedMultiplyAddNegatedScalar, -1, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fnmadd, INS_fnmadd}, HW_Category_SIMDScalar, HW_Flag_NoContainment|HW_Flag_SpecialCodeGen)
srcCount += BuildDelayFreeUses(op3);
break;
+ case NI_AdvSimd_ExtractAndNarrowHigh:
+
+ assert((numArgs == 2) && (op2 != nullptr));
+
+ buildUses = false;
+
+ tgtPrefUse = BuildUse(op1);
+ srcCount += 1;
+ srcCount += BuildDelayFreeUses(op2);
+ break;
+
default:
assert((intrinsicId > NI_HW_INTRINSIC_START) && (intrinsicId < NI_HW_INTRINSIC_END));
break;
<Compile Include="CompareTest.Vector128.UInt32.cs" />
<Compile Include="DivideScalar.Vector64.Double.cs" />
<Compile Include="DivideScalar.Vector64.Single.cs" />
+ <Compile Include="ExtractAndNarrowLow.Vector128.Int16.cs" />
+ <Compile Include="ExtractAndNarrowLow.Vector128.Int32.cs" />
+ <Compile Include="ExtractAndNarrowLow.Vector128.Int64.cs" />
+ <Compile Include="ExtractAndNarrowLow.Vector128.UInt16.cs" />
+ <Compile Include="ExtractAndNarrowLow.Vector128.UInt32.cs" />
+ <Compile Include="ExtractAndNarrowLow.Vector128.UInt64.cs" />
+ <Compile Include="ExtractAndNarrowHigh.Vector128.Int16.cs" />
+ <Compile Include="ExtractAndNarrowHigh.Vector128.Int32.cs" />
+ <Compile Include="ExtractAndNarrowHigh.Vector128.Int64.cs" />
+ <Compile Include="ExtractAndNarrowHigh.Vector128.UInt16.cs" />
+ <Compile Include="ExtractAndNarrowHigh.Vector128.UInt32.cs" />
+ <Compile Include="ExtractAndNarrowHigh.Vector128.UInt64.cs" />
<Compile Include="FusedMultiplyAdd.Vector64.Single.cs" />
<Compile Include="FusedMultiplyAdd.Vector128.Single.cs" />
<Compile Include="FusedMultiplyAddScalar.Vector64.Double.cs" />
<Compile Include="CompareTest.Vector128.UInt32.cs" />
<Compile Include="DivideScalar.Vector64.Double.cs" />
<Compile Include="DivideScalar.Vector64.Single.cs" />
+ <Compile Include="ExtractAndNarrowLow.Vector128.Int16.cs" />
+ <Compile Include="ExtractAndNarrowLow.Vector128.Int32.cs" />
+ <Compile Include="ExtractAndNarrowLow.Vector128.Int64.cs" />
+ <Compile Include="ExtractAndNarrowLow.Vector128.UInt16.cs" />
+ <Compile Include="ExtractAndNarrowLow.Vector128.UInt32.cs" />
+ <Compile Include="ExtractAndNarrowLow.Vector128.UInt64.cs" />
+ <Compile Include="ExtractAndNarrowHigh.Vector128.Int16.cs" />
+ <Compile Include="ExtractAndNarrowHigh.Vector128.Int32.cs" />
+ <Compile Include="ExtractAndNarrowHigh.Vector128.Int64.cs" />
+ <Compile Include="ExtractAndNarrowHigh.Vector128.UInt16.cs" />
+ <Compile Include="ExtractAndNarrowHigh.Vector128.UInt32.cs" />
+ <Compile Include="ExtractAndNarrowHigh.Vector128.UInt64.cs" />
<Compile Include="FusedMultiplyAdd.Vector64.Single.cs" />
<Compile Include="FusedMultiplyAdd.Vector128.Single.cs" />
<Compile Include="FusedMultiplyAddScalar.Vector64.Double.cs" />
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.Arm;
+
+namespace JIT.HardwareIntrinsics.Arm
+{
+ public static partial class Program
+ {
+ private static void ExtractAndNarrowHigh_Vector128_Int16()
+ {
+ var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int16();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+ }
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int16
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(SByte[] inArray1, Int16[] inArray2, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<SByte>();
+ if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<SByte, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Int16, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector64<SByte> _fld1;
+ public Vector128<Int16> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref testStruct._fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref testStruct._fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int16 testClass)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int16 testClass)
+ {
+ fixed (Vector64<SByte>* pFld1 = &_fld1)
+ fixed (Vector128<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((Int16*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 16;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+ private static Int16[] _data2 = new Int16[Op2ElementCount];
+
+ private static Vector64<SByte> _clsVar1;
+ private static Vector128<Int16> _clsVar2;
+
+ private Vector64<SByte> _fld1;
+ private Vector128<Int16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int16()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _clsVar1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ }
+
+ public SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int16()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64<SByte>), typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64<SByte>), typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<SByte>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((SByte*)(pClsVar1)),
+ AdvSimd.LoadVector128((Int16*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.ExtractAndNarrowHigh(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.ExtractAndNarrowHigh(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int16();
+ var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int16();
+
+ fixed (Vector64<SByte>* pFld1 = &test._fld1)
+ fixed (Vector128<Int16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((Int16*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<SByte>* pFld1 = &_fld1)
+ fixed (Vector128<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((Int16*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((SByte*)(&test._fld1)),
+ AdvSimd.LoadVector128((Int16*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector64<SByte> op1, Vector128<Int16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(SByte[] left, Int16[] right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (Helpers.ExtractAndNarrowHigh(0, left, right, result))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (Helpers.ExtractAndNarrowHigh(i, left, right, result))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowHigh)}<SByte>(Vector64<SByte>, Vector128<Int16>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.Arm;
+
+namespace JIT.HardwareIntrinsics.Arm
+{
+ public static partial class Program
+ {
+ private static void ExtractAndNarrowHigh_Vector128_Int32()
+ {
+ var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int32();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+ }
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int32
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Int16[] inArray1, Int32[] inArray2, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Int16>();
+ if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Int16, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Int32, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector64<Int16> _fld1;
+ public Vector128<Int32> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref testStruct._fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref testStruct._fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int32 testClass)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int32 testClass)
+ {
+ fixed (Vector64<Int16>* pFld1 = &_fld1)
+ fixed (Vector128<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector128((Int32*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 16;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+ private static Int32[] _data2 = new Int32[Op2ElementCount];
+
+ private static Vector64<Int16> _clsVar1;
+ private static Vector128<Int32> _clsVar2;
+
+ private Vector64<Int16> _fld1;
+ private Vector128<Int32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int32()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref _clsVar1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _clsVar2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ }
+
+ public SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int32()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref _fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64<Int16>), typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64<Int16>), typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Int16>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((Int16*)(pClsVar1)),
+ AdvSimd.LoadVector128((Int32*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.ExtractAndNarrowHigh(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.ExtractAndNarrowHigh(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int32();
+ var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int32();
+
+ fixed (Vector64<Int16>* pFld1 = &test._fld1)
+ fixed (Vector128<Int32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector128((Int32*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Int16>* pFld1 = &_fld1)
+ fixed (Vector128<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector128((Int32*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((Int16*)(&test._fld1)),
+ AdvSimd.LoadVector128((Int32*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector64<Int16> op1, Vector128<Int32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int16[] left, Int32[] right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (Helpers.ExtractAndNarrowHigh(0, left, right, result))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (Helpers.ExtractAndNarrowHigh(i, left, right, result))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowHigh)}<Int16>(Vector64<Int16>, Vector128<Int32>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.Arm;
+
+namespace JIT.HardwareIntrinsics.Arm
+{
+ public static partial class Program
+ {
+ private static void ExtractAndNarrowHigh_Vector128_Int64()
+ {
+ var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int64();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+ }
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int64
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Int32[] inArray1, Int64[] inArray2, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Int32>();
+ if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Int32, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Int64, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector64<Int32> _fld1;
+ public Vector128<Int64> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref testStruct._fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref testStruct._fld2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int64 testClass)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int64 testClass)
+ {
+ fixed (Vector64<Int32>* pFld1 = &_fld1)
+ fixed (Vector128<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector128((Int64*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 16;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int64>>() / sizeof(Int64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+ private static Int64[] _data2 = new Int64[Op2ElementCount];
+
+ private static Vector64<Int32> _clsVar1;
+ private static Vector128<Int64> _clsVar2;
+
+ private Vector64<Int32> _fld1;
+ private Vector128<Int64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int64()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref _clsVar1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _clsVar2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+ }
+
+ public SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int64()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref _fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _fld2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64<Int32>), typeof(Vector128<Int64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64<Int32>), typeof(Vector128<Int64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Int32>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((Int32*)(pClsVar1)),
+ AdvSimd.LoadVector128((Int64*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.ExtractAndNarrowHigh(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.ExtractAndNarrowHigh(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int64();
+ var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int64();
+
+ fixed (Vector64<Int32>* pFld1 = &test._fld1)
+ fixed (Vector128<Int64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector128((Int64*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Int32>* pFld1 = &_fld1)
+ fixed (Vector128<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector128((Int64*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((Int32*)(&test._fld1)),
+ AdvSimd.LoadVector128((Int64*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector64<Int32> op1, Vector128<Int64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int32[] left, Int64[] right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (Helpers.ExtractAndNarrowHigh(0, left, right, result))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (Helpers.ExtractAndNarrowHigh(i, left, right, result))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowHigh)}<Int32>(Vector64<Int32>, Vector128<Int64>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.Arm;
+
+namespace JIT.HardwareIntrinsics.Arm
+{
+ public static partial class Program
+ {
+ private static void ExtractAndNarrowHigh_Vector128_UInt16()
+ {
+ var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt16();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+ }
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt16
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Byte[] inArray1, UInt16[] inArray2, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Byte>();
+ if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Byte, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<UInt16, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector64<Byte> _fld1;
+ public Vector128<UInt16> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref testStruct._fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt16 testClass)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt16 testClass)
+ {
+ fixed (Vector64<Byte>* pFld1 = &_fld1)
+ fixed (Vector128<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((UInt16*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 16;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+ private static UInt16[] _data2 = new UInt16[Op2ElementCount];
+
+ private static Vector64<Byte> _clsVar1;
+ private static Vector128<UInt16> _clsVar2;
+
+ private Vector64<Byte> _fld1;
+ private Vector128<UInt16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt16()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _clsVar1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _clsVar2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ }
+
+ public SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt16()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64<Byte>), typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64<Byte>), typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Byte>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((Byte*)(pClsVar1)),
+ AdvSimd.LoadVector128((UInt16*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.ExtractAndNarrowHigh(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.ExtractAndNarrowHigh(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt16();
+ var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt16();
+
+ fixed (Vector64<Byte>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((UInt16*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Byte>* pFld1 = &_fld1)
+ fixed (Vector128<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((UInt16*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((Byte*)(&test._fld1)),
+ AdvSimd.LoadVector128((UInt16*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector64<Byte> op1, Vector128<UInt16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Byte[] left, UInt16[] right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (Helpers.ExtractAndNarrowHigh(0, left, right, result))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (Helpers.ExtractAndNarrowHigh(i, left, right, result))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowHigh)}<Byte>(Vector64<Byte>, Vector128<UInt16>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.Arm;
+
+namespace JIT.HardwareIntrinsics.Arm
+{
+ public static partial class Program
+ {
+ private static void ExtractAndNarrowHigh_Vector128_UInt32()
+ {
+ var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt32();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+ }
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt32
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(UInt16[] inArray1, UInt32[] inArray2, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<UInt16>();
+ if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<UInt16, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<UInt32, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector64<UInt16> _fld1;
+ public Vector128<UInt32> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt32 testClass)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt32 testClass)
+ {
+ fixed (Vector64<UInt16>* pFld1 = &_fld1)
+ fixed (Vector128<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector128((UInt32*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 16;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+ private static UInt32[] _data2 = new UInt32[Op2ElementCount];
+
+ private static Vector64<UInt16> _clsVar1;
+ private static Vector128<UInt32> _clsVar2;
+
+ private Vector64<UInt16> _fld1;
+ private Vector128<UInt32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt32()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref _clsVar1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _clsVar2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ }
+
+ public SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt32()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref _fld1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64<UInt16>), typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64<UInt16>), typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<UInt16>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((UInt16*)(pClsVar1)),
+ AdvSimd.LoadVector128((UInt32*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.ExtractAndNarrowHigh(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.ExtractAndNarrowHigh(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt32();
+ var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt32();
+
+ fixed (Vector64<UInt16>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector128((UInt32*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<UInt16>* pFld1 = &_fld1)
+ fixed (Vector128<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector128((UInt32*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((UInt16*)(&test._fld1)),
+ AdvSimd.LoadVector128((UInt32*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector64<UInt16> op1, Vector128<UInt32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt16[] left, UInt32[] right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (Helpers.ExtractAndNarrowHigh(0, left, right, result))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (Helpers.ExtractAndNarrowHigh(i, left, right, result))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowHigh)}<UInt16>(Vector64<UInt16>, Vector128<UInt32>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.Arm;
+
+namespace JIT.HardwareIntrinsics.Arm
+{
+ public static partial class Program
+ {
+ private static void ExtractAndNarrowHigh_Vector128_UInt64()
+ {
+ var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt64();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+ }
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt64
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] inArray2;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(UInt32[] inArray1, UInt64[] inArray2, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<UInt32>();
+ if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.inArray2 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<UInt32, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<UInt64, byte>(ref inArray2[0]), (uint)sizeOfinArray2);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector64<UInt32> _fld1;
+ public Vector128<UInt64> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt64 testClass)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt64 testClass)
+ {
+ fixed (Vector64<UInt32>* pFld1 = &_fld1)
+ fixed (Vector128<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector128((UInt64*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 16;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt64>>() / sizeof(UInt64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+ private static UInt64[] _data2 = new UInt64[Op2ElementCount];
+
+ private static Vector64<UInt32> _clsVar1;
+ private static Vector128<UInt64> _clsVar2;
+
+ private Vector64<UInt32> _fld1;
+ private Vector128<UInt64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt64()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref _clsVar1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _clsVar2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+ }
+
+ public SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt64()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref _fld1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _fld2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64<UInt32>), typeof(Vector128<UInt64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64<UInt32>), typeof(Vector128<UInt64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<UInt32>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((UInt32*)(pClsVar1)),
+ AdvSimd.LoadVector128((UInt64*)(pClsVar2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.ExtractAndNarrowHigh(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.ExtractAndNarrowHigh(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt64();
+ var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt64();
+
+ fixed (Vector64<UInt32>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector128((UInt64*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<UInt32>* pFld1 = &_fld1)
+ fixed (Vector128<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector128((UInt64*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowHigh(
+ AdvSimd.LoadVector64((UInt32*)(&test._fld1)),
+ AdvSimd.LoadVector128((UInt64*)(&test._fld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector64<UInt32> op1, Vector128<UInt64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt32[] left, UInt64[] right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (Helpers.ExtractAndNarrowHigh(0, left, right, result))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (Helpers.ExtractAndNarrowHigh(i, left, right, result))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowHigh)}<UInt32>(Vector64<UInt32>, Vector128<UInt64>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})");
+ TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.Arm;
+
+namespace JIT.HardwareIntrinsics.Arm
+{
+ public static partial class Program
+ {
+ private static void ExtractAndNarrowLow_Vector128_Int16()
+ {
+ var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int16();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+ }
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int16
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Int16[] inArray1, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<SByte>();
+ if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Int16, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector128<Int16> _fld1;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref testStruct._fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int16 testClass)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int16 testClass)
+ {
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((Int16*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 16;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+
+ private static Vector128<Int16> _clsVar1;
+
+ private Vector128<Int16> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int16()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ }
+
+ public SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int16()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); }
+ _dataTable = new DataTable(_data1, new SByte[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.ExtractAndNarrowLow(
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<SByte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<SByte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.ExtractAndNarrowLow(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int16>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((Int16*)(pClsVar1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.ExtractAndNarrowLow(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.ExtractAndNarrowLow(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int16();
+ var result = AdvSimd.ExtractAndNarrowLow(test._fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int16();
+
+ fixed (Vector128<Int16>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((Int16*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.ExtractAndNarrowLow(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((Int16*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowLow(test._fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((Int16*)(&test._fld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector128<Int16> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Int16[] firstOp, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (((SByte)firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowLow)}<SByte>(Vector128<Int16>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.Arm;
+
+namespace JIT.HardwareIntrinsics.Arm
+{
+ public static partial class Program
+ {
+ private static void ExtractAndNarrowLow_Vector128_Int32()
+ {
+ var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int32();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+ }
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int32
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Int32[] inArray1, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Int16>();
+ if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Int32, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector128<Int32> _fld1;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref testStruct._fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int32 testClass)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int32 testClass)
+ {
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((Int32*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 16;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+
+ private static Vector128<Int32> _clsVar1;
+
+ private Vector128<Int32> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int32()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _clsVar1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ }
+
+ public SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int32()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); }
+ _dataTable = new DataTable(_data1, new Int16[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.ExtractAndNarrowLow(
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.ExtractAndNarrowLow(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int32>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((Int32*)(pClsVar1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.ExtractAndNarrowLow(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.ExtractAndNarrowLow(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int32();
+ var result = AdvSimd.ExtractAndNarrowLow(test._fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int32();
+
+ fixed (Vector128<Int32>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((Int32*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.ExtractAndNarrowLow(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((Int32*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowLow(test._fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((Int32*)(&test._fld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector128<Int32> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Int32[] firstOp, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (((Int16)firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowLow)}<Int16>(Vector128<Int32>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.Arm;
+
+namespace JIT.HardwareIntrinsics.Arm
+{
+ public static partial class Program
+ {
+ private static void ExtractAndNarrowLow_Vector128_Int64()
+ {
+ var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int64();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+ }
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int64
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Int64[] inArray1, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Int32>();
+ if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<Int64, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector128<Int64> _fld1;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref testStruct._fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int64 testClass)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int64 testClass)
+ {
+ fixed (Vector128<Int64>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((Int64*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 16;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Int64>>() / sizeof(Int64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+
+ private static Int64[] _data1 = new Int64[Op1ElementCount];
+
+ private static Vector128<Int64> _clsVar1;
+
+ private Vector128<Int64> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int64()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _clsVar1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+ }
+
+ public SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int64()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ _dataTable = new DataTable(_data1, new Int32[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.ExtractAndNarrowLow(
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArray1Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128<Int64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128<Int64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.ExtractAndNarrowLow(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int64>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((Int64*)(pClsVar1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector128<Int64>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.ExtractAndNarrowLow(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.ExtractAndNarrowLow(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int64();
+ var result = AdvSimd.ExtractAndNarrowLow(test._fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int64();
+
+ fixed (Vector128<Int64>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((Int64*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.ExtractAndNarrowLow(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int64>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((Int64*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowLow(test._fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((Int64*)(&test._fld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector128<Int64> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] firstOp, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (((Int32)firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowLow)}<Int32>(Vector128<Int64>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.Arm;
+
+namespace JIT.HardwareIntrinsics.Arm
+{
+ public static partial class Program
+ {
+ private static void ExtractAndNarrowLow_Vector128_UInt16()
+ {
+ var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt16();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+ }
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt16
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(UInt16[] inArray1, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Byte>();
+ if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<UInt16, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector128<UInt16> _fld1;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt16 testClass)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt16 testClass)
+ {
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((UInt16*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 16;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+
+ private static Vector128<UInt16> _clsVar1;
+
+ private Vector128<UInt16> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt16()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _clsVar1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ }
+
+ public SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt16()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _fld1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); }
+ _dataTable = new DataTable(_data1, new Byte[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.ExtractAndNarrowLow(
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Byte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Byte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.ExtractAndNarrowLow(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt16>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((UInt16*)(pClsVar1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.ExtractAndNarrowLow(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.ExtractAndNarrowLow(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt16();
+ var result = AdvSimd.ExtractAndNarrowLow(test._fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt16();
+
+ fixed (Vector128<UInt16>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((UInt16*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.ExtractAndNarrowLow(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((UInt16*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowLow(test._fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((UInt16*)(&test._fld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector128<UInt16> op1, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(UInt16[] firstOp, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (((Byte)firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowLow)}<Byte>(Vector128<UInt16>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.Arm;
+
+namespace JIT.HardwareIntrinsics.Arm
+{
+ public static partial class Program
+ {
+ private static void ExtractAndNarrowLow_Vector128_UInt32()
+ {
+ var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt32();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+ }
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt32
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(UInt32[] inArray1, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<UInt16>();
+ if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<UInt32, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector128<UInt32> _fld1;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt32 testClass)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt32 testClass)
+ {
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((UInt32*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 16;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+
+ private static Vector128<UInt32> _clsVar1;
+
+ private Vector128<UInt32> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt32()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _clsVar1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ }
+
+ public SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt32()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _fld1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); }
+ _dataTable = new DataTable(_data1, new UInt16[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.ExtractAndNarrowLow(
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.ExtractAndNarrowLow(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt32>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((UInt32*)(pClsVar1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.ExtractAndNarrowLow(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.ExtractAndNarrowLow(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt32();
+ var result = AdvSimd.ExtractAndNarrowLow(test._fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt32();
+
+ fixed (Vector128<UInt32>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((UInt32*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.ExtractAndNarrowLow(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((UInt32*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowLow(test._fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((UInt32*)(&test._fld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector128<UInt32> op1, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(UInt32[] firstOp, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (((UInt16)firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowLow)}<UInt16>(Vector128<UInt32>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************************
+ * This file is auto-generated from a template file by the GenerateTests.csx *
+ * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make *
+ * changes, please update the corresponding template and run according to the *
+ * directions listed in the file. *
+ ******************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.Arm;
+
+namespace JIT.HardwareIntrinsics.Arm
+{
+ public static partial class Program
+ {
+ private static void ExtractAndNarrowLow_Vector128_UInt64()
+ {
+ var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt64();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a static member works, using pinning and Load
+ test.RunClsVarScenario_Load();
+ }
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+ }
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local class works, using pinning and Load
+ test.RunClassLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a class works, using pinning and Load
+ test.RunClassFldScenario_Load();
+ }
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing the field of a local struct works, using pinning and Load
+ test.RunStructLclFldScenario_Load();
+ }
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+
+ if (AdvSimd.IsSupported)
+ {
+ // Validates passing an instance member of a struct works, using pinning and Load
+ test.RunStructFldScenario_Load();
+ }
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt64
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(UInt64[] inArray1, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<UInt32>();
+ if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray)
+ {
+ throw new ArgumentException("Invalid value of alignment");
+ }
+
+ this.inArray1 = new byte[alignment * 2];
+ this.outArray = new byte[alignment * 2];
+
+ this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned);
+
+ this.alignment = (ulong)alignment;
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray1Ptr), ref Unsafe.As<UInt64, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ }
+
+ public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment);
+ public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment);
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ outHandle.Free();
+ }
+
+ private static unsafe void* Align(byte* buffer, ulong expectedAlignment)
+ {
+ return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1));
+ }
+ }
+
+ private struct TestStruct
+ {
+ public Vector128<UInt64> _fld1;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt64 testClass)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt64 testClass)
+ {
+ fixed (Vector128<UInt64>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((UInt64*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 16;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<UInt64>>() / sizeof(UInt64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+
+ private static UInt64[] _data1 = new UInt64[Op1ElementCount];
+
+ private static Vector128<UInt64> _clsVar1;
+
+ private Vector128<UInt64> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt64()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _clsVar1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+ }
+
+ public SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt64()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ _dataTable = new DataTable(_data1, new UInt32[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.ExtractAndNarrowLow(
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray1Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load));
+
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128<UInt64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128<UInt64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.ExtractAndNarrowLow(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt64>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((UInt64*)(pClsVar1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.ExtractAndNarrowLow(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.ExtractAndNarrowLow(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt64();
+ var result = AdvSimd.ExtractAndNarrowLow(test._fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load));
+
+ var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt64();
+
+ fixed (Vector128<UInt64>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((UInt64*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.ExtractAndNarrowLow(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt64>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((UInt64*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowLow(test._fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructLclFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load));
+
+ var test = TestStruct.Create();
+ var result = AdvSimd.ExtractAndNarrowLow(
+ AdvSimd.LoadVector128((UInt64*)(&test._fld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(this);
+ }
+
+ public void RunStructFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario_Load(this);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario));
+
+ bool succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ succeeded = true;
+ }
+
+ if (!succeeded)
+ {
+ Succeeded = false;
+ }
+ }
+
+ private void ValidateResult(Vector128<UInt64> op1, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(UInt64[] firstOp, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (((UInt32)firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowLow)}<UInt32>(Vector128<UInt64>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
["CompareTest.Vector128.UInt32"] = CompareTest_Vector128_UInt32,
["DivideScalar.Vector64.Double"] = DivideScalar_Vector64_Double,
["DivideScalar.Vector64.Single"] = DivideScalar_Vector64_Single,
+ ["ExtractAndNarrowLow.Vector128.Int16"] = ExtractAndNarrowLow_Vector128_Int16,
+ ["ExtractAndNarrowLow.Vector128.Int32"] = ExtractAndNarrowLow_Vector128_Int32,
+ ["ExtractAndNarrowLow.Vector128.Int64"] = ExtractAndNarrowLow_Vector128_Int64,
+ ["ExtractAndNarrowLow.Vector128.UInt16"] = ExtractAndNarrowLow_Vector128_UInt16,
+ ["ExtractAndNarrowLow.Vector128.UInt32"] = ExtractAndNarrowLow_Vector128_UInt32,
+ ["ExtractAndNarrowLow.Vector128.UInt64"] = ExtractAndNarrowLow_Vector128_UInt64,
+ ["ExtractAndNarrowHigh.Vector128.Int16"] = ExtractAndNarrowHigh_Vector128_Int16,
+ ["ExtractAndNarrowHigh.Vector128.Int32"] = ExtractAndNarrowHigh_Vector128_Int32,
+ ["ExtractAndNarrowHigh.Vector128.Int64"] = ExtractAndNarrowHigh_Vector128_Int64,
+ ["ExtractAndNarrowHigh.Vector128.UInt16"] = ExtractAndNarrowHigh_Vector128_UInt16,
+ ["ExtractAndNarrowHigh.Vector128.UInt32"] = ExtractAndNarrowHigh_Vector128_UInt32,
+ ["ExtractAndNarrowHigh.Vector128.UInt64"] = ExtractAndNarrowHigh_Vector128_UInt64,
["FusedMultiplyAdd.Vector64.Single"] = FusedMultiplyAdd_Vector64_Single,
["FusedMultiplyAdd.Vector128.Single"] = FusedMultiplyAdd_Vector128_Single,
["FusedMultiplyAddScalar.Vector64.Double"] = FusedMultiplyAddScalar_Vector64_Double,
("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "CompareTest_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}),
("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "DivideScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DivideScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Divide(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}),
("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "DivideScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DivideScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Divide(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "ExtractAndNarrowLow_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "((SByte)firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "ExtractAndNarrowLow_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "((Int16)firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "ExtractAndNarrowLow_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "((Int32)firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "ExtractAndNarrowLow_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "((Byte)firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "ExtractAndNarrowLow_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "((UInt16)firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "ExtractAndNarrowLow_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "((UInt32)firstOp[i]) != result[i]"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "ExtractAndNarrowHigh_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "Helpers.ExtractAndNarrowHigh(0, left, right, result)", ["ValidateRemainingResults"] = "Helpers.ExtractAndNarrowHigh(i, left, right, result)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "ExtractAndNarrowHigh_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "Helpers.ExtractAndNarrowHigh(0, left, right, result)", ["ValidateRemainingResults"] = "Helpers.ExtractAndNarrowHigh(i, left, right, result)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "ExtractAndNarrowHigh_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.ExtractAndNarrowHigh(0, left, right, result)", ["ValidateRemainingResults"] = "Helpers.ExtractAndNarrowHigh(i, left, right, result)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "ExtractAndNarrowHigh_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "Helpers.ExtractAndNarrowHigh(0, left, right, result)", ["ValidateRemainingResults"] = "Helpers.ExtractAndNarrowHigh(i, left, right, result)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "ExtractAndNarrowHigh_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "Helpers.ExtractAndNarrowHigh(0, left, right, result)", ["ValidateRemainingResults"] = "Helpers.ExtractAndNarrowHigh(i, left, right, result)"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "ExtractAndNarrowHigh_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.ExtractAndNarrowHigh(0, left, right, result)", ["ValidateRemainingResults"] = "Helpers.ExtractAndNarrowHigh(i, left, right, result)"}),
("VecTernOpTest.template", new Dictionary<string, string> { ["TestName"] = "FusedMultiplyAdd_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplyAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplyAdd(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
("VecTernOpTest.template", new Dictionary<string, string> { ["TestName"] = "FusedMultiplyAdd_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplyAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplyAdd(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
("SimpleTernOpTest.template", new Dictionary<string, string> { ["TestName"] = "FusedMultiplyAddScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplyAddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FusedMultiplyAdd(firstOp[0], secondOp[0], thirdOp[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}),
}
public static sbyte PolynomialMultiply(sbyte op1, sbyte op2) => (sbyte)PolynomialMult(op1, op2);
-
private static ulong PolynomialMult(byte op1, byte op2)
{
ulong result = 0;
}
public static byte PolynomialMultiply(byte op1, byte op2) => (byte)PolynomialMult(op1, op2);
-
+ public static bool ExtractAndNarrowHigh(int i, sbyte[] left,
+ short[] right,
+ sbyte[] result)
+ {
+ if (i < left.Length)
+ return left[i] != result[i];
+ else
+ return (sbyte)right[i - left.Length] != result[i];
+ }
+ public static bool ExtractAndNarrowHigh(int i, short[] left,
+ int[] right,
+ short[] result)
+ {
+ if (i < left.Length)
+ return left[i] != result[i];
+ else
+ return (short)right[i - left.Length] != result[i];
+ }
+ public static bool ExtractAndNarrowHigh(int i, int[] left,
+ long[] right,
+ int[] result)
+ {
+ if (i < left.Length)
+ return left[i] != result[i];
+ else
+ return (int)right[i - left.Length] != result[i];
+ }
+ public static bool ExtractAndNarrowHigh(int i, byte[] left,
+ ushort[] right,
+ byte[] result)
+ {
+ if (i < left.Length)
+ return left[i] != result[i];
+ else
+ return (byte)right[i - left.Length] != result[i];
+ }
+ public static bool ExtractAndNarrowHigh(int i, ushort[] left,
+ uint[] right,
+ ushort[] result)
+ {
+ if (i < left.Length)
+ return left[i] != result[i];
+ else
+ return (ushort)right[i - left.Length] != result[i];
+ }
+ public static bool ExtractAndNarrowHigh(int i, uint[] left,
+ ulong[] right,
+ uint[] result)
+ {
+ if (i < left.Length)
+ return left[i] != result[i];
+ else
+ return (uint)right[i - left.Length] != result[i];
+ }
}
}
}
public static <#= typeName #> PolynomialMultiply(<#= typeName #> op1, <#= typeName #> op2) => (<#= typeName #>)PolynomialMult(op1, op2);
+<#
+ }
+ foreach (var type in new[] { (small: "sbyte", wide: "short"),
+ (small: "short", wide: "int"),
+ (small: "int", wide: "long"),
+ (small: "byte", wide: "ushort"),
+ (small: "ushort", wide: "uint"),
+ (small: "uint", wide: "ulong") })
+ {
+#>
+ public static bool ExtractAndNarrowHigh(int i, <#= type.small #>[] left,
+ <#= type.wide #>[] right,
+ <#= type.small #>[] result)
+ {
+ if (i < left.Length)
+ return left[i] != result[i];
+ else
+ return (<#= type.small #>)right[i - left.Length] != result[i];
+ }
<#
}
#>
public static Vector64<float> DivideScalar(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
/// <summary>
+ /// int8x8_t vmovn_s16 (int16x8_t a)
+ /// A32: VMOVN.I16 Dd, Qm
+ /// A64: XTN Vd.8B, Vn.8H
+ /// </summary>
+ public static Vector64<sbyte> ExtractAndNarrowLow (Vector128<short> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int16x4_t vmovn_s32 (int32x4_t a)
+ /// A32: VMOVN.I32 Dd, Qm
+ /// A64: XTN Vd.4H, Vn.4S
+ /// </summary>
+ public static Vector64<short> ExtractAndNarrowLow (Vector128<int> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int32x2_t vmovn_s64 (int64x2_t a)
+ /// A32: VMOVN.I64 Dd, Qm
+ /// A64: XTN Vd.2S, Vn.2D
+ /// </summary>
+ public static Vector64<int> ExtractAndNarrowLow (Vector128<long> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint8x8_t vmovn_u16 (uint16x8_t a)
+ /// A32: VMOVN.I16 Dd, Qm
+ /// A64: XTN Vd.8B, Vn.8H
+ /// </summary>
+ public static Vector64<byte> ExtractAndNarrowLow (Vector128<ushort> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint16x4_t vmovn_u32 (uint32x4_t a)
+ /// A32: VMOVN.I32 Dd, Qm
+ /// A64: XTN Vd.4H, Vn.4S
+ /// </summary>
+ public static Vector64<ushort> ExtractAndNarrowLow (Vector128<uint> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint32x2_t vmovn_u64 (uint64x2_t a)
+ /// A32: VMOVN.I64 Dd, Qm
+ /// A64: XTN Vd.2S, Vn.2D
+ /// </summary>
+ public static Vector64<uint> ExtractAndNarrowLow (Vector128<ulong> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int8x16_t vmovn_high_s16 (int8x8_t r, int16x8_t a)
+ /// A32: VMOVN.I16 Dd+1, Qm
+ /// A64: XTN2 Vd.16B, Vn.8H
+ /// </summary>
+ public static Vector128<sbyte> ExtractAndNarrowHigh (Vector64<sbyte> lower, Vector128<short> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int16x8_t vmovn_high_s32 (int16x4_t r, int32x4_t a)
+ /// A32: VMOVN.I32 Dd+1, Qm
+ /// A64: XTN2 Vd.8H, Vn.4S
+ /// </summary>
+ public static Vector128<short> ExtractAndNarrowHigh (Vector64<short> lower, Vector128<int> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int32x4_t vmovn_high_s64 (int32x2_t r, int64x2_t a)
+ /// A32: VMOVN.I64 Dd+1, Qm
+ /// A64: XTN2 Vd.4S, Vn.2D
+ /// </summary>
+ public static Vector128<int> ExtractAndNarrowHigh (Vector64<int> lower, Vector128<long> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint8x16_t vmovn_high_u16 (uint8x8_t r, uint16x8_t a)
+ /// A32: VMOVN.I16 Dd+1, Qm
+ /// A64: XTN2 Vd.16B, Vn.8H
+ /// </summary>
+ public static Vector128<byte> ExtractAndNarrowHigh (Vector64<byte> lower, Vector128<ushort> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint16x8_t vmovn_high_u32 (uint16x4_t r, uint32x4_t a)
+ /// A32: VMOVN.I32 Dd+1, Qm
+ /// A64: XTN2 Vd.8H, Vn.4S
+ /// </summary>
+ public static Vector128<ushort> ExtractAndNarrowHigh (Vector64<ushort> lower, Vector128<uint> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint32x4_t vmovn_high_u64 (uint32x2_t r, uint64x2_t a)
+ /// A32: VMOVN.I64 Dd+1, Qm
+ /// A64: XTN2 Vd.4S, Vn.2D
+ /// </summary>
+ public static Vector128<uint> ExtractAndNarrowHigh (Vector64<uint> lower, Vector128<ulong> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
/// float32x2_t vfma_f32 (float32x2_t a, float32x2_t b, float32x2_t c)
/// A32: VFMA.F32 Dd, Dn, Dm
/// A64: FMLA Vd.2S, Vn.2S, Vm.2S
public static Vector64<float> DivideScalar(Vector64<float> left, Vector64<float> right) => DivideScalar(left, right);
/// <summary>
+ /// int8x8_t vmovn_s16 (int16x8_t a)
+ /// A32: VMOVN.I16 Dd, Qm
+ /// A64: XTN Vd.8B, Vn.8H
+ /// </summary>
+ public static Vector64<sbyte> ExtractAndNarrowLow (Vector128<short> value) => ExtractAndNarrowLow (value);
+
+ /// <summary>
+ /// int16x4_t vmovn_s32 (int32x4_t a)
+ /// A32: VMOVN.I32 Dd, Qm
+ /// A64: XTN Vd.4H, Vn.4S
+ /// </summary>
+ public static Vector64<short> ExtractAndNarrowLow (Vector128<int> value) => ExtractAndNarrowLow (value);
+
+ /// <summary>
+ /// int32x2_t vmovn_s64 (int64x2_t a)
+ /// A32: VMOVN.I64 Dd, Qm
+ /// A64: XTN Vd.2S, Vn.2D
+ /// </summary>
+ public static Vector64<int> ExtractAndNarrowLow (Vector128<long> value) => ExtractAndNarrowLow (value);
+
+ /// <summary>
+ /// uint8x8_t vmovn_u16 (uint16x8_t a)
+ /// A32: VMOVN.I16 Dd, Qm
+ /// A64: XTN Vd.8B, Vn.8H
+ /// </summary>
+ public static Vector64<byte> ExtractAndNarrowLow (Vector128<ushort> value) => ExtractAndNarrowLow (value);
+
+ /// <summary>
+ /// uint16x4_t vmovn_u32 (uint32x4_t a)
+ /// A32: VMOVN.I32 Dd, Qm
+ /// A64: XTN Vd.4H, Vn.4S
+ /// </summary>
+ public static Vector64<ushort> ExtractAndNarrowLow (Vector128<uint> value) => ExtractAndNarrowLow (value);
+
+ /// <summary>
+ /// uint32x2_t vmovn_u64 (uint64x2_t a)
+ /// A32: VMOVN.I64 Dd, Qm
+ /// A64: XTN Vd.2S, Vn.2D
+ /// </summary>
+ public static Vector64<uint> ExtractAndNarrowLow (Vector128<ulong> value) => ExtractAndNarrowLow (value);
+
+ /// <summary>
+ /// int8x16_t vmovn_high_s16 (int8x8_t r, int16x8_t a)
+ /// A32: VMOVN.I16 Dd+1, Qm
+ /// A64: XTN2 Vd.16B, Vn.8H
+ /// </summary>
+ public static Vector128<sbyte> ExtractAndNarrowHigh (Vector64<sbyte> lower, Vector128<short> value) => ExtractAndNarrowHigh (lower, value);
+
+ /// <summary>
+ /// int16x8_t vmovn_high_s32 (int16x4_t r, int32x4_t a)
+ /// A32: VMOVN.I32 Dd+1, Qm
+ /// A64: XTN2 Vd.8H, Vn.4S
+ /// </summary>
+ public static Vector128<short> ExtractAndNarrowHigh (Vector64<short> lower, Vector128<int> value) => ExtractAndNarrowHigh (lower, value);
+
+ /// <summary>
+ /// int32x4_t vmovn_high_s64 (int32x2_t r, int64x2_t a)
+ /// A32: VMOVN.I64 Dd+1, Qm
+ /// A64: XTN2 Vd.4S, Vn.2D
+ /// </summary>
+ public static Vector128<int> ExtractAndNarrowHigh (Vector64<int> lower, Vector128<long> value) => ExtractAndNarrowHigh (lower, value);
+
+ /// <summary>
+ /// uint8x16_t vmovn_high_u16 (uint8x8_t r, uint16x8_t a)
+ /// A32: VMOVN.I16 Dd+1, Qm
+ /// A64: XTN2 Vd.16B, Vn.8H
+ /// </summary>
+ public static Vector128<byte> ExtractAndNarrowHigh (Vector64<byte> lower, Vector128<ushort> value) => ExtractAndNarrowHigh (lower, value);
+
+ /// <summary>
+ /// uint16x8_t vmovn_high_u32 (uint16x4_t r, uint32x4_t a)
+ /// A32: VMOVN.I32 Dd+1, Qm
+ /// A64: XTN2 Vd.8H, Vn.4S
+ /// </summary>
+ public static Vector128<ushort> ExtractAndNarrowHigh (Vector64<ushort> lower, Vector128<uint> value) => ExtractAndNarrowHigh (lower, value);
+
+ /// <summary>
+ /// uint32x4_t vmovn_high_u64 (uint32x2_t r, uint64x2_t a)
+ /// A32: VMOVN.I64 Dd+1, Qm
+ /// A64: XTN2 Vd.4S, Vn.2D
+ /// </summary>
+ public static Vector128<uint> ExtractAndNarrowHigh (Vector64<uint> lower, Vector128<ulong> value) => ExtractAndNarrowHigh (lower, value);
+
+ /// <summary>
/// float32x2_t vfma_f32 (float32x2_t a, float32x2_t b, float32x2_t c)
/// A32: VFMA.F32 Dd, Dn, Dm
/// A64: FMLA Vd.2S, Vn.2S, Vm.2S
public static System.Runtime.Intrinsics.Vector64<uint> CompareTest(System.Runtime.Intrinsics.Vector64<uint> left, System.Runtime.Intrinsics.Vector64<uint> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<double> DivideScalar(System.Runtime.Intrinsics.Vector64<double> left, System.Runtime.Intrinsics.Vector64<double> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<float> DivideScalar(System.Runtime.Intrinsics.Vector64<float> left, System.Runtime.Intrinsics.Vector64<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<sbyte> ExtractAndNarrowLow (System.Runtime.Intrinsics.Vector128<short> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<short> ExtractAndNarrowLow (System.Runtime.Intrinsics.Vector128<int> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<int> ExtractAndNarrowLow (System.Runtime.Intrinsics.Vector128<long> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<byte> ExtractAndNarrowLow (System.Runtime.Intrinsics.Vector128<ushort> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<ushort> ExtractAndNarrowLow (System.Runtime.Intrinsics.Vector128<uint> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<uint> ExtractAndNarrowLow (System.Runtime.Intrinsics.Vector128<ulong> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<sbyte> ExtractAndNarrowHigh (System.Runtime.Intrinsics.Vector64<sbyte> lower, System.Runtime.Intrinsics.Vector128<short> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<short> ExtractAndNarrowHigh (System.Runtime.Intrinsics.Vector64<short> lower, System.Runtime.Intrinsics.Vector128<int> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<int> ExtractAndNarrowHigh (System.Runtime.Intrinsics.Vector64<int> lower, System.Runtime.Intrinsics.Vector128<long> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<byte> ExtractAndNarrowHigh (System.Runtime.Intrinsics.Vector64<byte> lower, System.Runtime.Intrinsics.Vector128<ushort> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<ushort> ExtractAndNarrowHigh (System.Runtime.Intrinsics.Vector64<ushort> lower, System.Runtime.Intrinsics.Vector128<uint> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<uint> ExtractAndNarrowHigh (System.Runtime.Intrinsics.Vector64<uint> lower, System.Runtime.Intrinsics.Vector128<ulong> value) { throw null; }
public static System.Runtime.Intrinsics.Vector128<float> FusedMultiplyAdd(System.Runtime.Intrinsics.Vector128<float> acc, System.Runtime.Intrinsics.Vector128<float> left, System.Runtime.Intrinsics.Vector128<float> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<float> FusedMultiplyAdd(System.Runtime.Intrinsics.Vector64<float> acc, System.Runtime.Intrinsics.Vector64<float> left, System.Runtime.Intrinsics.Vector64<float> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<double> FusedMultiplyAddNegatedScalar(System.Runtime.Intrinsics.Vector64<double> acc, System.Runtime.Intrinsics.Vector64<double> left, System.Runtime.Intrinsics.Vector64<double> right) { throw null; }